30行脚本最终可以为Laravel应用中的存储库模式提供一个很好的解决方案。
问题
Laravel提供了一种通过Eloquent(对象关系映射)查询数据库的漂亮方法。 您的项目变大的那一刻开始出现问题。 实体和模型之间的差异开始变得模糊。 让我举一个例子:
我们有两种方法,一种叫做findByName
,另一种叫做concatName
。
<?php
namespace App ;
use Illuminate \ Database \ Eloquent \ Model ;
class Product extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'products' ;
/**
* Find published product by name
* @param string $name
* @return Product
*/
public function findByName (string $name) : Product
{
return $this ->whereName($name)
->whereIsPublished( 1 )
->first();
}
/**
* Say we want to concat the name and a category name
* @return string
*/
public function concatName () : string
{
return $this ->attributes[ 'name' ] . ' - ' . $this ->attributes[ 'category_name' ];
}
}
我们实际上在这里所做的是将用于检索(集合)产品的方法与用于1个产品实例的方法混合在一起。
一种更干净的方法是将它们分为两个不同的类。 一种用于获取模型的实例和集合,另一种用于模型定义本身。 您可以将其称为存储库模式。
分为2类
Laravel有几个库可以开始使用存储库模式。 对我来说,一个很大的缺点是您不能在存储库上使用Eloquent函数。 由于Eloquent是我使用Laravel的重要原因,所以我仍然希望能够在存储库上使用Eloquent来获取模型。
解决方案
我创建了一个非常简单的代码,可以在您的存储库中启用Eloquent的所有功能 。 这样,您就可以以一种有趣的方式使用存储库模式,并保持模型和存储库的清洁! 使用laravel-repositories
如下所示:
<?php
namespace App \ Repositories ;
use App \ Models \ Product ;
use MrAtiebatie \ Repository ;
use Illuminate \ Database \ Eloquent \ Model ;
/**
* Product repository
*/
class ProductRepository extends Model
{
use Repository ;
/**
* The model being queried.
*
* @var \Illuminate\Database\Eloquent\Model
*/
protected $model;
/**
* Constructor
*/
public function __construct ()
{
$this ->model = app(Product::class);
}
/**
* Find published products by SKU
* @param {int} $sku
* @return {Product}
*/
public function findBySku (int $sku) : Product {
return this->whereIsPublished( 1 )
->whereSku($sku)
->first();
}
}
通过使用存储库特征和$model
属性, laravel-repositories
知道要查询的模型,在哪里使用Eloquent以及在哪里使用您自己的存储库方法。
有了存储库的此定义,我们现在可以在控制器,作业,命令等中使用它:
<?php
/**
* In your routes/web.php
*/
$router->get( '/' , function (\App\Repositories\ProductRepository $productRepo) {
// Use any Eloquent feature directly
$productRepo->all()->dd();
// Use your custom repository methods
echo $productRepo->findBySku( 12345 )->name;
// You can even query relations
echo $productRepo->first()->category;
});
去尝试一下,给我一些改进的反馈!
我目前正在使用Laravel Pigeon,这是一个用于与您的用户进行通信和调试通知的通知中心。 注册抢先体验!
From: https://hackernoon.com/the-best-laravel-repositories-solution-in-30-lines-of-code-ee1553z31