30-строчный фрагмент скрипта может наконец обеспечить хорошее решение для шаблона репозитория в приложениях Laravel.
Проблема
Laravel предоставляет прекрасный способ запроса вашей базы данных с помощью Eloquent, Object Relational Mapping. В тот момент, когда ваш проект становится больше, возникает проблема. Разница между сущностями и моделями начинает расплываться. Позвольте привести пример:
У нас есть два метода, один называется 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 разных класса. Один для получения экземпляров и коллекций моделей и один для определения самой модели. Вы можете назвать это шаблоном хранилища.
Разделение на 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();
}
}
Используя черту Repository и $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;
});
0 комментариев
Добавить комментарий