Laravel Taggable 為你的模型添加打標(biāo)簽功能

本文經(jīng)授權(quán)轉(zhuǎn)自 PHPHub 社區(qū)

功能說明

使用最簡便的方式智润,為你的數(shù)據(jù)模型提供強(qiáng)大「打標(biāo)簽」功能心包。

:gift: 項(xiàng)目地址:https://github.com/summerblue/laravel-taggable

本項(xiàng)目修改于 rtconner/laravel-tagging 項(xiàng)目跪腹,增加了一下功能:

  • 標(biāo)簽名唯一畏梆;
  • 增加 etrepat/baum 依賴闸婴,讓標(biāo)簽支持無限級(jí)別標(biāo)簽嵌套坏挠;
  • 中文 slug 拼音自動(dòng)生成支持,感謝超哥的 overtrue/pinyin邪乍;
  • 提供完整的測試用例降狠,保證代碼質(zhì)量。

注意: 本項(xiàng)目只支持 5.1 LTS

:heart: 此項(xiàng)目由 The EST Group 團(tuán)隊(duì)的 @Summer 維護(hù)庇楞。

無限級(jí)別標(biāo)簽嵌套

集成 etrepat/baum 讓標(biāo)簽具備從屬關(guān)系榜配。


$root = Tag::create(['name' => 'Root']);

// 創(chuàng)建子標(biāo)簽
$child1 = $root->children()->create(['name' => 'Child1']);

$child = Tag::create(['name' => 'Child2']);
$child->makeChildOf($root);

// 批量構(gòu)建樹
$tagTree = [
    'name' => 'RootTag',
    'children' => [
        ['name' => 'L1Child1',
            'children' => [
                ['name' => 'L2Child1'],
                ['name' => 'L2Child1'],
                ['name' => 'L2Child1'],
            ]
        ],
        ['name' => 'L1Child2'],
        ['name' => 'L1Child3'],
    ]
];

Tag::buildTree($tagTree);

更多關(guān)聯(lián)操作請查看:etrepat/baum

標(biāo)簽名稱規(guī)則說明

  • 標(biāo)簽名里的特殊符號(hào)和空格會(huì)被 - 替代吕晌;
  • 智能標(biāo)簽 slug 生成蛋褥,會(huì)生成 name 對(duì)應(yīng)的中文拼音 slug ,如:標(biāo)簽 -> biao-qian睛驳,拼音一樣的時(shí)候會(huì)被加上隨機(jī)值烙心;

標(biāo)簽名清理使用:$normalize_string = EstGroupe\Taggable\Util::tagName($name)


Tag::create(['標(biāo)簽名']);
// name: 標(biāo)簽名
// slug: biao-qian-ming

Tag::create(['表簽名']);
// name: 表簽名
// slug: biao-qian-ming-3243 (后面 3243 為隨機(jī)乏沸,解決拼音沖突)

Tag::create(['標(biāo)簽 名']);
// name: 標(biāo)簽-名
// slug: biao-qian-ming

Tag::create(['標(biāo)簽!名']);
// name: 標(biāo)簽-名
// slug: biao-qian-ming

安裝說明:

安裝

composer require estgroupe/laravel-taggable "5.1.*"

安裝和執(zhí)行遷移

config/app.phpproviders 數(shù)組中加入:

'providers' => array(
    \EstGroupe\Taggable\Providers\TaggingServiceProvider::class,
);
php artisan vendor:publish --provider="EstGroupe\Taggable\Providers\TaggingServiceProvider"
php artisan migrate

請仔細(xì)閱讀 config/tagging.php 文件淫茵。

創(chuàng)建 Tag.php

不是必須的,不過建議你創(chuàng)建自己項(xiàng)目專屬的 Tag.php 文件蹬跃。

<?php namespace App\Models;

use EstGroupe\Taggable\Model\Tag as TaggableTag;

class Tag extends TaggableTag
{
    // Model code go here
}

修改 config/tagging.php 文件中:

    'tag_model'=>'\App\Models\Tag',

加入 Taggable Trait

<?php namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use EstGroupe\Taggable\Taggable;

class Article extends \Illuminate\Database\Eloquent\Model {
    use Taggable;
}

