• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

rinvex/laravel-categories: Rinvex Categorizable is a polymorphic Laravel package ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

rinvex/laravel-categories

开源软件地址(OpenSource Url):

https://github.com/rinvex/laravel-categories

开源编程语言(OpenSource Language):

PHP 100.0%

开源软件介绍(OpenSource Introduction):

Rinvex Categories

Rinvex Categories is a polymorphic Laravel package, for category management. You can categorize any eloquent model with ease, and utilize the power of Nested Sets, and the awesomeness of Sluggable, and Translatable models out of the box.

Packagist Scrutinizer Code Quality Travis StyleCI License

Installation

  1. Install the package via composer:

    composer require rinvex/laravel-categories
  2. Publish resources (migrations and config files):

    php artisan rinvex:publish:categories
  3. Execute migrations via the following command:

    php artisan rinvex:migrate:categories
  4. Done!

Usage

To add categories support to your eloquent models simply use \Rinvex\Categories\Traits\Categorizable trait.

Manage your categories

Your categories are just normal eloquent models, so you can deal with it like so. Nothing special here!

Notes: since Rinvex Categories extends and utilizes other awesome packages, checkout the following documentations for further details:

Manage your categorizable model

The API is intutive and very straightfarwad, so let's give it a quick look:

// Get all categories
$allCategories = app('rinvex.categories.category')->first();

// Get instance of your model
$post = new \App\Models\Post::find();

// Get attached categories collection
$post->categories;

// Get attached categories query builder
$post->categories();

You can attach categories in various ways:

// Single category id
$post->attachCategories(1);

// Multiple category IDs array
$post->attachCategories([1, 2, 5]);

// Multiple category IDs collection
$post->attachCategories(collect([1, 2, 5]));

// Single category model instance
$categoryInstance = app('rinvex.categories.category')->first();
$post->attachCategories($categoryInstance);

// Single category slug
$post->attachCategories('test-category');

// Multiple category slugs array
$post->attachCategories(['first-category', 'second-category']);

// Multiple category slugs collection
$post->attachCategories(collect(['first-category', 'second-category']));

// Multiple category model instances
$categoryInstances = app('rinvex.categories.category')->whereIn('id', [1, 2, 5])->get();
$post->attachCategories($categoryInstances);

Notes:

  • The attachCategories() method attach the given categories to the model without touching the currently attached categories, while there's the syncCategories() method that can detach any records that's not in the given items, this method takes a second optional boolean parameter that's set detaching flag to true or false.
  • To detach model categories you can use the detachCategories() method, which uses exactly the same signature as the attachCategories() method, with additional feature of detaching all currently attached categories by passing null or nothing to that method as follows: $post->detachCategories();.

And as you may have expected, you can check if categories attached:

// Single category id
$post->hasAnyCategories(1);

// Multiple category IDs array
$post->hasAnyCategories([1, 2, 5]);

// Multiple category IDs collection
$post->hasAnyCategories(collect([1, 2, 5]));

// Single category model instance
$categoryInstance = app('rinvex.categories.category')->first();
$post->hasAnyCategories($categoryInstance);

// Single category slug
$post->hasAnyCategories('test-category');

// Multiple category slugs array
$post->hasAnyCategories(['first-category', 'second-category']);

// Multiple category slugs collection
$post->hasAnyCategories(collect(['first-category', 'second-category']));

// Multiple category model instances
$categoryInstances = app('rinvex.categories.category')->whereIn('id', [1, 2, 5])->get();
$post->hasAnyCategories($categoryInstances);

Notes:

  • The hasAnyCategories() method check if ANY of the given categories are attached to the model. It returns boolean true or false as a result.
  • Similarly the hasAllCategories() method uses exactly the same signature as the hasAnyCategories() method, but it behaves differently and performs a strict comparison to check if ALL of the given categories are attached.

Advanced usage

Generate category slugs

Rinvex Categories auto generates slugs and auto detect and insert default translation for you if not provided, but you still can pass it explicitly through normal eloquent create method, as follows:

app('rinvex.categories.category')->create(['name' => ['en' => 'My New Category'], 'slug' => 'custom-category-slug']);

