Skip to content

Commit

Permalink
Merge pull request #2 from biiiiiigmonster/fix/readme
Browse files Browse the repository at this point in the history
readme
  • Loading branch information
biiiiiigmonster committed Oct 11, 2022
2 parents bbd593f + 2ac6d5a commit 2e6f932
Show file tree
Hide file tree
Showing 14 changed files with 266 additions and 50 deletions.
205 changes: 202 additions & 3 deletions README.md
Expand Up @@ -26,9 +26,208 @@ composer require biiiiiigmonster/laravel-clearable
```

# Introductions
删除作为数据操作的生命周期最后一环,受到关注度较小,然而在业务中完整数据的关联性往往会因为这些疏忽而被破坏。
这个包可以很方便的帮您管理这些关联数据删除关系,仅仅只需要简单的定义。
让我们来尝试一下吧!
`relation` is powerful, it can help us manage complex relationship's data.
Usually, as the last section of the data life cycle, the "delete" behavior receives less attention.
We often neglect the processing of the associated model data while deleting the data itself, the business will also be damaged due to these residual data.

This package can easily help you manage these related data's deletion relationships, with simple definitions. Let's try it!

## Usage
For example, `User` model related `Post` model, it's also hoped that the associated `Post` model can be deleted after the `User` model deleted:

```injectablephp
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the posts for the user.
*
* @return HasMany
*/
public function posts()
{
return $this->hasMany(Post::class);
}
}
```
To accomplish this, you may add the `BiiiiiigMonster\Clears\Concerns\HasClears` trait to the models you would like to auto-clear.
After adding one of the traits to the model, add the attribute name to the `clears` property of your model.
```injectablephp
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use BiiiiiigMonster\Clears\Concerns\HasClears;
class User extends Model
{
use HasClears;
/**
* The relationships that will be auto-clear when deleted.
*
* @var array
*/
protected $clears = ['posts'];
}
```
Once the relationship has been added to the `clears` list, it will be auto-clear when deleted.

## Clear Configuration
### Custom Clear
Sometimes you may occasionally need to define your own clear's logic, You may accomplish this by defining a class that implements the `InvokableClear` interface.

To generate a new clear object, you may use the `make:clear` Artisan command. we will place the new rule in the `app/Clears` directory. If this directory does not exist, We will create it when you execute the Artisan command to create your clear:
```bash
php artisan make:clear PostWithoutReleasedClear
```

Once the clear has been created, we are ready to define its behavior. A clear object contains a single method: `__invoke`.
This method will determine whether the relation data is cleared.

```injectablephp
<?php
namespace App\Clears;
use BiiiiiigMonster\Clears\Contracts\InvokableClear;
use Illuminate\Database\Eloquent\Model;
class PostWithoutReleasedClear implements InvokableClear
{
/**
* Decide if the clearable cleared.
*
* @param Model $post
* @return bool
*/
public function __invoke($post)
{
return $post->status != 'published';
}
}
```

Once you have defined a custom clear type, you may attach it to a model attribute using its class name:
```injectablephp
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use BiiiiiigMonster\Clears\Concerns\HasClears;
use App\Clears\PostWithoutReleasedClear;
class User extends Model
{
use HasClears;
/**
* The relationships that will be auto-clear when deleted.
*
* @var array
*/
protected $clears = [
'posts' => PostWithoutReleasedClear::class
];
}
```

### Use Queue
When the relation data that we need to clear may be very large, it is a very good strategy to use `queue` to execute it.

Making it work is also simple, add the attribute name to the `clearQueue` property of your model.
```injectablephp
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use BiiiiiigMonster\Clears\Concerns\HasClears;
use App\Clears\PostWithoutReleasedClear;
class User extends Model
{
use HasClears;
/**
* The clearable that will be dispatch on this name queue.
*
* @var bool|string
*/
protected $clearQueue = true;
}
```
Once the `clearQueue` has been declared, the `posts`'s clear behavior will be executed using the queue, reducing the serial pressure.
> Tips: You can also set it as a string `protected $clearQueue = 'queue-name';`, which will run in the named queue.
### Clearing At Runtime
At runtime, you may instruct a model instance to using the `clear` or `setClears` method just like
[`append`](https://laravel.com/docs/9.x/eloquent-serialization#appending-at-run-time):
```injectablephp
$user->clear(['posts' => PostWithoutReleasedClear::class])->delete();
$user->setClears(['posts' => PostWithoutReleasedClear::class])->delete();
```

## PHP8 Attribute
The 'Attribute' feature is added to php8, which provides another form of configuration, and clear is ready for it.

It is very simple to use `Attribute`, we have defined an attribute of `#[Clear]`, just only need to relate the method.
```injectablephp
namespace App\Models;
use BiiiiiigMonster\Clears\Attributes\Clear;
use BiiiiiigMonster\Clears\Concerns\HasClears;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use HasClears;
/**
* Get the posts for the user.
*
* @return HasMany
*/
#[Clear]
public function posts()
{
return $this->hasMany(Post::class);
}
}
```

