mirror of
https://github.com/barryvdh/laravel-ide-helper.git
synced 2026-08-18 01:57:13 +00:00
Model hooks (#945)
* Model hooks * composer fix-style * Fix test for ModelHooks Co-authored-by: laravel-ide-helper <[email protected]>
This commit is contained in:
co-authored by
laravel-ide-helper
parent
b8d5fc3663
commit
f0c138c4fd
@@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
[Next release](https://github.com/barryvdh/laravel-ide-helper/compare/v2.9.2...master)
|
[Next release](https://github.com/barryvdh/laravel-ide-helper/compare/v2.9.2...master)
|
||||||
--------------
|
--------------
|
||||||
|
### Added
|
||||||
|
- Model hooks for adding custom information from external sources to model classes through the ModelsCommand [\#945 / wimski](https://github.com/barryvdh/laravel-ide-helper/pull/945)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Running tests triggering post_migrate hooks [\#1193 / netpok](https://github.com/barryvdh/laravel-ide-helper/pull/1193)
|
- Running tests triggering post_migrate hooks [\#1193 / netpok](https://github.com/barryvdh/laravel-ide-helper/pull/1193)
|
||||||
- Array_merge error when config is cached prior to package install [\#1184 / netpok](https://github.com/barryvdh/laravel-ide-helper/pull/1184)
|
- Array_merge error when config is cached prior to package install [\#1184 / netpok](https://github.com/barryvdh/laravel-ide-helper/pull/1184)
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ Generation is done based on the files in your project, so they are always up-to-
|
|||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Automatic PHPDoc generation for Laravel Facades](#automatic-phpdoc-generation-for-laravel-facades)
|
- [Automatic PHPDoc generation for Laravel Facades](#automatic-phpdoc-generation-for-laravel-facades)
|
||||||
- [Automatic PHPDocs for models](#automatic-phpdocs-for-models)
|
- [Automatic PHPDocs for models](#automatic-phpdocs-for-models)
|
||||||
|
- [Model Directories](#model-directories)
|
||||||
|
- [Ignore Models](#ignore-models)
|
||||||
|
- [Model Hooks](#model-hooks)
|
||||||
- [Automatic PHPDocs generation for Laravel Fluent methods](#automatic-phpdocs-generation-for-laravel-fluent-methods)
|
- [Automatic PHPDocs generation for Laravel Fluent methods](#automatic-phpdocs-generation-for-laravel-fluent-methods)
|
||||||
- [Auto-completion for factory builders](#auto-completion-for-factory-builders)
|
- [Auto-completion for factory builders](#auto-completion-for-factory-builders)
|
||||||
- [PhpStorm Meta for Container instances](#phpstorm-meta-for-container-instances)
|
- [PhpStorm Meta for Container instances](#phpstorm-meta-for-container-instances)
|
||||||
@@ -175,6 +178,8 @@ With the `--write-mixin (-M)` option
|
|||||||
*/
|
*/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Model Directories
|
||||||
|
|
||||||
By default, models in `app/models` are scanned. The optional argument tells what models to use (also outside app/models).
|
By default, models in `app/models` are scanned. The optional argument tells what models to use (also outside app/models).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -189,6 +194,8 @@ php artisan ide-helper:models --dir="path/to/models" --dir="app/src/Model"
|
|||||||
|
|
||||||
You can publish the config file (`php artisan vendor:publish`) and set the default directories.
|
You can publish the config file (`php artisan vendor:publish`) and set the default directories.
|
||||||
|
|
||||||
|
#### Ignore Models
|
||||||
|
|
||||||
Models can be ignored using the `--ignore (-I)` option
|
Models can be ignored using the `--ignore (-I)` option
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -270,6 +277,42 @@ For those special cases, you can map them via the config `custom_db_types`. Exam
|
|||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Model Hooks
|
||||||
|
|
||||||
|
If you need additional information on your model from sources that are not handled by default, you can hook in to the
|
||||||
|
generation process with model hooks to add extra information on the fly.
|
||||||
|
Simply create a class that implements `ModelHookInterface` and add it to the `model_hooks` array in the config:
|
||||||
|
|
||||||
|
```php
|
||||||
|
'model_hooks' => [
|
||||||
|
MyCustomHook::class,
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
The `run` method will be called during generation for every model and receives the current running `ModelsCommand` and the current `Model`, e.g.:
|
||||||
|
|
||||||
|
```php
|
||||||
|
class MyCustomHook implements ModelHookInterface
|
||||||
|
{
|
||||||
|
public function run(ModelsCommand $command, Model $model): void
|
||||||
|
{
|
||||||
|
if (! $model instanceof MyModel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$command->setProperty('custom', 'string', true, false, 'My custom property');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```php
|
||||||
|
/**
|
||||||
|
* MyModel
|
||||||
|
*
|
||||||
|
* @property integer $id
|
||||||
|
* @property-read string $custom
|
||||||
|
```
|
||||||
|
|
||||||
### Automatic PHPDocs generation for Laravel Fluent methods
|
### Automatic PHPDocs generation for Laravel Fluent methods
|
||||||
|
|
||||||
If you need PHPDocs support for Fluent methods in migration, for example
|
If you need PHPDocs support for Fluent methods in migration, for example
|
||||||
|
|||||||
@@ -144,6 +144,21 @@ return [
|
|||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Models hooks
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Define which hook classes you want to run for models to add custom information
|
||||||
|
|
|
||||||
|
| Hooks should implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'model_hooks' => [
|
||||||
|
// App\Support\IdeHelper\MyModelHook::class
|
||||||
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Extra classes
|
| Extra classes
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Barryvdh\LaravelIdeHelper\Console;
|
namespace Barryvdh\LaravelIdeHelper\Console;
|
||||||
|
|
||||||
|
use Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface;
|
||||||
use Barryvdh\Reflection\DocBlock;
|
use Barryvdh\Reflection\DocBlock;
|
||||||
use Barryvdh\Reflection\DocBlock\Context;
|
use Barryvdh\Reflection\DocBlock\Context;
|
||||||
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
|
use Barryvdh\Reflection\DocBlock\Serializer as DocBlockSerializer;
|
||||||
@@ -279,6 +280,9 @@ class ModelsCommand extends Command
|
|||||||
$this->getSoftDeleteMethods($model);
|
$this->getSoftDeleteMethods($model);
|
||||||
$this->getCollectionMethods($model);
|
$this->getCollectionMethods($model);
|
||||||
$this->getFactoryMethods($model);
|
$this->getFactoryMethods($model);
|
||||||
|
|
||||||
|
$this->runModelHooks($model);
|
||||||
|
|
||||||
$output .= $this->createPhpDocs($name);
|
$output .= $this->createPhpDocs($name);
|
||||||
$ignore[] = $name;
|
$ignore[] = $name;
|
||||||
$this->nullableColumns = [];
|
$this->nullableColumns = [];
|
||||||
@@ -336,7 +340,7 @@ class ModelsCommand extends Command
|
|||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Model $model
|
* @param \Illuminate\Database\Eloquent\Model $model
|
||||||
*/
|
*/
|
||||||
protected function castPropertiesType($model)
|
public function castPropertiesType($model)
|
||||||
{
|
{
|
||||||
$casts = $model->getCasts();
|
$casts = $model->getCasts();
|
||||||
foreach ($casts as $name => $type) {
|
foreach ($casts as $name => $type) {
|
||||||
@@ -412,7 +416,7 @@ class ModelsCommand extends Command
|
|||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Model $model
|
* @param \Illuminate\Database\Eloquent\Model $model
|
||||||
*/
|
*/
|
||||||
protected function getPropertiesFromTable($model)
|
public function getPropertiesFromTable($model)
|
||||||
{
|
{
|
||||||
$table = $model->getConnection()->getTablePrefix() . $model->getTable();
|
$table = $model->getConnection()->getTablePrefix() . $model->getTable();
|
||||||
$schema = $model->getConnection()->getDoctrineSchemaManager();
|
$schema = $model->getConnection()->getDoctrineSchemaManager();
|
||||||
@@ -509,7 +513,7 @@ class ModelsCommand extends Command
|
|||||||
/**
|
/**
|
||||||
* @param \Illuminate\Database\Eloquent\Model $model
|
* @param \Illuminate\Database\Eloquent\Model $model
|
||||||
*/
|
*/
|
||||||
protected function getPropertiesFromMethods($model)
|
public function getPropertiesFromMethods($model)
|
||||||
{
|
{
|
||||||
$methods = get_class_methods($model);
|
$methods = get_class_methods($model);
|
||||||
if ($methods) {
|
if ($methods) {
|
||||||
@@ -721,7 +725,7 @@ class ModelsCommand extends Command
|
|||||||
* @param string|null $comment
|
* @param string|null $comment
|
||||||
* @param bool $nullable
|
* @param bool $nullable
|
||||||
*/
|
*/
|
||||||
protected function setProperty($name, $type = null, $read = null, $write = null, $comment = '', $nullable = false)
|
public function setProperty($name, $type = null, $read = null, $write = null, $comment = '', $nullable = false)
|
||||||
{
|
{
|
||||||
if (!isset($this->properties[$name])) {
|
if (!isset($this->properties[$name])) {
|
||||||
$this->properties[$name] = [];
|
$this->properties[$name] = [];
|
||||||
@@ -1351,4 +1355,26 @@ class ModelsCommand extends Command
|
|||||||
|
|
||||||
return $parameterName;
|
return $parameterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Illuminate\Database\Eloquent\Model $model
|
||||||
|
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||||
|
* @throws \RuntimeException
|
||||||
|
*/
|
||||||
|
protected function runModelHooks($model): void
|
||||||
|
{
|
||||||
|
$hooks = $this->laravel['config']->get('ide-helper.model_hooks', []);
|
||||||
|
|
||||||
|
foreach ($hooks as $hook) {
|
||||||
|
$hookInstance = $this->laravel->make($hook);
|
||||||
|
|
||||||
|
if (!$hookInstance instanceof ModelHookInterface) {
|
||||||
|
throw new \RuntimeException(
|
||||||
|
'Your IDE helper model hook must implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hookInstance->run($this, $model);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Barryvdh\LaravelIdeHelper\Contracts;
|
||||||
|
|
||||||
|
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
interface ModelHookInterface
|
||||||
|
{
|
||||||
|
public function run(ModelsCommand $command, Model $model): void;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks;
|
||||||
|
|
||||||
|
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
|
||||||
|
use Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class CustomProperty implements ModelHookInterface
|
||||||
|
{
|
||||||
|
public function run(ModelsCommand $command, Model $model): void
|
||||||
|
{
|
||||||
|
$command->setProperty('custom', 'string', true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Simple extends Model
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks;
|
||||||
|
|
||||||
|
use Barryvdh\LaravelIdeHelper\Console\ModelsCommand;
|
||||||
|
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\AbstractModelsCommand;
|
||||||
|
use Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Hooks\CustomProperty;
|
||||||
|
use Illuminate\Filesystem\Filesystem;
|
||||||
|
use Mockery;
|
||||||
|
|
||||||
|
class Test extends AbstractModelsCommand
|
||||||
|
{
|
||||||
|
protected function getEnvironmentSetUp($app)
|
||||||
|
{
|
||||||
|
parent::getEnvironmentSetUp($app);
|
||||||
|
|
||||||
|
$app['config']->set('ide-helper', [
|
||||||
|
'model_locations' => [
|
||||||
|
// This is calculated from the base_path() which points to
|
||||||
|
// vendor/orchestra/testbench-core/laravel
|
||||||
|
'/../../../../tests/Console/ModelsCommand/ModelHooks/Models',
|
||||||
|
],
|
||||||
|
'model_hooks' => [
|
||||||
|
CustomProperty::class,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test(): void
|
||||||
|
{
|
||||||
|
$actualContent = null;
|
||||||
|
|
||||||
|
$mockFilesystem = Mockery::mock(Filesystem::class);
|
||||||
|
$mockFilesystem
|
||||||
|
->shouldReceive('get')
|
||||||
|
->andReturn(file_get_contents(__DIR__ . '/Models/Simple.php'))
|
||||||
|
->once();
|
||||||
|
$mockFilesystem
|
||||||
|
->shouldReceive('put')
|
||||||
|
->with(
|
||||||
|
Mockery::any(),
|
||||||
|
Mockery::capture($actualContent)
|
||||||
|
)
|
||||||
|
->andReturn(1) // Simulate we wrote _something_ to the file
|
||||||
|
->once();
|
||||||
|
|
||||||
|
$this->instance(Filesystem::class, $mockFilesystem);
|
||||||
|
|
||||||
|
$command = $this->app->make(ModelsCommand::class);
|
||||||
|
|
||||||
|
$tester = $this->runCommand($command, [
|
||||||
|
'--write' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertSame(0, $tester->getStatusCode());
|
||||||
|
$this->assertStringContainsString('Written new phpDocBlock to', $tester->getDisplay());
|
||||||
|
|
||||||
|
$expectedContent = <<<'PHP'
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\ModelHooks\Models\Simple
|
||||||
|
*
|
||||||
|
* @property int $id
|
||||||
|
* @property-read string $custom
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|Simple newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|Simple newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|Simple query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder|Simple whereId($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Simple extends Model
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PHP;
|
||||||
|
|
||||||
|
$this->assertSame($expectedContent, $actualContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user