「標(biāo)簽狀態(tài)」標(biāo)示

Taggable 能跟蹤模型是否打過標(biāo)簽的狀態(tài):

// `no`
$article->is_tagged

// `yes`
$article->tag('Tag1');
$article->is_tagged;

// `no`
$article->unTag();
$article->is_tagged

// This is fast
$taggedArticles = Article::where('is_tagged', 'yes')->get()

首先你需要修改 config/tagging.php 文件中:

'is_tagged_label_enable' => true,

然后在你的模型的數(shù)據(jù)庫創(chuàng)建腳本里加上:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticlesTable extends Migration {

    public function up()
    {
        Schema::create('weibo_statuses', function(Blueprint $table) {
            $table->increments('id');
            ...
            // Add this line
            $table->enum('is_tagged', array('yes', 'no'))->default('no');
            ...
            $table->timestamps();
        });
    }
}

「推薦標(biāo)簽」標(biāo)示

方便你實(shí)現(xiàn)「推薦標(biāo)簽」功能匙瘪,只需要把 suggest 字段標(biāo)示為 true

$tag = EstGroupe\Taggable\Model\Tag::where('slug', '=', 'blog')->first();
$tag->suggest = true;
$tag->save();

即可以用以下方法讀取:

$suggestedTags = EstGroupe\Taggable\Model\Tag::suggested()->get();

重寫 Util 類?

大部分的通用操作都發(fā)生在 Util 類,你想獲取更多的定制權(quán)力丹喻,請創(chuàng)建自己的 Util 類薄货,并注冊服務(wù)提供者:

namespace My\Project\Providers;

use EstGroupe\Taggable\Providers\TaggingServiceProvider as ServiceProvider;
use EstGroupe\Taggable\Contracts\TaggingUtility;

class TaggingServiceProvider extends ServiceProvider {

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(TaggingUtility::class, function () {
            return new MyNewUtilClass;
        });
    }

}

然后在

注意 MyNewUtilClass 必須實(shí)現(xiàn) EstGroupe\Taggable\Contracts\TaggingUtility 接口。

使用范例

$article = Article::with('tags')->first(); // eager load

// 獲取所有標(biāo)簽
foreach($article->tags as $tag) {
    echo $tag->name . ' with url slug of ' . $tag->slug;
}

// 打標(biāo)簽
$article->tag('Gardening'); // attach the tag
$article->tag('Gardening, Floral'); // attach the tag
$article->tag(['Gardening', 'Floral']); // attach the tag
$article->tag('Gardening', 'Floral'); // attach the tag

// 批量通過 tag ids 打標(biāo)簽
$article->tagWithTagIds([1,2,3]);

// 去掉標(biāo)簽
$article->untag('Cooking'); // remove Cooking tag
$article->untag(); // remove all tags

// 重打標(biāo)簽
$article->retag(['Fruit', 'Fish']); // delete current tags and save new tags
$article->retag('Fruit', 'Fish');
$article->retag('Fruit, Fish');

$tagged = $article->tagged; // return Collection of rows tagged to article
$tags = $article->tags; // return Collection the actual tags (is slower than using tagged)

// 獲取綁定的標(biāo)簽名稱數(shù)組
$article->tagNames(); // get array of related tag names

// 獲取打了「任意」標(biāo)簽的 Article 對(duì)象
Article::withAnyTag('Gardening, Cooking')->get(); // fetch articles with any tag listed
Article::withAnyTag(['Gardening','Cooking'])->get(); // different syntax, same result as above
Article::withAnyTag('Gardening','Cooking')->get(); // different syntax, same result as above

// 獲取打了「全包含」標(biāo)簽的 Article 對(duì)象
Article::withAllTags('Gardening, Cooking')->get(); // only fetch articles with all the tags
Article::withAllTags(['Gardening', 'Cooking'])->get();
Article::withAllTags('Gardening', 'Cooking')->get();

EstGroupe\Taggable\Model\Tag::where('count', '>', 2)->get(); // return all tags used more than twice

Article::existingTags(); // return collection of all existing tags on any articles

如果你 創(chuàng)建了 Tag.php驻啤,即可使用以下標(biāo)簽讀取功能:


// 通過 slug 獲取標(biāo)簽
Tag::byTagSlug('biao-qian-ming')->first();

// 通過名字獲取標(biāo)簽
Tag::byTagName('標(biāo)簽名')->first();

// 通過名字?jǐn)?shù)組獲取標(biāo)簽數(shù)組
Tag::byTagNames(['標(biāo)簽名', '標(biāo)簽2', '標(biāo)簽3'])->first();

// 通過 Tag ids 數(shù)組獲取標(biāo)簽數(shù)組
Tag::byTagIds([1,2菲驴,3])->first();

// 通過名字?jǐn)?shù)組獲取 ID 數(shù)組
$ids = Tag::idsByNames(['標(biāo)簽名', '標(biāo)簽2', '標(biāo)簽3'])->all();
// [1,2,3]

標(biāo)簽事件

Taggable trait 提供以下兩個(gè)事件:

EstGroupe\Taggable\Events\TagAdded;

EstGroupe\Taggable\Events\TagRemoved;

監(jiān)聽標(biāo)簽事件:

\Event::listen(EstGroupe\Taggable\Events\TagAdded::class, function($article){
    \Log::debug($article->title . ' was tagged');
});

單元測試

基本用例測試請見: tests/CommonUsageTest.php

運(yùn)行測試:

composer install
vendor/bin/phpunit --verbose

Thanks

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骑冗,一起剝皮案震驚了整個(gè)濱河市赊瞬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贼涩,老刑警劉巖巧涧,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異遥倦,居然都是意外死亡谤绳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門袒哥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缩筛,“玉大人,你說我怎么就攤上這事堡称∠古祝” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵却紧,是天一觀的道長桐臊。 經(jīng)常有香客問我,道長晓殊,這世上最難降的妖魔是什么断凶? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮巫俺,結(jié)果婚禮上认烁,老公的妹妹穿的比我還像新娘。我一直安慰自己识藤,他們只是感情好砚著,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著痴昧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冠王。 梳的紋絲不亂的頭發(fā)上赶撰,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼豪娜。 笑死餐胀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘤载。 我是一名探鬼主播否灾,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鸣奔!你這毒婦竟也來了墨技?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤挎狸,失蹤者是張志新(化名)和其女友劉穎扣汪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锨匆,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崭别,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恐锣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茅主。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖土榴,靈堂內(nèi)的尸體忽然破棺而出诀姚,到底是詐尸還是另有隱情,我是刑警寧澤鞭衩,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布学搜,位于F島的核電站,受9級(jí)特大地震影響论衍,放射性物質(zhì)發(fā)生泄漏瑞佩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一坯台、第九天 我趴在偏房一處隱蔽的房頂上張望炬丸。 院中可真熱鬧,春花似錦蜒蕾、人聲如沸稠炬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽首启。三九已至,卻和暖如春撤摸,著一層夾襖步出監(jiān)牢的瞬間毅桃,已是汗流浹背褒纲。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钥飞,地道東北人莺掠。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像读宙,于是被迫代替她去往敵國和親彻秆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理结闸,服務(wù)發(fā)現(xiàn)唇兑,斷路器,智...
    卡卡羅2017閱讀 134,696評(píng)論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,277評(píng)論 25 707
  • 在上一個(gè)章節(jié)膀估,我們已經(jīng)創(chuàng)建了一個(gè)基礎(chǔ)的Blog程序♂:ィ現(xiàn)在我們將使用一些Dajngo高級(jí)功能,去實(shí)現(xiàn)一個(gè)完整的blo...
    金金剛狼閱讀 3,591評(píng)論 1 12
  • 且騎說二匪本是奉了命出去插千打探察纯,未料及在一個(gè)毛頭小子處跌了跟頭帕棉,心頭自然燥熱窩火,不過既然瞄見了稀罕寶物饼记,總算沒...
    到猶今閱讀 203評(píng)論 1 1
  • 前端 Yarn 包管理器 時(shí)間:2016-10-15 12:48:54作者:zhongxia 也就兩三天沒有關(guān)注前...
    izhongxia閱讀 1,453評(píng)論 0 0