-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from AliBayat/v2.0
V2.0
- Loading branch information
Showing
13 changed files
with
7,971 additions
and
1,146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,12 +3,13 @@ | |
Laravel Categorizable Package | ||
============ | ||
|
||
This Package enables you to Categorize your Eloquent Models. just use the trait in the model and you're good to go. | ||
This Package is an implementation of a Nested-set hierarchy structure, which enables you to categorize your Eloquent models in a polymorphic way. just use the trait in the model, and you're good to go. | ||
There is also a `Category` model which you can use directly or extend it in your model of choosing. | ||
|
||
|
||
### Requirements | ||
- PHP 7.4+ | ||
- Laravel 7+ | ||
## Requirements | ||
- PHP 8+ | ||
- Laravel 8+ | ||
|
||
## Installation | ||
|
||
|
@@ -27,8 +28,8 @@ php artisan migrate | |
Laravel Categorizable package will be auto-discovered by Laravel. and if not: register the package in config/app.php providers array manually. | ||
```php | ||
'providers' => [ | ||
... | ||
\AliBayat\LaravelCategorizable\CategorizableServiceProvider::class, | ||
... | ||
\AliBayat\LaravelCategorizable\CategorizableServiceProvider::class, | ||
], | ||
``` | ||
|
||
|
@@ -38,93 +39,82 @@ Laravel Categorizable package will be auto-discovered by Laravel. and if not: re | |
```php | ||
<?php | ||
|
||
namespace App; | ||
namespace App\Models; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
use AliBayat\LaravelCategorizable\Categorizable; | ||
|
||
class Post extends Model | ||
{ | ||
use Categorizable; | ||
|
||
use Categorizable; | ||
} | ||
|
||
``` | ||
|
||
## Usage | ||
first of all we need to create some Category to work with. Laravel Categorizable package relies on another package called [laravel-nestedset](https://github.com/lazychaser/laravel-nestedset) that is responsible for creating, updating, removing and retrieving single or nested categories. | ||
Here i demonstrate how to create categories and assign one as the other's child.. but you can always refer to package's repository for full documentation. | ||
first we need to create some categories to work with. this package relies on another package called [laravel-nestedset](https://github.com/lazychaser/laravel-nestedset) that is responsible for creating, updating, removing and retrieving single or nested structured categories. | ||
Here I demonstrate how to create categories and assign one as the other's child. but you can always check out the tests or refer to package's repository for full documentation. | ||
https://github.com/lazychaser/laravel-nestedset | ||
|
||
|
||
```php | ||
use App\Post; | ||
use App\Models\Post; | ||
use AliBayat\LaravelCategorizable\Category; | ||
|
||
// first we create a bunch of categories | ||
|
||
// create "BackEnd" category | ||
Category::create([ | ||
'name' => 'BackEnd' | ||
]); | ||
|
||
// create "PHP" category | ||
Category::create([ | ||
'name' => 'PHP' | ||
]); | ||
|
||
// create "FrontEnd" category | ||
Category::create([ | ||
'name' => 'FrontEnd' | ||
]); | ||
|
||
// create "Test" Category (alternative way) | ||
$test = new Category(); | ||
$test->name = 'Test'; | ||
$test->save(); | ||
|
||
|
||
// assign "PHP" as a child of "BackEnd" category | ||
$parent = Category::findByName('BackEnd'); | ||
$child = Category::findByName('PHP'); | ||
$parent->appendNode($child); | ||
|
||
// delete "Test" Category | ||
$testObj = Category::findByName('Test'); | ||
$testObj->delete(); | ||
|
||
// create categories | ||
$backEnd = Category::create(['name' => 'Back End']); | ||
$frontEnd = Category::create(['name' => 'Front End']); | ||
$php = Category::create(['name' => 'PHP']); | ||
|
||
// assign "PHP" as a child of "Back End" category | ||
$backEnd->appendNode($php); | ||
|
||
// assuming that we have these variables | ||
// assuming that we have a post instance | ||
$post = Post::first(); | ||
``` | ||
|
||
### Multiple category structure | ||
|
||
// 3 different ways of getting a category's instance | ||
$backendCategory = Category::findById(1); // 'BackEnd' | ||
$phpCategory = Category::findByName('PHP'); // 'PHP' | ||
$frontendCategory = Category::find(3); // 'FrontEnd' | ||
there are times that you may wish to have different category structures for different models. in that's the case you can also pass in a `type` parameter while creating a category. by default, type is set to `default`. while having a type you can also leverage Eloquent model scopes to filter categories with ease. | ||
|
||
### Create a Tree while creating new categories | ||
|
||
it's also possible to pass a nested structure as the `children` property to the create method: | ||
```php | ||
$categoryWithChildAndGrandchild = Category::create([ | ||
'name' => 'Foo', | ||
'children' => [ | ||
[ | ||
'name' => 'Bar', | ||
'children' => [ | ||
[ 'name' => 'Baz' ], | ||
], | ||
], | ||
], | ||
]); | ||
``` | ||
|
||
### Attach the post to category | ||
|
||
```php | ||
$post->attachCategory($phpCategory); | ||
$post->attachCategory($php); | ||
``` | ||
|
||
### Detach the post from a category | ||
|
||
```php | ||
$post->detachCategory($phpCategory); | ||
$post->detachCategory($php); | ||
``` | ||
|
||
### Attach the post to list of categories | ||
|
||
```php | ||
$post->syncCategories([ | ||
$phpCategory, | ||
$backendCategory | ||
]); | ||
$php, | ||
$backEnd | ||
]); | ||
``` | ||
|
||
### Detach the post from all categories | ||
|
@@ -136,114 +126,117 @@ $frontendCategory = Category::find(3); // 'FrontEnd' | |
### Sync the categories attached to a post | ||
|
||
```php | ||
$post->syncCategories([ | ||
$frontendCategory | ||
]); | ||
|
||
|
||
// removes attached categories & adds the given categories | ||
$post->syncCategories([$frontEnd]); | ||
``` | ||
|
||
|
||
### Check if post is attached to categories (boolean) | ||
### Check if post is attached to given categories (boolean) | ||
```php | ||
// single use case | ||
$post->hasCategory($phpCategory); | ||
$post->hasCategory($php); | ||
|
||
// multiple use case | ||
$post->hasCategory([ | ||
$phpCategory, | ||
$backendCategory | ||
]); | ||
|
||
|
||
// return boolean | ||
$php, | ||
$backEnd | ||
]); | ||
``` | ||
|
||
### List of categories attached to the post (array) | ||
### List of categories attached to the post (array [1 => 'BackEnd']) | ||
```php | ||
$post->categoriesList(); | ||
|
||
|
||
// return array [id => name] | ||
``` | ||
|
||
### List of categories IDs attached to the post (array) | ||
### List of categories IDs attached to the post (array [1, 2, 3]) | ||
```php | ||
$post->categoriesId(); | ||
|
||
|
||
// return array | ||
$post->categoriesIds(); | ||
``` | ||
|
||
### Get all posts attached to given category (MorphToMany) | ||
```php | ||
$categoryPosts = Category::find(1) | ||
->entries(Post::class); | ||
|
||
$categoryPosts = Category::find(1)->entries(Post::class); | ||
``` | ||
|
||
// return MorphToMany | ||
### Get all posts attached to given category and it's children (Builder) | ||
```php | ||
$categoryAndDescendantsPosts = Category::find(1)->allEntries(Post::class); | ||
``` | ||
|
||
### Get all posts attached to given category or it's children (Builder) | ||
--- | ||
|
||
## Methods | ||
On the Base `Category` Model (or any other model that extends this class), you'll have access to various methods: | ||
|
||
```php | ||
$categoryAllPosts = Category::find(1) | ||
->allEntries(Post::class); | ||
$result = Category::ancestorsOf($id); | ||
$result = Category::ancestorsAndSelf($id); | ||
$result = Category::descendantsOf($id); | ||
$result = Category::descendantsAndSelf($id); | ||
$result = Category::whereDescendantOf($node)->get(); | ||
$result = Category::whereNotDescendantOf($node)->get(); | ||
$result = Category::orWhereDescendantOf($node)->get(); | ||
$result = Category::orWhereNotDescendantOf($node)->get(); | ||
$result = Category::whereDescendantAndSelf($id)->get(); | ||
$result = Category::whereDescendantOrSelf($node)->get(); | ||
$result = Category::whereAncestorOf($node)->get(); | ||
$result = Category::whereAncestorOrSelf($id)->get(); | ||
|
||
$siblings = Category::find($id)->getSiblings(); | ||
$nextSibling = Category::find($id)->getNextSibling(); | ||
$nextSiblings = Category::find($id)->getNextSiblings(); | ||
$prevSibling = Category::find($id)->getPrevSibling(); | ||
$prevSiblings = Category::find($id)->getPrevSiblings(); | ||
|
||
$withDepth = Category::withDepth()->find($id); | ||
$withSpecificDepth = Category::withDepth()->having('depth', '=', 1)->get(); | ||
|
||
// return Builder | ||
$tree = Category::get()->toTree(); | ||
$flatTree = Category::get()->toFlatTree(); | ||
|
||
$bool = Category::isBroken(); | ||
$data = Category::countErrors(); | ||
Category::fixTree(); | ||
``` | ||
full documentation for these methods is available at `laravel-nestedset` package's readme. | ||
|
||
--- | ||
|
||
## Relationships | ||
|
||
### categories() Relationship | ||
```php | ||
$postWithCategories = Post::with('categories') | ||
->get(); | ||
|
||
|
||
// you have access to categories() relationship in case you need eager loading | ||
|
||
$postWithCategories = Post::with('categories')->get(); | ||
``` | ||
|
||
### parent Relationship | ||
```php | ||
$category = Post::first()->categories()->first(); | ||
|
||
$category->parent; | ||
// return the category's parent if available | ||
|
||
$categoryWithParent = Category::with('parent')->find(1); | ||
``` | ||
|
||
### children Relationship | ||
```php | ||
$category = Post::first()->categories()->first(); | ||
|
||
$category->children; | ||
// return the category's children if any | ||
|
||
$categoryWithChildren = Category::with('children')->find(1); | ||
``` | ||
|
||
### ancestors Relationship | ||
```php | ||
$category = Post::first()->categories()->first(); | ||
|
||
$category->ancestors; | ||
// return the category's ancestors if any | ||
|
||
$categoryWithAncestors = Category::with('ancestors')->find(1); | ||
``` | ||
|
||
### descendants Relationship | ||
```php | ||
$category = Post::first()->categories()->first(); | ||
|
||
$category->descendants; | ||
// return the category's descendants if any | ||
$categoryWithDescendants = Category::with('descendants')->find(1); | ||
``` | ||
|
||
|
||
|
||
## Tests | ||
this package comes with unit and feature tests as well (a total of 47 tests, 169 assertions) to ensure the provided features work as they should, you can run tests by the following composer command: | ||
``` | ||
composer test | ||
``` | ||
|
||
#### Credits | ||
|
||
- Ali Bayat - <[email protected]> | ||
- Thanks to all contributors |
Oops, something went wrong.