touhidurabir/laravel-model-repository

用于实现Laravel模型仓库模式的包

1.1.3 2021-10-27 06:48 UTC

This package is auto-updated.

Last update: 2024-08-27 13:10:45 UTC


README

一个简单的包,用于为Laravel模型使用仓库模式

仓库模式

仓库是封装访问数据源所需逻辑的类或组件。它们集中了常见的数据访问功能,提供了更好的可维护性,并从领域模型层解耦了用于访问数据库的基础设施或技术。 Microsoft

安装

使用Composer安装包

composer require touhidurabir/laravel-model-repository

发布配置文件

php artisan vendor:publish --provider="Touhidurabir\ModelRepository\ModelRepositoryServiceProvider" --tag=config

命令和配置

要使用此包,您需要将仓库类绑定到Laravel模型类。此包包含一个命令,可以从命令行轻松创建仓库类。要创建一个新的仓库类,运行以下命令

php artisan make:repository UserRepository --model=User

上述命令将在 App\Repositories 路径下创建一个新的 UserRepository 类。使用 --model 选项定义要针对此仓库类的Laravel模型类。 UserRepository 的内容将类似于

namespace App\Repositories;

use Touhidurabir\ModelRepository\BaseRepository;
use App\Models\User;

class UserRepository extends BaseRepository {

	/**
     * Constructor to bind model to repo
     *
     * @param  object<App\Models\User> $user
     * @return void
     */
    public function __construct(User $user) {

        $this->model = $user;

        $this->modelClass = get_class($user);
    }

}

默认情况下,此包假设所有 模型 都位于路径 App\Models,并使用路径 App\Repositories 来存储仓库类。但也可能提供自定义仓库类路径和不同的模型类路径。例如

php artisan make:repository App\\SomeOtherPath\\UserRepository --model=App\\OtherModelPath\\User

上述命令将尝试将仓库类存储到路径 App\SomeOtherPath,并在不存在的情况下创建名为 SomeOtherPath 的目录。它还将尝试从 App\OtherModelPath 解析模型路径/命名空间。

在发布后检查 config 文件,在 config/model-repository.php 中查看默认设置配置。

也可以通过传递标志 --replace 通过命令替换现有的仓库文件。

php artisan make:repository UserRepository --model=User --replace

上述命令将用新创建的一个替换给定路径上已经存在的 UserRepository.php

请务必小心替换功能,因为如果您的仓库类包含任何自定义代码,它将被完全替换为新创建的文件,并且这些自定义更改将会丢失。

使用方法

通过控制器类通过 依赖注入 使用仓库类是最佳方式。例如

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;

class UserController extends Controller {

    /**
     * The resource repository instance
     *
     * @var mixed<object{\App\Repositories\UserRepository}|null>
     */
    protected $userRepository;

	/**
     * create a new controller instance
     *
     * @param  \App\Repositories\UserRepository         $userRepository
     * @return void
     */
    public function __construct(UserRepository $userRepository) {

        $this->userRepository = $userRepository;
    }
}

也可以手动初始化

namespace App\Http\Controllers;

use App\Models\User;
use App\Http\Controllers\Controller;
use App\Repositories\UserRepository;
...

$userRepository = new UserRepository(new User);

或通过静态构造函数

$userRepository = UserRepository::withModel(new User);

仓库类将具有以下功能和能力。

创建

要创建一个新的模型记录,只需在仓库类上调用 create 方法,并传递数据属性作为

$this->userRepository->create([
    ...
]);

更新

要更新现有的模型记录,请调用仓库类的 update 方法。 update 方法需要两个参数,即数据属性和模型记录的主键值或现有的模型实例。

例如,要更新主键为id值为10的用户

$primaryKeyValue = 10;

$this->userRepository->update([
    ...
], $primaryKeyValue);

或更新已检索的模型记录

$user; // the already retrived model record instance

$this->userRepository->update([
    ...
], $user);

查找

要查找模型记录,请使用仓储类的 find 方法

$this->userRepository->find(1); // find the id(primary key) of 1
$this->userRepository->find([1,2,3]); // find the id(primary key) of 1,2 and 3

find 方法还可以与数组一起使用,它将使用这些数组作为 AND WHERE 查询,并返回第一个匹配的记录

$this->userRepository->find(['email' => 'somemail@mail.test']);

通过将可选的关系数组作为 find 方法的第二个参数传递,可以同时加载模型记录及其关系

$this->userRepository->find(1, ['profile']); // find the id(primary key) of 1
$this->userRepository->find([1,2,3], ['profile']); // find the id(primary key) of 1,2 and 3

