PHP code example of migears / domain

1. Go to this page and download the library: Download migears/domain library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

migears / domain example snippets


use MiGears\Domain\DataAccess;

class UserDomain
{
    use DataAccess;

    public function __construct(
        public readonly int $id,
        public readonly string $user_name,
        public readonly string $email,
        public readonly int $age,
        public readonly string $created_at,
    ) {}
}

// From a database row
$row = ['id' => 1, 'user_name' => 'Alice', 'email' => '[email protected]', 'age' => 25, 'created_at' => '2024-01-01'];

$user = UserDomain::fromArray($row);
echo $user->user_name;  // "Alice"

$row = $user->toArray();
// ['id' => 1, 'user_name' => 'Alice', 'email' => '[email protected]', 'age' => 25, 'created_at' => '2024-01-01']

$domain = UserDomain::fromArray($row);
$back = $domain->toArray();
// $back === $row  ✅  (same key order)

$user = UserDomain::fromArray($row);            // ['id'=>1,'user_name'=>'Alice','email'=>'[email protected]',...]
$renamed = $user->with(['user_name' => 'Bob']); // new object; $user is untouched

$renamed->user_name;  // "Bob"
$user->user_name;     // "Alice" — original unchanged

$dao->update($user->with(['user_name' => 'Bob'])->toArray());

final class OrderManager
{
    public function __construct(private OrderItemDao $itemDao)
    {
        OrderDomain::setItemLoader(
            fn(OrderDomain $order) => $this->itemDao->getByOrderId($order->id)
        );
    }
}

use Closure;
use MiGears\Domain\DataAccess;
use RuntimeException;

class OrderDomain
{
    use DataAccess;

    /** @var null|Closure(self): list<OrderItemDomain> */
    private static ?Closure $itemLoader = null;

    public function __construct(
        public readonly int $id,
        public readonly string $title,
    ) {}

    public static function setItemLoader(?callable $loader): void
    {
        static::$itemLoader = $loader === null ? null : Closure::fromCallable($loader);
    }

    /** @return list<OrderItemDomain> */
    public function items(): array
    {
        if (static::$itemLoader === null) {
            throw new RuntimeException('OrderDomain::setItemLoader() was not called');
        }

        return (static::$itemLoader)($this);
    }
}

$order = OrderDomain::fromArray($row);
$order->items();     // loaded through the Manager's callable
$order->toArray();   // ['id' => ..., 'title' => ...] — loader not 

use MiGears\Domain\DataAccess;
use MiGears\Domain\Validatable;

class UserDomain
{
    use DataAccess;
    use Validatable;

    public function __construct(
        public readonly string $username,
        public readonly string $email,
        public readonly int $age = 0,
    ) {}

