zoha / laravel-meta
用于处理模型元数据的包
Requires
- laravel/framework: >=8.0
Requires (Dev)
- php: >=8
- orchestra/testbench: >=6.0
- phpunit/phpunit: ^9
README
一个用于处理元数据的 Laravel 包!
页面内容
简介
有时我们的 Laravel 模型需要很多信息,这些信息应该存储在数据库中。例如,假设你想创建一个博客,并为这个博客添加一个帖子模型。这个模型最需要的信息是标题和内容。但这个模型可能还有更多信息,比如点赞数、下载链接、缩略图、浏览次数等。当这些信息量很大时,我们需要为模型表创建更多的列,如果列太多,会很难处理。此外,每篇帖子可能都有其他帖子不需要的独特信息。在这种情况下,这个包会很有帮助。如果我们想简单地解释这个包:Laravel Meta 允许你为每个模型存储信息,并轻松访问它们,而不必在数据库表中为这些信息创建新列。如果你还没有注意到,请看下面的例子。
特性
- 轻松存储和获取每个模型的元数据
- 在数据库表中创建许多列的替代方案
- 最少的查询次数和完全优化
- 能够通过元数据过滤数据库记录
安装
首先,使用 composer 安装此包
$ composer require zoha/laravel-meta
如果你使用 Laravel <= 5.4,请将 ServiceProvider 和 Alias 添加到 config/app.php 中
'providers' => [ ... Zoha\Meta\MetaServiceProvider::class, ... ] 'aliases' => [ ... 'Meta' => Zoha\Meta\Facades\MetaFacade::class, ... ]
然后执行迁移命令以迁移元数据表
$ php artisan migrate
然后,为了将元数据功能添加到你的每个模型中,你只需将其从 MetableModel 继承,而不是从 Model 继承。
use Zoha\MetableModel; class Post extends MetableModel { ... }
或者你可以使用 Metable 特性
use Zoha\Metable; class Post extends Model { use Metable; ... }
可选部分
你可以使用此命令发布元数据配置文件
$ php artisan vendor:publish --provider="Zoha\Meta\MetaServiceProvider" --tag=config
在此文件中,你可以更改默认的元数据表(默认:meta)或者你可以 为特定模型自定义元数据表
就这样!现在你可以使用所有的 Laravel 元数据功能了
在下面的所有示例中,我们假设 $post 已设置为 Post::first(),其中 Post 模型是一个示例模型
基本方法
创建新元数据
要创建元数据,你可以在模型上使用 createMeta
$post->createMeta('key' , 'value');
或者你可以这样创建多个元数据
$post->createMeta([ 'key1' => 'value1', 'key2' => 'value2' ]);
@return : createMeta
方法如果元数据创建成功则返回 true,否则返回 false
addMeta
方法是createMeta
方法的别名
更新元数据
要更新元数据,你可以在模型上使用 updateMeta
$post->updateMeta('key' , 'new value');
或者你可以这样更新多个元数据
$post->updateMeta([ 'key1' => 'new value 1', 'key2' => 'new value 2' ]);
@return : 如果更新成功,updateMeta
返回 true。但如果元数据已不存在或更新失败,则返回 false
创建或更新元数据
要创建或更新元数据,请使用 setMeta
方法,此方法将更新元数据,如果尚未存在,则创建新的元数据
$post->setMeta('key' , 'value'); // create meta $post->setMeta('key' , 'new value'); // update meta
或者您可以这样设置多个元数据
$post->setMeta([ 'key1' => 'value 1', 'key2' => 'value 2' ]);
@return : setMeta
如果成功则返回 true。否则返回 false
或者,您可以使用 meta 属性 来设置元数据,如下所示
$post->meta->key1 = 'value'; $post->meta->key2 = 'value2'; $post->meta->save();
获取元数据
getMeta
方法将返回元数据的值
//return meta value or null if meta not exists $post->getMeta('key'); // return value or 'default value ' if not exists or value is null $post->getMeta('key' , 'default value') ;
您也可以使用 meta 属性 来获取元数据的值
$post->meta->key; // return meta value
获取元数据列表
getMetas
方法将返回所有元数据作为集合
// return a collection of all metas for this model // no meta yet ? -> empty collection $post->getMetas() ;
删除元数据
要删除元数据,请使用 deleteMeta
方法
$post->deleteMeta(); // delete all meta of this model $post->deleteMeta('key'); // delete a specific meta
或者您可以使用 unsetMeta
方法代替,这两种方法都是相同的。 truncateMeta
也会删除特定模型的所有元数据
$post->truncateMeta(); // delete all model meta
检查元数据是否存在
如果您想检查是否存在特定的元数据,可以使用 hasMeta
方法(如果元数据存在但值为 null,则返回 false)
$post->hasMeta(); // return true if this model has at least one meta $post->hasMeta('key'); // return true or false
第二个参数指定是否接受 null 值。如果您将第二个参数传递为 true,即使值为 null,如果元数据存在,则返回 true
$post->setMeta('key' , null); // set key to null $post->hasMeta('key'); // return false $post->hasMeta('key' , true); // return true
如果您想指定一个特定的帖子具有特定的元数据,即使其值为 null,也请使用 existsMeta
方法。
$post->setMeta('key' , null); // set key to null $post->existsMeta('key'); // return true
增加元数据
您可以使用 increaseMeta
方法简单地增加元数据的值。请注意,增加浮点值时,除非指定,否则不会增加小数部分。
$post->setMeta('key' , 3); $post->increaseMeta('key'); // meta value will change to 4 $post->setMeta('key' , 3.5); $post->increaseMeta('key'); // meta value will change to 4.5 $post->setMeta('key' , 3.5); $post->increaseMeta('key' , .1); // meta value will change to 3.6 $post->setMeta('key2' , 'not integer value'); $post->increaseMeta('key2'); // meta value will not change
您可以为确定增加步骤传递第二个参数
$post->setMeta('key' , 3); $post->increaseMeta('key',3); // meta value will change to 6
减少元数据
您可以使用 decreaseMeta
方法简单地减少元数据的值。请注意,减少浮点值时,除非指定,否则不会减少小数值。
$post->setMeta('key' , 3); $post->decreaseMeta('key'); // meta value will change to 2 $post->setMeta('key' , 3.5); $post->decreaseMeta('key'); // meta value will change to 2.5 $post->setMeta('key' , 3.5); $post->decreaseMeta('key', .1); // meta value will change to 3.4 $post->setMeta('key2' , 'not integer value'); $post->decreaseMeta('key2'); // meta value will not change
您也可以为确定减少步骤传递第二个参数
$post->setMeta('key' , 3); $post->decreaseMeta('key',3); // meta value will change to 0
子句
Where Meta 子句
通过元数据值过滤项目
$result = Post::whereMeta('key','value'); // you can use operator : $result = Post::whereMeta('key', '>' , 100); // you can use multiple whereMeta Clause $result = Post::whereMeta('key', '>' , 100) ->whereMeta('key' , '<' , 200); //orWhereMeta clause $result = Post::whereMeta('key', '>' , 100) ->orWhereMeta('key' , '<' , 50); //branched clauses $result = Post::where(function($query){ $query->where(function($query){ $query->whereMeta('key1' , 'value1'); $query->orWhereMeta('key1' , 'value2'); }); $query->whereMeta('key2' , 'like' , '%value%'); $query->WhereMeta('key3' , '>' , 100); });
您也可以传递一个数组作为过滤结果
// all of below conditions will converted to 'AND' $result = Post::whereMeta([ 'key1' => 'value1', [ 'key2' , '!=' , 'value2' ], [ 'key3' , 'value3' ] ]);
您还可以使用 orWhere 为多个 or where 子句
$result = Post::orWhereMeta([ 'key1' => 'value1', [ 'key2' , '!=' , 'value2' ], [ 'key3' , 'value3' ] ]);
您可以使用分支过滤器来处理所有元数据子句
Where Meta In 子句
whereMetaIn
和 whereMetaNotIn
子句
$result = Post::whereMetaIn('key', ['value1' , 'value2']); $result = Post::whereMetaNotIn('key', ['value1' , 'value2']); // multiple clauses $result = Post::whereMetaIn('key', [1,2]) ->whereMetaIn('key2' , [1,2]); // 'orWhere' clauses $result = Post::whereMetaNotIn('key', [1,2,3]) ->orWhereMetaIn('key2', [1,2]) ->orWhereMetaNotIn('key3', [1,2]);
Where Meta Between 子句
whereMetaBetween
和 whereMetaNotBetween
子句
$result = Post::whereMetaBetween('key', [0,100]); $result = Post::whereMetaNotBetween('key', [0,100]); // multiple clauses $result = Post::whereMetaBetween('key', [100,200]) ->whereMetaBetween('key2' , [100,200]); // 'orWhere' clauses $result = Post::whereMetaNotBetween('key', [1000,8000]) ->orWhereMetaBetween('key2', [1,5]) ->orWhereMetaNotBetween('key3', [0,100]);
Where Meta Null 子句
whereMetaNull
和 whereMetaNotNull
子句
$result = Post::whereMetaNull('key'); $result = Post::whereMetaNotNull('key'); // multiple clauses $result = Post::whereMetaNull('key') ->whereMetaNull('key2'); // 'orWhere' clauses $result = Post::whereMetaNotNull('key') ->orWhereMetaNull('key2') ->orWhereMetaNotNull('key3');
Where Meta Has 子句
whereMetaHas
和 whereMetaDoesntHave
子句
//filter records that has at least one meta $result = Post::whereMetaHas(); $result = Post::whereMetaHas('key'); $result = Post::whereMetaHas('key' , true); //count null values $result = Post::whereMetaDoesntHave('key'); $result = Post::whereMetaDoesntHave('key' , true); //count null values // multiple clauses $result = Post::whereMetaHas('key') ->whereMetaDoesntHave('key2'); // 'orWhere' clauses $result = Post::whereMetaDoesntHave('key') ->orWhereMetaHas('key2') ->orWhereMetaDoesntHave('key3');
按元数据排序
您可以使用 orderByMeta
子句对数据库结果进行排序
Post::orderByMeta('price')->get(); Post::orderByMeta('price' , 'desc')->get(); Post::orderByMeta('price')->orderByMeta('likes' , 'desc')->get();
预加载
如果您第一次调用 $post->getMeta('key')
,所有这个模型的元数据都将一次性加载(一次)。如果您尝试从这个模型获取另一个元数据,则不会执行另一个查询,元数据值将来自之前的查询。但是,如果您尝试从另一个模型获取元数据,则将为新模型执行另一个查询。如果您想在一个查询中获取所有模型的元数据,可以使用元数据的预加载。您只需调用 withMeta
范围,如下所示
$posts = Post::withMeta()->get(); // will return all posts results with their meta values
请注意,with('meta')
将不起作用
其他方法和特性
注意
- 默认情况下,当您尝试获取它们时,所有集合、数组和 JSON 值都将转换为集合。
- 所有
[]
、"{}"
、"[]"
和null
值都将被视为 null。 - 如果元数据模型中的一个项目被删除,与该项目相关的所有元数据也将被删除。
数据类型
所有 setMeta
、getMeta
、updateMeta
和 createMeta
方法都接受第三个参数,该参数确定元数据类型。以下是一些该功能的示例
可用的数据类型:
string
、integer
、float
、null
、collection
、json
、array
、boolean
。
在 setMeta
方法中
$post->setMeta('key' , '123' , 'integer'); $post->meta->key; // 123 ( integer ) $post->setMeta('key' , '123.45' , 'integer'); $post->meta->key; // 123 ( integer - decimal dropped) $post->setMeta('key' , '123.45' , 'float'); $post->meta->key; // 123.45 ( float ) //---------------------------------- $post->setMeta('key' , [1,2,3] , 'json'); $post->meta->key; // "[1,2,3]" ( string - json ) //---------------------------------- $post->setMeta([ 'key1' => 'value', 'key2' => 2 'key3' => [1,2,3] ],'string' ); // all values will converted to string when you try to get them $post->meta->key2; // "2" ( string ) $post->meta->key3; // "[1,2,3]" ( string json )
createMeta
和 updateMeta
方法中的第三个参数与 setMeta
方法中的相同
在 getMeta
方法中
$post->setMeta('key' , 123); $post->getMeta('key' , 'null' , 'string'); // "123" (string) //---------------------------------- $post->setMeta('key' , [1,2,3] , 'string'); $post->getMeta('key' , 'null'); // "[1,2,3]" (string) $post->getMeta('key' , 'null' , 'array'); // [1,2,3] (array) $post->getMeta('key' , 'null' , 'boolean'); // true (boolean)
自定义元数据表
默认情况下,所有模型的元数据都将存储在 meta
数据库表中。但如果您想,您可以为特定模型使用一个单独的表。
例如,您有 Post
、Comment
和 User
模型
您希望将所有帖子评论的元数据存储在默认表中,但用户的元数据标签存储在特殊表中。为此,您需要执行以下四个步骤
第一步:您应该使用以下命令发布包配置文件
$ php artisan vendor:publish --provider="Zoha\Meta\MetaServiceProvider" --tag=config
此命令将在您的配置文件夹中放置一个名为 meta.php
的文件
第二步:在 tables
数组中打开配置文件,您会找到一个自定义数组。在这个数组中,您可以添加新的表名。在我们的例子中,我们将 users_meta
添加到这个数组中以处理用户元数据
'tables' => [ 'default' => 'meta', 'custom' => [ 'users_meta' ], ]
第三步:您需要运行迁移命令来创建新表。
$ php artisan migrate
如果您已经迁移了元数据迁移,您应该回滚此迁移并再次迁移(以创建新表)
最后一步:现在新表已创建,您可以将它引入到 User
模型(或您想处理的任何模型)中,以便使用此表处理其元数据。如下所示
use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use \Zoha\Metable; protected $metaTable = 'users_meta'; }
元数据模型
您可以在项目中自由使用元数据模型
use Zoha\Meta\Models\Meta; $count = Meta::count();
注意:如果您使用元数据模型(直接更改数据库)更改元数据值,则之前加载的元数据值将不会更新。如果您想更新它们,您应该调用 refreshLoadedMeta
方法
use Zoha\Meta\Models\Meta; $post->meta->key1; // exmaple : return 'test' Meta::truncate(); $post->meta->key1; // still return 'test' $post->refreshLoadeMeta(); $post->meta->key1; // will return null
元数据表
元数据表的结构如下
Schema::create('meta', function (Blueprint $table) { $table->increments('id'); $table->string('key',110); $table->text('value')->nullable(); $table->string('type')->default(Meta::META_TYPE_STRING); $table->boolean('status')->default(true); $table->string('owner_type',80); $table->integer('owner_id'); $table->unique(['key','owner_type','owner_id']); $table->timestamps(); });
许可证
贡献
该项目欢迎您的贡献 贡献