neat / object
Neat Object 组件
Requires
- php: ^7.2 || ^8.0
- neat/database: ^1.5
- psr/event-dispatcher: ^1.0
Requires (Dev)
- ext-sqlite3: *
- phpunit/phpunit: ^8.0 || ^9.0
- dev-master / 0.12.x-dev
- 0.11.x-dev
- 0.11.17
- 0.11.16
- 0.11.15
- 0.11.14
- 0.11.13
- 0.11.12
- 0.11.11
- 0.11.10
- 0.11.9
- 0.11.8
- 0.11.7
- 0.11.6
- 0.11.5
- 0.11.4
- 0.11.3
- 0.11.2
- 0.11.1
- 0.11.0
- 0.10.x-dev
- 0.10.1
- 0.10.0
- 0.9.5
- 0.9.4
- 0.9.3
- 0.9.2
- 0.9.1
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.0
- 0.5.1
- 0.5.0
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
- dev-feature/psalm
- dev-feature/order-by
- dev-feature/serializable-rebased
- dev-fix/34-datetime-zero
- dev-refactor/namespace-rebase
- dev-refactor/namespaces
- dev-feature/serializable-74
- dev-feature/serializable
This package is auto-updated.
Last update: 2024-09-04 13:38:12 UTC
README
Neat object 组件在 Neat 数据库组件之上添加了一个简单直观的 ORM 层。
入门指南
要安装此包,请在命令行中简单执行 composer
composer require neat/object
然后初始化对象管理器
<?php // Initialize the manager using a database connection and an object policy $pdo = new PDO('mysql:host=localhost;charset=utf8mb4;dbname=test', 'username', 'password'); $connection = new Neat\Database\Connection($pdo); $policy = new Neat\Object\Policy(); $manager = new Neat\Object\Manager($connection, $policy); // If you want easy access to static methods, set the Manager instance Neat\Object\Manager::set($manager); // Or set a factory that connects to the database only when needed Neat\Object\Manager::setFactory(function () { $pdo = new PDO('dsn', 'username', 'password'); $connection = new Neat\Database\Connection($pdo); $policy = new Neat\Object\Policy(); return new Neat\Object\Manager($connection, $policy); });
创建实体
实体可以是普通的 PHP 对象
class User { /** @var int */ public $id; /** @var string */ public $name; }
要将这些实体持久化到数据库中,我们可以使用存储库
$repository = Neat\Object\Manager::get()->repository(User::class); $user = new User(); $user->name = 'John'; $repository->store($user); echo $user->id; // 1
按标识符查找
如果您知道实体的标识符,您可以使用 has
和 get
方法来访问它。
$repository = Neat\Object\Manager::get()->repository(User::class); // Get the user at once $user = $repository->get(1); // Returns user with id 1 or null if not found // Or just check if it exists if (!$repository->has(1)) { throw new Exception('boohoo'); }
要使用复合主键从表中查找实体,应将标识符作为数组传递。
使用查询查找
存储库允许您以多种方式查询实体
one
返回一个实体(如果没有匹配则返回 null)all
返回与查询匹配的所有实体作为数组collection
返回包含匹配实体的集合实例iterate
返回一个生成器,允许您遍历匹配的实体select
返回一个可变的查询构建器,允许链式调用上述任何方法sql
返回一个使用手写 SQL 查询(作为字符串提供)的查询对象
这些方法中的每一种都可以以多种方式传递查询
$repository = Neat\Object\Manager::get()->repository(User::class); // Find one user with name John (note the [key => value] query array) $user = $repository->one(['name' => 'John']); // Find all users that have been deleted (the query is an SQL where clause) $user = $repository->all('deleted = 1'); // Find all users using a complex query $administrators = $repository ->select('u') ->innerJoin('user_group', 'ug', 'u.id = ug.user_id') ->innerJoin('group', 'g', 'g.id = ug.group_id') ->where('g.name = ?', 'administrators') ->orderBy('u.name') ->all(); // Get one user using your own SQL query $user = $repository->sql('SELECT * FROM users WHERE id = ?', 1)->one(); // Or multiple in an array $active = $repository->sql('SELECT * FROM users WHERE deleted = 0')->all();
使用静态访问查找
为了防止在代码中到处都是管理器和存储库实例,您可以使用 Storage
特性以允许静态存储库访问
class User { use Neat\Object\Storage; /** @var int */ public $id; /** @var string */ public $name; } // The Storage trait gives you static access to repository methods $user = User::get(1); $users = User::all(); $latest = User::select()->orderBy('created_at DESC')->one(); foreach (User::iterate() as $user) { $user->greet(); }
关系
如果您需要关系,只需使用 Relations
特性,它提供了一组用于 hasOne/-Many 和 belongsToOne/-Many 关系的工厂函数。
class User { use Neat\Object\Storage; use Neat\Object\Relations; public function address(): Neat\Object\Relations\One { return $this->hasOne(Address::class); } } $user = User::one(...); // Returns the address object for the user or null $address = $user->address()->get(); // Relations are automatically stored when the parent model is stored: $address = new Address(); $user->address()->set($address); $user->store(); // Stores the user // Sets the Address::$userId // Stores the address
当您对同一类有多个关系时,请确保使用第二个参数为每个关系分配一个唯一角色,以避免它们之间的冲突
class Appointment { use Neat\Object\Storage; use Neat\Object\Relations; public function createdBy(): Neat\Object\Relations\One { return $this->belongsToOne(User::class, 'creator'); } public function updatedBy(): Neat\Object\Relations\One { return $this->belongsToOne(User::class, 'updater'); } }
引用
用于每个关系的列名和表名使用由 Policy
确定的默认值。当这些默认值不适用时,您可以通过将配置闭包作为第三个参数传递给您选择的任何关系方法来覆盖它们
class AgendaLine { use Neat\Object\Storage; /** @var int */ public $id; /** @var int */ public $appointmentId; /** @var string */ public $description; } class User { use Neat\Object\Storage; /** @var int */ public $id; /** @var int */ public $alternativeId; } class Appointment { use Neat\Object\Storage; use Neat\Object\Relations; /** @var int */ public $id; /** @var int */ public $createdBy; public function creator(): Neat\Object\Relations\One { // Pass reference configuration to belongsToOne as // callable(LocalKeyBuilder) return $this->belongsToOne(User::class, 'creator', function (Neat\Object\Relations\Reference\LocalKeyBuilder $builder) { // Use the local property name $builder->setLocalKey('createdBy'); // Or alternatively, the local column name $builder->setLocalKeyColumn('created_by'); // Set the remote property name $builder->setRemoteKey('alternativeId'); // Or alternatively, the remote column name $builder->setRemoteKeyColumn('alternative_id'); }); } public function agendaLines(): Neat\Object\Relations\Many { // Pass reference configuration to hasOne and hasMany as // callable(RemoteKeyBuilder) return $this->hasMany(AgendaLine::class, 'agenda', function (Neat\Object\Relations\Reference\RemoteKeyBuilder $builder) { // The same local and remote key setters as with belongsToOne // can be used with hasMany and hasOne relations. }); } public function attendees(): Neat\Object\Relations\Many { // Pass reference configuration to belongsToMany as // callable(JunctionTableBuilder) return $this->belongsToMany(User::class, 'attendees', function (Neat\Object\Relations\Reference\JunctionTableBuilder $builder) { // Set the junction table name and column names in addition to // the same local and remote key setters as with belongsToOne. $builder->setJunctionTable('appointment_attendee'); $builder->setJunctionTableLocalKeyColumn('appointment_id'); $builder->setJunctionTableRemoteKeyColumn('attendee_id'); // Please note that the junction table doesn't have an entity // class. Therefore you cannot use class and property names. }); } }
访问器
访问器方法允许您直接在实体对象上调用 add
、all
、has
、get
、remove
、select
和 set
等方法
class UserAccount { use Neat\Object\Storage; use Neat\Object\Relations; // Use the Accessors trait to add accessor methods use Neat\Object\Accessors; public function address(): Neat\Object\Relations\One { return $this->belongsToOne(Address::class); } public function roles(): Neat\Object\Relations\Many { return $this->belongsToMany(Role::class); } } $user = UserAccount::one(...); $user->getAddress(); // same as $user->address()->get(); $user->setAddress(...); // same as $user->address()->set(...); $user->addRole(...); // same as $user->roles()->add(...); $user->hasRole(...); // same as $user->roles()->has(...); $user->deleteRole(...); // same as $user->roles()->delete(...); $user->getRoles(); // same as $user->roles()->get(); $user->selectRoles(); // same as $user->roles()->select();
将 $user->addRole()
转换为 $user->roles()->add()
是由 Policy 完成的。在其构造函数中,您可以为提供复数化函数,以允许进行适当的转换
// Use the Policy with custom $pluralize function to initialize your Manager $policy = new Neat\Object\Policy(null, function (string $singular): string { return $singular . 's'; // lousy way of pluralizing relation names });
集合
集合包装了多个项的数组,并提供了一种链式方式来使用多个操作访问这些项。对类多个实例的关系(hasMany 和 belongsToMany)提供了相同的 Collectible
API
class User { use Neat\Object\Storage; use Neat\Object\Relations; public function roles(): Neat\Object\Relations\Many { return $this->belongsToMany(Role::class); } } $user = User::one(...); // Both of these offer the Collectible API $roles = Role::collection(); $roles = $user->roles(); // Get all roles, the first or the last role $all = $user->roles()->all(); $first = $user->roles()->first(); $last = $user->roles()->last(); // Count roles $count = $user->roles()->count(); // Get a filtered collection of roles $filtered = $user->roles()->filter(function (Role $role) { return !$role->invisible; }); // Get a sorted collection of roles $sorted = $user->roles()->sort(function (Role $a, Role $b) { return $a->name <=> $b->name; }); // Map roles and get the results in a collection $names = $user->roles()->map(function (Role $role) { return $role->name; }); // Or get the values of a single property in a collection $names = $user->roles()->column('name'); // Chain multiple collection functions, then get an array of roles $result = $user->roles()->filter(...)->sort(...)->all();