第三个参数是一个可选的布尔值,默认设置为 false。将其设置为 true 时,如果找不到模型记录,它将抛出 \Illuminate\Database\Eloquent\ModelNotFoundException

$this->userRepository->find(1, ['profile'],  true); // find the id(primary key) of 1
$this->userRepository->find([1,2,3], [], true); // find the id(primary key) of 1,2 and 3

所有记录

要获取所有记录,请使用仓储类的 all 方法

$this->userRepository->all();

删除

要删除模型记录,请使用仓储类的 delete 方法

$this->userRepository->delete(1);

delete 方法可以与模型实例或传递给仓储类 find 方法的相同类型的参数一起使用

$this->userRepository->delete($user); // delete the alredt retrived $user model instance
$this->userRepository->delete(1); // delete user id of 1
$this->userRepository->delete([1,2,3]); // delete user id of 1,2 and 3
$this->userRepository->delete(['email' => 'somemail@mail.test']); // delete user with email of somemail@mail.test

delete 方法还会检查 SoftDelete 功能,即如果模型正在使用 Illuminate\Database\Eloquent\SoftDeletes 特性,它将执行给定模型记录的软删除。

强制删除

要强制删除模型记录,请使用仓储类的 forceDelete 方法

$this->userRepository->forceDelete(1);

delete 方法可以与模型实例或传递给仓储类 find 方法的相同类型的参数一起使用

$this->userRepository->forceDelete($user); // delete the alredt retrived $user model instance
$this->userRepository->forceDelete(1); // delete user id of 1
$this->userRepository->forceDelete([1,2,3]); // delete user id of 1,2 and 3
$this->userRepository->forceDelete(['email' => 'somemail@mail.test']); // delete user with email of somemail@mail.test

delete 方法还会检查 SoftDelete 功能,即无论模型是否使用 Illuminate\Database\Eloquent\SoftDeletes 特性,它都会将这些记录从数据库中删除。

恢复

要恢复已软删除的模型记录,请使用仓储类的 restore 方法

$this->userRepository->restore(1);

restore 只适用于使用 SoftDeletes 功能的模型。如果尝试在未实现 SoftDeletes 的模型上使用恢复,它将抛出异常。

restore 方法可以与模型实例或模型主键数组一起使用。

$this->userRepository->restore($user); // restore the already retrived $user model instance
$this->userRepository->restore(1); // restore user id of 1
$this->userRepository->restore([1,2,3]); // restore user id of 1,2 and 3test

其他功能

获取模型

由于本包不处理 Eloquent 的所有功能,并且如果需要其他 Eloquent 方法来构建复杂查询,我们需要模型实例。要获取模型实例

$this->userRepository->getModel();

以及稍后设置/更新模型

$this->userRepository->setModel(new User);
$this->userRepository->setModel($user);

模型清理器

BaseRepository 类包含一个模型清理器,它将在模型记录创建/更新时自动清理传递的数组属性。这里的清理意味着它将从数据数组中删除任何元素以匹配模型表架构,同时同时尊重模型的 $fillable$hidden 属性。

这些方法的实现如下

/**
 * Sanitize data list to model fillables
 *
 * @param  array   $data
 * @return array
 */
public function sanitizeToModelFillable(array $data) {

    $classModel   = $this->model->getModel();
    $fillable     = $classModel->getFillable();

    $fillables = ! empty($fillable) 
                    ? $fillable 
                    : array_diff(
                        array_diff(
                            Schema::getColumnListing($classModel->getTable()), 
                            $classModel->getGuarded()
                        ), 
                        $classModel->getHidden()
                    );

    return array_intersect_key($data, array_flip($fillables));
}

因此,即使传递了额外的详细信息,也将被忽略或传递了在 $fillable$hidden 列表中列出的某些列。

$user = $this->userRepository->create([
    'name' => 'User Name',
    'email' => 'somemail@mail.test',
    'password' => Hash::make('password'),
    'date_of_birth' => '1990-12-08' // This date_of_birth column not present in users table
]);

上述代码将正常运行,而简单的模型创建方法将抛出异常。

$user = $this->userRepository->create($request->validated());

$profile = $this->profileRepository->create($request->validated());

当在单个控制器方法中需要将数据推送到多个模型表时,这非常有用。

贡献

欢迎拉取请求。对于重大更改,请首先打开一个问题来讨论您想进行哪些更改。

请确保根据需要更新测试。

许可证

MIT