Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readme #2

Merged
merged 11 commits into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 202 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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;
}
Loading