foothing / laravel-repository
此包为 Laravel 5 提供了仓库模式的实现。
Requires
- php: >=5.4.0
- illuminate/database: ~5.0
- illuminate/support: ~5.0
Requires (Dev)
- codeclimate/php-test-reporter: dev-master
- mockery/mockery: 0.9.*
- orchestra/testbench: ~3.0
- phpunit/phpunit: 4.*
This package is auto-updated.
Last update: 2024-09-23 00:00:23 UTC
README
此包为 Laravel 5 提供了仓库模式的实现。
Composer 安装
composer require foothing/laravel-repository
基本用法
此包包含仓库接口定义和 Eloquent
实现。 EloquentRepository
已准备好使用。
// Make a repository instance manually $repository = new EloquentRepository(new Post());
现在你已经准备好了
// Find first occurrence with matching field 'email' $repository->findOneBy('email', 'test@example.com'); // Find first occurrence where id > 1 $repository->findOneBy('id', '1', '>'); // Find where title starts with 'foo' $repository->findAllBy('title', 'foo%', 'like'); // Find all occurrences where id > 1 $repository->findAllBy('id', '1', '>'); // Returns all posts $repository->all(); // Returns all post with Laravel pagination format $repository->paginate(); // Return record count $repository->filter('name', 'Homer')->count(); // Create, update and delete instances. $model = new Post(Input::all()); $freshMoel = $repository->create($model); $updatedModel = $repository->update($model); $repository->delete($model);
如果你想通过自定义方法扩展基本实现,你需要扩展基本类,并定义一个构造函数,将 Eloquent
模型作为第一个参数。
class PostsRepository extends EloquentRepository { function __construct(Post $post) { // Call superclass constructor. parent::construct($post); } function customFancyMethod() { } }
不要忘记调用超类构造函数,以启用所有开箱即用的功能。你还可以在重写基本构造函数时添加额外的依赖。
class PostsRepository extends AbstractEloquentRepository { function __construct(Post $post, AnotherDependency $dependency) { parent::construct($post); // Do whatever you like with your $dependency } }
现在一切都准备好了。示例
// Use with a dependency injector class PostsController { protected $posts; function __construct(PostsRepository $posts) { $this->posts = $posts; } function getIndex($id = null) { // Return one post by primary key return $this->posts->find($id); } }
预加载关系
你可以使用 with
方法来预加载数据库关系
$posts = $repository->with(['author', 'comments'])->all(); Output: [ { "id": 1, "title": "Post title", "author": { "id": 1, "email": "test@example.com" }, "comments": [ {"id": 1, "text": "a comment"}, {"id": 2, "text": "another comment"}, ], } ]
你可以将 with
方法链接到所有可用方法
$posts = $repository->with(['author', 'comments'])->findOneBy('name', 'foo'); $posts = $repository->with(['author', 'comments'])->all(); // And so on.
你通常会默认预加载数些关系。假设你有一个具有与 Role 模型多对多关系的 User 模型,并且你想要获取用户信息和角色。
Foothing\Resources\Resource
接口有三个方法,用于定义默认模型行为
- 为 findOne 操作默认预加载哪些关系
- 为 findMany 操作默认预加载哪些关系
- 在保存时要跳过哪些字段
class User extends Model implements Foothing\Resources\Resource { /** * Array of relations we want to eager-load when * a single entity is being fetched. * * @return array */ function unitRelations() { return ['roles', 'posts']; } /** * Array of relations we want to eager-load when * a list of entities is being fetched. * * @return array */ function listRelations() { return ['roles']; } /** * When the resource is sent in a json-encoded * format it may happen to have relations fields * populated. Since they would be set as stdClass * objects we need to unset them before save. * * This method should return an array with all relations * we want to be unset when processing the updates. * * @return array */ function skipOnSave() { return ['roles', 'posts']; } }
这样,每次使用你的 UserRepository 时,以下行为将是默认的
$users->find($id); // will eager load *roles* and *posts* $users->findOneBy($id); // will eager load *roles* and *posts* $users->create(); // will eager load *roles* and *posts* $users->update(); // will eager load *roles* and *posts* $users->all(); // will eager load *roles* $users->paginate(); // will eager load *roles*
如果你显式使用 with
方法,则将忽略此默认行为。
skipOnSave
方法在处理 JSON 对象时很有用,因为当你读取资源,然后在客户端上对其进行处理,然后将它发送回服务器时,它将包含关系属性。这些属性将被转换为 stdClass PHP 对象,从而破坏 Eloquent 保存方法。
条件
你可以使用 CriteriaInterface
应用筛选器和排序约束,该接口也包含一个 Eloquent
实现。
用法
$criteria = new \Foothing\Repository\Eloquent\EloquentCriteria(); $criteria->filter('name', 'Homer'); $criteria->filter('lastName', 'Simpson'); // Chain methods $criteria->order('name')->sort('asc'); $repository->criteria($criteria)->paginate();
仓库提供了可以在链中使用的快捷方法。以下示例产生的效果与上一个示例相同。
$repository ->filter('name', 'Homer') ->filter('lastName', 'Simpson') ->order('name') ->sort('asc') ->paginate();
可用筛选器
// Defaults to '=' $criteria->filter('name', 'Homer'); $criteria->filter('name', 'Home%', 'like'); $criteria->filter('id', 1, '>'); $criteria->filter('id', 1', '>='); $criteria->filter('id', 1, '<'); $criteria->filter('id', 1, '<='); $criteria->filter('id', 1, '!='); $criteria->filter('lastName', 'Simpson,Nahasapeemapetilon', 'in');
你可以使用逗号分隔的值列表或值数组与 in 操作符一起使用。
$criteria->filter('lastName', 'Simpson,Nahasapeemapetilon', 'in'); $criteria->filter('lastName', ['Simpson', 'Nahasapeemapetilon'], 'in');
嵌套筛选器
你也可以查询模型关系。假设你的 Eloquent 模型定义了一个类似这样的 children
关系
class Foo extends Model { protected $table = 'foo'; public function children() { return $this->hasMany('Bar'); } }
在这种情况下,你将被允许查询 children
值
$criteria->filter('children.name', 'Bar');
请注意,受条件限制的方法是所有获取多个记录的方法。
多对多关联的附加和分离
给定以下 Model
class Homer extends Model { public function roles() { return $this->hasMany('Role'); } }
你可以使用 attach()
和 detach()
方法将关联附加到/从关联中分离。
$homer = Homer::find(1); $foodCritic = Role::find(1); $repository->attach($homer, 'roles', $foodCritic); $repository->detach($homer, 'roles', $foodCritic);
作用域
你可以使用 scope()
方法插入你的模型作用域。
// Model class Person extends Model { public function scopeMale($query) { return $query->where('sex', 'male'); } } // Usage in Repository $malePeople = $repository->scope('male')->all(); $malePeople = $repository->scope('male')->filter('name', 'Bart')->all(); $malePeople = $repository->scope('male')->paginate(); $malePeople = $repository->scope('male')->findAllBy('name', 'John');
作用域只应用于读取方法。
全局作用域
你可以为每个仓库实现定义一个全局作用域,这可能会在全局范围内限制记录访问。
只需在你的仓库中设置
protected $globalScope = 'whatever';
全局作用域必须与 Eloquent 作用域匹配。请注意,如果你使用显式作用域,即 $repository->scope('male')
,则将忽略全局作用域。
仓库 API
<?php namespace Foothing\Repository; interface RepositoryInterface { // // // Crud. // // public function find($id); public function findOneBy($field, $arg1, $arg2 = null); public function findAllBy($field, $arg1, $arg2 = null); public function all(); public function paginate($limit = null, $offset = null); public function count(); public function create($entity); public function update($entity); public function delete($entity); // // // Eager loading. // // public function with(array $relations); // // // Relations. // // /** * Attach $relatedEntity and $entity in a many-to-many relation. * * @param Model $entity * @param string $relation * @param Model $relatedEntity * * @return Model the updated $entity */ public function attach($entity, $relation, $relatedEntity); /** * Detach $entity and $relatedEntity in a many-to-many relation. * * @param Model $entity * @param string $relation * @param Model $relatedEntity * * @return Model the updated $entity */ public function detach($entity, $relation, $relatedEntity); // // // Criteria shortcuts. // // public function criteria(CriteriaInterface $criteria); public function filter($field, $value, $operator = '='); public function order($field, $sort = null); public function sort($direction); // // // Scopes. // // public function scope($scope); // // // Helpers. // // /** * Forces the next read query to skip cached values. * @return self */ public function refresh(); /** * Reset the refresh flag. * @return self */ public function reset(); }
远程查询
更多信息即将推出。