Loading repository data…
Loading repository data…
rinvex / repository
Rinvex Categorizable 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.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
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.
Install the package via composer:
composer require rinvex/laravel-categories
Publish resources (migrations and config files):
php artisan rinvex:publish:categories
Execute migrations via the following command:
php artisan rinvex:migrate:categories
Done!
To add categories support to your eloquent models simply use \Rinvex\Categories\Traits\Categorizable trait.
Your categories are just normal eloquent models, so you can deal with it like so. Nothing special here!
Notes: since extends and utilizes other awesome packages, checkout the following documentations for further details:
kalnoy/nestedsetspatie/laravel-sluggablespatie/laravel-translatableThe API is intutive and very straightforward, so let's give it a quick look:
// Get all categories
$allCategories = app('rinvex.categories.category')->all();
// Get instance of your model
$post = new \App\Models\Post::find(123);
// 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 thesyncCategories()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 totrueorfalse.- To detach model categories you can use the
detachCategories()method, which uses exactly the same signature as theattachCategories()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 booleantrueorfalseas a result.- Similarly the
hasAllCategories()method uses exactly the same signature as thehasAnyCategories()method, but it behaves differently and performs a strict comparison to check if ALL of the given categories are attached.
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.
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.
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();
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 callget()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 lastlywithoutAnyCategories()which find posts without ANY attached categories at all. All scopes are created equal, with same signature, and returns query builder.
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.
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();
}
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.
The category will be appended to the end of the tree:
// #1 Implicit save
$category->saveAsRoot();
// #2 Explicit save
$category->makeRoot()->save();
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()->assoc