Similarly, you can set `Custom Clear` in `#[Clear]`, or even configure `clearQueue` separately:
```injectablephp
#[Clear(PostWithoutReleasedClear::class, 'queue-name')]
public function posts()
{
return $this->hasMany(Post::class);
}
```
> Tips:`#[Clear]` will overwrite the corresponding configuration in `protected $clears`.
## Support Relationship
Data's "deletion" is generally a sensitive operation, we do not want important data to declare `clear` by any relationships. Therefore, we don't support `clear` in the `BelongsTo` relationships.

Support-List:
- HasOne
- HasOneThrough
- HasMany
- HasManyThrough
- MorphMany
- MorphOne
- BelongsToMany
- MorphToMany
> Tips:When the `BelongsToMany` and `MorphToMany` relationship declare is `clear`, deleted is the pivot model data.
Not-Support-List:
- BelongsTo
- MorphTo

# Test
```bash
composer test
```

# License
[MIT](./LICENSE)
8 changes: 4 additions & 4 deletions src/Attributes/Clear.php
Expand Up @@ -10,12 +10,12 @@ class Clear
/**
* Clear constructor.
*
* @param string|null $clearsAttributesClassName
* @param string|null $clearQueue
* @param string|null $invokableClearClassName
* @param string|bool|null $clearQueue
*/
public function __construct(
public ?string $clearsAttributesClassName = null,
public ?string $clearQueue = null
public ?string $invokableClearClassName = null,
public string|bool|null $clearQueue = null,
) {
}
}
28 changes: 17 additions & 11 deletions src/ClearManager.php
Expand Up @@ -4,11 +4,9 @@

use BiiiiiigMonster\Clearable\Attributes\Clear;
use BiiiiiigMonster\Clearable\Jobs\ClearsJob;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;

class ClearManager
Expand Down Expand Up @@ -36,18 +34,26 @@ public static function make(Model $model): static

/**
* ClearManager handle.
* @throws ReflectionException
*/
public function handle(): void
{
$clears = $this->parse();

foreach ($clears as $relationName => $clear) {
$param = [$this->model::class, $this->model->getOriginal(), $relationName, $relations = Collection::wrap($this->model->$relationName), $clear->clearsAttributesClassName];
$payload = [
$this->model::class,
$this->model->getOriginal(),
$relationName,
$relations = Collection::wrap($this->model->$relationName),
$clear->invokableClearClassName
];

if ($relations->isNotEmpty()) {
$clear->clearQueue
? ClearsJob::dispatch(...$param)->onQueue($clear->clearQueue)
: ClearsJob::dispatchSync(...$param);
match ($clear->clearQueue) {
null,false => ClearsJob::dispatchSync(...$payload),
true,'' => ClearsJob::dispatch(...$payload),
default => ClearsJob::dispatch(...$payload)->onQueue($clear->clearQueue)
};
}
}
}
Expand All @@ -62,13 +68,13 @@ protected function parse(): array
$clears = [];