Note: Check Sluggable package for further details.

Smart parameter detection

Rinvex Categories methods that accept list of categories are smart enough to handle almost all kinds of inputs as you've seen in the above examples. It will check input type and behave accordingly.

Retrieve all models attached to the category

You may encounter a situation where you need to get all models attached to certain category, you do so with ease as follows:

$category = app('rinvex.categories.category')->find(1);
$category->entries(\App\Models\Post::class)->get();

Query scopes

Yes, Rinvex Categories shipped with few awesome query scopes for your convenience, usage example:

// Single category id
$post->withAnyCategories(1)->get();

// Multiple category IDs array
$post->withAnyCategories([1, 2, 5])->get();

// Multiple category IDs collection
$post->withAnyCategories(collect([1, 2, 5]))->get();

// Single category model instance
$categoryInstance = app('rinvex.categories.category')->first();
$post->withAnyCategories($categoryInstance)->get();

// Single category slug
$post->withAnyCategories('test-category')->get();

// Multiple category slugs array
$post->withAnyCategories(['first-category', 'second-category'])->get();

// Multiple category slugs collection
$post->withAnyCategories(collect(['first-category', 'second-category']))->get();

// Multiple category model instances
$categoryInstances = app('rinvex.categories.category')->whereIn('id', [1, 2, 5])->get();
$post->withAnyCategories($categoryInstances)->get();

Notes:

  • The withAnyCategories() scope finds posts with ANY attached categories of the given. It returns normally a query builder, so you can chain it or call get() method for example to execute and get results.
  • Similarly there's few other scopes like withAllCategories() that finds posts with ALL attached categories of the given, withoutCategories() which finds posts without ANY attached categories of the given, and lastly withoutAnyCategories() which find posts without ANY attached categories at all. All scopes are created equal, with same signature, and returns query builder.

Category translations

Manage category translations with ease as follows:

$category = app('rinvex.categories.category')->find(1);

// Update title translations
$category->setTranslation('name', 'en', 'New English Category Title')->save();

// Alternatively you can use default eloquent update
$category->update([
    'name' => [
        'en' => 'New Category',
        'ar' => 'تصنيف جديد',
    ],
]);

// Get single category translation
$category->getTranslation('name', 'en');

// Get all category translations
$category->getTranslations('name');

// Get category title in default locale
$category->name;

Note: Check Translatable package for further details.


Manage your nodes/nestedsets

Inserting categories

Moving and inserting categories includes several database queries, so transaction is automatically started when category is saved. It is safe to use global transaction if you work with several models.

Another important note is that structural manipulations are deferred until you hit save on model (some methods implicitly call save and return boolean result of the operation).

If model is successfully saved it doesn't mean that category was moved. If your application depends on whether the category has actually changed its position, use hasMoved method:

if ($category->save()) {
    $moved = $category->hasMoved();
}

Creating categories

When you simply create a category, it will be appended to the end of the tree:

app('rinvex.categories.category')->create($attributes); // Saved as root

$category = app('rinvex.categories.category')->fill($attributes);
$category->save(); // Saved as root

In this case the category is considered a root which means that it doesn't have a parent.

Making a root from existing category

The category will be appended to the end of the tree:

// #1 Implicit save
$category->saveAsRoot();

// #2 Explicit save
$category->makeRoot()->save();

Appending and prepending to the specified parent

If you want to make category a child of other category, you can make it last or first child. Suppose that $parent is some existing category, there are few ways to append a category:

// #1 Using deferred insert
$category->appendToNode($parent)->save();

// #2 Using parent category
$parent->appendNode($category);

// #3 Using parent's children relationship
$parent->children()->create($attributes);

// #5 Using category's parent relationship
$category->parent()->associate($parent)->save();

// #6 Using the parent attribute
$category->parent_id = $parent->getKey();
$category->save();

// #7 Using static method
app('rinvex.categories.category')->create($attributes, $parent);

And only a couple ways to prepend:

// #1 Using deferred insert
$category->prependToNode($parent)->save();

// #2 Using parent category
$parent->prependNode($category);

