Skip to content

Commit

Permalink
Merge pull request #9 from AliBayat/v2.0
Browse files Browse the repository at this point in the history
V2.0
  • Loading branch information
AliBayat authored Dec 23, 2022
2 parents 3104567 + cfcdfcc commit 59e662b
Show file tree
Hide file tree
Showing 13 changed files with 7,971 additions and 1,146 deletions.
209 changes: 101 additions & 108 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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,
],
```

Expand All @@ -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
Expand All @@ -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
Loading

0 comments on commit 59e662b

Please sign in to comment.