    protected static function validationRules(): array
    {
        return [
            'username' => ['

$user = new UserDomain('ab', 'invalid', -1);

$errors = $user->validate();
// [
//   'username' => ['rule' => 'minLength', 'params' => ['min' => 3]],
//   'email'    => ['rule' => 'email', 'params' => []],
//   'age'      => ['rule' => 'min', 'params' => ['min' => 0]],
// ]

$user->isValid(); // false

$errors = UserDomain::validateArray($_POST);

if ($errors === []) {
    $user = UserDomain::fromArray($_POST);
}

use MiGears\Validator\RuleInterface;

final class StrengthRule implements RuleInterface
{
    public function __construct(private int $min = 8) {}
    public function validate(mixed $value): bool
    {
        return is_string($value) && strlen($value) >= $this->min;
    }
    public function getErrorCode(): string { return 'strength'; }
    public function getErrorParams(): array { return ['min' => $this->min]; }
}

UserDomain::register(StrengthRule::class);

// in validationRules():
'password' => ['strength' => 12],   // → new StrengthRule(12)
'pin'      => ['strength' => 4],    // → new StrengthRule(4)

use Closure;
use MiGears\Validator\RuleInterface;

final class UniqueEmailRule implements RuleInterface
{
    /** @param Closure(string): bool $emailExists */
    public function __construct(private Closure $emailExists) {}

    public function validate(mixed $value): bool
    {
        return $value === null || $value === ''
            || !($this->emailExists)((string) $value);
    }

    public function getErrorCode(): string { return 'uniqueEmail'; }
    public function getErrorParams(): array { return []; }
}

final class UserManager
{
    public function __construct(private UserDao $dao)
    {
        UserDomain::register(
            new UniqueEmailRule(fn (string $email) => $this->dao->existsByEmail($email))
        );
    }
}

'email' => ['

['field' => ['rule' => 'minLength', 'params' => ['min' => 3]]]

$message = $translator->translate(
    "validation.{$error['rule']}",
    ['field' => $fieldLabel, ...$error['params']]
);

use MiGears\Domain\DataAccess;

class UserDomain
{
    use DataAccess;

    public function __construct(
        public readonly int $id,
        public readonly string $user_name,
        public readonly string $email,
        public readonly int $age,
        public readonly string $created_at,
    ) {}
}

// 从数据库行构造
$row = ['id' => 1, 'user_name' => 'Alice', 'email' => '[email protected]', 'age' => 25, 'created_at' => '2024-01-01'];

$user = UserDomain::fromArray($row);
echo $user->user_name;  // "Alice"

$row = $user->toArray();
// ['id' => 1, 'user_name' => 'Alice', 'email' => '[email protected]', 'age' => 25, 'created_at' => '2024-01-01']

$domain = UserDomain::fromArray($row);
$back = $domain->toArray();
// $back === $row  ✅  (键序一致时)

$user = UserDomain::fromArray($row);            // ['id'=>1,'user_name'=>'Alice','email'=>'[email protected]',...]
$renamed = $user->with(['user_name' => 'Bob']); // 新对象;$user 不变

$renamed->user_name;  // "Bob"
$user->user_name;     // "Alice" —— 原对象不受影响

$dao->update($user->with(['user_name' => 'Bob'])->toArray());

final class OrderManager
{
    public function __construct(private OrderItemDao $itemDao)
    {
        OrderDomain::setItemLoader(
            fn(OrderDomain $order) => $this->itemDao->getByOrderId($order->id)
        );
    }
}

use Closure;
use MiGears\Domain\DataAccess;
use RuntimeException;

class OrderDomain
{
    use DataAccess;

    /** @var null|Closure(self): list<OrderItemDomain> */
    private static ?Closure $itemLoader = null;

    public function __construct(
        public readonly int $id,
        public readonly string $title,
    ) {}

    public static function setItemLoader(?callable $loader): void
    {
        static::$itemLoader = $loader === null ? null : Closure::fromCallable($loader);
    }

    /** @return list<OrderItemDomain> */
    public function items(): array
    {
        if (static::$itemLoader === null) {
            throw new RuntimeException('OrderDomain::setItemLoader() was not called');
        }

        return (static::$itemLoader)($this);
    }
}

$order = OrderDomain::fromArray($row);
$order->items();     // 经 Manager 注入的 callable 加载
$order->toArray();   // ['id' => ..., 'title' => ...] —— 不含 loader

use MiGears\Domain\DataAccess;
use MiGears\Domain\Validatable;

class UserDomain
{
    use DataAccess;
    use Validatable;

    public function __construct(
        public readonly string $username,
        public readonly string $email,
        public readonly int $age = 0,
    ) {}

    protected static function validationRules(): array
    {
        return [
            'username' => ['

$user = new UserDomain('ab', 'invalid', -1);

$errors = $user->validate();
// [
//   'username' => ['rule' => 'minLength', 'params' => ['min' => 3]],
//   'email'    => ['rule' => 'email', 'params' => []],
//   'age'      => ['rule' => 'min', 'params' => ['min' => 0]],
// ]

$user->isValid(); // false

$errors = UserDomain::validateArray($_POST);

if ($errors === []) {
    $user = UserDomain::fromArray($_POST);
}

use MiGears\Validator\RuleInterface;

final class StrengthRule implements RuleInterface
{
    public function __construct(private int $min = 8) {}
    public function validate(mixed $value): bool
    {
        return is_string($value) && strlen($value) >= $this->min;
    }
    public function getErrorCode(): string { return 'strength'; }
    public function getErrorParams(): array { return ['min' => $this->min]; }
}

UserDomain::register(StrengthRule::class);

// validationRules() 里:
'password' => ['strength' => 12],   // → new StrengthRule(12)
'pin'      => ['strength' => 4],    // → new StrengthRule(4)

use Closure;
use MiGears\Validator\RuleInterface;

final class UniqueEmailRule implements RuleInterface
{
    /** @param Closure(string): bool $emailExists */
    public function __construct(private Closure $emailExists) {}

    public function validate(mixed $value): bool
    {
        return $value === null || $value === ''
            || !($this->emailExists)((string) $value);
    }

    public function getErrorCode(): string { return 'uniqueEmail'; }
    public function getErrorParams(): array { return []; }
}

final class UserManager
{
    public function __construct(private UserDao $dao)
    {
        UserDomain::register(
            new UniqueEmailRule(fn (string $email) => $this->dao->existsByEmail($email))
        );
    }
}

'email' => ['

['字段名' => ['rule' => 'minLength', 'params' => ['min' => 3]]]

$message = $translator->translate(
    "validation.{$error['rule']}",
    ['field' => $fieldLabel, ...$error['params']]
);

PDO(PHP 8.1+)→ 原生 PHP 类型(int、float、string、null)
             ↓
  Domain::fromArray() 仅按参数名绑定(不 hydration、不强制转换)