Inserting before or after specified category

You can make $category to be a neighbor of the $neighbor category. Suppose that $neighbor is some existing category, while target category can be fresh. If target category exists, it will be moved to the new position and parent will be changed if it's required.

# Explicit save
$category->afterNode($neighbor)->save();
$category->beforeNode($neighbor)->save();

# Implicit save
$category->insertAfterNode($neighbor);
$category->insertBeforeNode($neighbor);

Building a tree from array

When using static method create on category, it checks whether attributes contains children key. If it does, it creates more categories recursively, as follows:

$category = app('rinvex.categories.category')->create([
    'name' => [
        'en' => 'New Category Title',
    ],

    'children' => [
        [
            'name' => 'Bar',

            'children' => [
                [ 'name' => 'Baz' ],
            ],
        ],
    ],
]);

$category->children now contains a list of created child categories.

Rebuilding a tree from array

You can easily rebuild a tree. This is useful for mass-changing the structure of the tree. Given the $data as an array of categories, you can build the tree as follows:

$data = [
    [ 'id' => 1, 'name' => 'foo', 'children' => [ ... ] ],
    [ 'name' => 'bar' ],
];

app('rinvex.categories.category')->rebuildTree($data, $delete);

There is an id specified for category with the title of foo which means that existing category will be filled and saved. If category does not exists ModelNotFoundException is thrown. Also, this category has children specified which is also an array of categories; they will be processed in the same manner and saved as children of category foo.

Category bar has no primary key specified, so it will treated as a new one, and be created.

$delete shows whether to delete categories that are already exists but not present in $data. By default, categories aren't deleted.

Retrieving categories

In some cases we will use an $id variable which is an id of the target category.

Ancestors

Ancestors make a chain of parents to the category. Helpful for displaying breadcrumbs to the current category.

// #1 Using accessor
$result = $category->getAncestors();

// #2 Using a query
$result = $category->ancestors()->get();

// #3 Getting ancestors by primary key
$result = app('rinvex.categories.category')->ancestorsOf($id);

Descendants

Descendants are all categories in a sub tree, i.e. children of category, children of children, etc.

// #1 Using relationship
$result = $category->descendants;

// #2 Using a query
$result = $category->descendants()->get();

// #3 Getting descendants by primary key
$result = app('rinvex.categories.category')->descendantsOf($id);

// #3 Get descendants and the category by id
$result = app('rinvex.categories.category')->descendantsAndSelf($id);

Descendants can be eagerly loaded:

$categories = app('rinvex.categories.category')->with('descendants')->whereIn('id', $idList)->get();

Siblings

Siblings are categories that have same parent.

$result = $category->getSiblings();

$result = $category->siblings()->get();

To get only next siblings:

// Get a sibling that is immediately after the category
$result = $category->getNextSibling();

// Get all siblings that are after the category
$result = $category->getNextSiblings();

// Get all siblings using a query
$result = $category->nextSiblings()->get();

To get previous siblings:

// Get a sibling that is immediately before the category
$result = $category->getPrevSibling();

// Get all siblings that are before the category
$result = $category->getPrevSiblings();

// Get all siblings using a query
$result = $category->prevSiblings()->get();

Getting related models from other table

Imagine that each category has many products. I.e. HasMany relationship is established. How can you get all products of $category and every its descendant? Easy!

// Get ids of descendants
$categories = $category->descendants()->pluck('id');

// Include the id of category itself
$categories[] = $category->getKey();

// Get products
$goods = Product::whereIn('category_id', $categories)->get();

Now imagine that each category has many posts. I.e. morphToMany relationship is established this time. How can you get all posts of $category and every its descendant? Is that even possible?! Sure!

// Get ids of descendants
$categories = $category->descendants()->pluck('id');

// Include the id of category itself
$categories[] = $category->getKey();

// Get posts
$posts = \App\Models\Post::withCategories($categories)->get();

Including category depth

If you need to know at which level the category is:

$result = app('rinvex.categories.category')->withDepth()->find($id);

$depth = $result->depth;

Root category will be at level 0. Children of root categories will have a level of 1, etc. To get categories of s


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap