lgrevelink / laravel-custom-query-builder
Laravel 中创建自定义查询构建器的实用项目。
Requires
- php: >=7.1
- illuminate/console: >=5.7
- illuminate/support: >=5.7
Requires (Dev)
- laravel/framework: >=5.7
- phpunit/phpunit: ^7.0
This package is auto-updated.
Last update: 2024-08-29 13:00:01 UTC
README
这是一个自定义查询构建器,允许项目在应用级别上使用 Eloquent 的构建器。通过薄抽象层,通过适当的 IntelliSense 定义连接、过滤器、排序和作用域。
安装
composer require lgrevelink/laravel-custom-query-builder
Laravel 的配置
Laravel 的自动发现直接注册了服务提供者,因此应该立即可用。如果您不使用自动发现,请将 ServiceProvider
添加到 config/app.php
中的提供者数组中。
LGrevelink\CustomQueryBuilder\ServiceProvider::class
通过添加服务提供者直接注册了 artisan 命令。如果您想更改默认配置,可以通过以下命令发布它;
php artisan vendor:publish --provider="LGrevelink\CustomQueryBuilder\ServiceProvider"
Lumen 的配置
在 Lumen 中使用此包需要您在 bootstrap/app.php
中注册服务提供者。
$app->register(LGrevelink\CustomQueryBuilder\ServiceProvider::class);
通过添加服务提供者直接注册了 artisan 命令。如果您想更改默认配置,可以通过以下命令发布它;
$app->configure('querybuilder');
使用方法
模型在从模型运行操作时使用 Eloquent 的构建器作为默认值。此包允许您使用托管在您项目中的自定义查询构建器来覆盖此默认行为。
创建新的查询构建器(生成器)
该包包含一个 artisan make 命令,该命令在指定位置配置了一个示例构建器。只需运行以下命令,您就应该有构建器了;
php artisan make:query-builder MyQueryBuilder
分配查询构建器
创建查询构建器后,我们需要将其分配给模型。模型需要应用 HasCustomQueryBuilder
关注。这可以通过扩展 Eloquent 的模型或直接将特性添加到类中来完成。这只会初始化到 CustomQueryBuilder
的连接。要使用自己的构建器,您必须在模型中设置它;
class SomeModel extends Model { use LGrevelink\CustomQueryBuilder\Concerns\HasCustomQueryBuilder; protected $queryBuilder = App\QueryBuilders\MyQueryBuilder::class; }
使用查询构建器
过滤器和排序的默认命名结构为 filterOn%s
和 sortBy%s
,其中占位符将被替换为过滤器的单数或复数版本,具体取决于过滤器值。如果是数组,它将尝试复数版本。任何其他值都将使用单数版本。以下是一些示例,其中每个集合的行为相同。
$builder = SomeModel::select(); // Using direct filters on the query builder $builder->filterOnProperty(1234); $builder->filterOnCategories([1, 2]); $builder->sortByCategory('asc'); $builder->sortByTitle('asc'); // Enforcing the naming structure $builder->applyFilter('property', 1234); // Calls filterOnProperty $builder->applyFilter('category', [1, 2]); // Calls filterOnCategories $builder->applySorting('category', 'asc'); // Calls sortByCategory $builder->applySorting('title', 'asc'); // Calls sortByTitle // Setting them in bulk $builder->applyFilters([ 'property' => 1234, 'category' => [1, 2], ); // Calls both filterOnProperty and filterOnCategories $builder->applySorting([ 'category' => 'asc', 'title' => 'asc', ]); // Calls both sortByCategory and sortByTitle
直接从构建器中获取全局作用域
如果您想将所有数据库相关数据(包括全局作用域)都保留在查询构建器中;您可以!它们仅在模型指示它们应该添加时才会添加,但这样您可以避免通过 Model->boot
函数添加这些。
class MyQueryBuilder extends CustomQueryBuilder { protected $globalScopes = [ MyScope::class, ]; }
严格的异常
如果过滤器不存在,将会抛出异常。对于这些情况有一个回退,它会自动应用 where
或 whereIn
以处理未知过滤器,并为未知排序应用 orderBy
。默认情况下,查询构建器的模式设置为 strict
,此行为被阻止。您可以通过覆盖 querybuilder.mode
配置值并将其设置为 auto
来更改此行为。请注意,如果输入没有经过适当验证,这可能会导致副作用。
工具
joinOnce
可以使用 joinOnce
方法来连接表并防止重复。它利用了 \Illuminate\Database\Query\Builder
的 join
方法在将连接添加到查询之前进行基本的表验证。这样就可以防止对同一表进行多次连接。
class ProductQueryBuilder extends CustomQueryBuilder { public function joinCategories() { return $this->joinOnce('categories', 'categories.id', 'products.category_id'); } public function filterOnCategoryStatus(string $status) { return $this->joinCategories()->where('categories.status', $status); } public function filterOnCategoryTitle(string $title) { return $this->joinCategories()->where('categories.title', 'LIKE', $title); } }
在这种情况下,当对状态和标题进行筛选时,连接只会形成一次,而不是多次。
通配符列限定
在选择语句中使用未限定的通配符可能会有难以发现的副作用。当使用连接时,如果列名称相同,原始表中的值可能会被连接表覆盖。为了防止这种行为,我们限定未限定的通配符。如果您希望覆盖是所需的行为,我们建议您将您想要的特定列显式添加到选择语句中。而不是让它成为副作用,这应该是一个开发者意识到的故意选择。