// from clears array
foreach ($this->model->getClears() as $relationName => $clearsAttributesClassName) {
foreach ($this->model->getClears() as $relationName => $invokableClearClassName) {
if (is_numeric($relationName)) {
$relationName = $clearsAttributesClassName;
$clearsAttributesClassName = null;
$relationName = $invokableClearClassName;
$invokableClearClassName = null;
}

$clears[$relationName] = new Clear($clearsAttributesClassName, $this->model->getClearQueue());
$clears[$relationName] = new Clear($invokableClearClassName, $this->model->getClearQueue());
}

// from clear attribute
Expand Down
4 changes: 2 additions & 2 deletions src/ClearsServiceProvider.php
Expand Up @@ -2,7 +2,7 @@

namespace BiiiiiigMonster\Clearable;

use BiiiiiigMonster\Clearable\Console\ClearsAttributesMakeCommand;
use BiiiiiigMonster\Clearable\Console\InvokableClearMakeCommand;
use Illuminate\Support\ServiceProvider;

class ClearsServiceProvider extends ServiceProvider
Expand All @@ -14,6 +14,6 @@ class ClearsServiceProvider extends ServiceProvider
*/
public function register()
{
$this->commands(ClearsAttributesMakeCommand::class);
$this->commands(InvokableClearMakeCommand::class);
}
}
10 changes: 5 additions & 5 deletions src/Concerns/HasClears.php
Expand Up @@ -9,7 +9,7 @@
* Trait HasClears
*
* @property array $clears The relationships that will be auto-cleared when deleted.
* @property ?string $clearQueue The clearable that will be dispatch on this name queue.
* @property string|bool|null $clearQueue The clearable that will be dispatch on this name queue.
* @package BiiiiiigMonster\Clears\Concerns
*/
trait HasClears
Expand Down Expand Up @@ -64,20 +64,20 @@ public function clear(array|string|null $clears): static
/**
* Get clearQueue.
*
* @return ?string
* @return string|bool|null
*/
public function getClearQueue(): ?string
public function getClearQueue(): string|bool|null
{
return $this->clearQueue;
}

/**
* Set the clearQueue attributes for the model.
*
* @param string $clearQueue
* @param string|bool|null $clearQueue
* @return $this
*/
public function setClearQueue(string $clearQueue): static
public function setClearQueue(string|bool|null $clearQueue): static
{
$this->clearQueue = $clearQueue;

Expand Down
Expand Up @@ -4,7 +4,7 @@

use Illuminate\Console\GeneratorCommand;

class ClearsAttributesMakeCommand extends GeneratorCommand
class InvokableClearMakeCommand extends GeneratorCommand
{
/**
* The console command name.
Expand Down Expand Up @@ -43,7 +43,7 @@ class ClearsAttributesMakeCommand extends GeneratorCommand
*/
protected function getStub()
{
$relativePath = '/stubs/clears-attributes.stub';
$relativePath = '/stubs/invoke-clear.stub';

return file_exists($customPath = $this->laravel->basePath(trim($relativePath, '/')))
? $customPath
Expand Down
Expand Up @@ -2,18 +2,18 @@

namespace {{ namespace }};

use BiiiiiigMonster\Clearable\Contracts\ClearsAttributes;
use BiiiiiigMonster\Clearable\Contracts\InvokableClear;
use Illuminate\Database\Eloquent\Model;

class {{ class }} implements ClearsAttributes
class {{ class }} implements InvokableClear
{
/**
* Decide if the clearable cleared.
*
* @param Model $clear
* @return bool
*/
public function abandon($clear): bool
public function __invoke($clear): bool
{
//
}
Expand Down
Expand Up @@ -4,13 +4,13 @@

use Illuminate\Database\Eloquent\Model;

interface ClearsAttributes
interface InvokableClear
{
/**
* Decide if the clearable cleared.
*
* @param Model $clear
* @return bool
*/
public function abandon($clear): bool;
public function __invoke($clear): bool;
}

0 comments on commit 2e6f932

Please sign in to comment.