generated from spatie/package-skeleton-laravel
-
-
Notifications
You must be signed in to change notification settings - Fork 218
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 #622 from spatie/structure-discoverer
Structure caching
- Loading branch information
Showing
20 changed files
with
456 additions
and
85 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
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
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 |
---|---|---|
@@ -1,6 +1,6 @@ | ||
--- | ||
title: Commands | ||
weight: 15 | ||
weight: 16 | ||
--- | ||
|
||
## make:data | ||
|
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 |
---|---|---|
@@ -0,0 +1,65 @@ | ||
--- | ||
title: Performance | ||
weight: 15 | ||
--- | ||
|
||
Laravel Data is a powerful package that leverages PHP reflection to infer as much information as possible. While this approach provides a lot of benefits, it does come with a minor performance overhead. This overhead is typically negligible during development, but it can become noticeable in a production environment with a large number of data objects. | ||
|
||
Fortunately, Laravel Data is designed to operate efficiently without relying on reflection. It achieves this by allowing you to cache the results of its complex analysis. This means that the performance cost is incurred only once, rather than on every request. By caching the analysis results before deploying your application to production, you ensure that a pre-analyzed, cached version of the data objects is used, significantly improving performance. | ||
|
||
## Caching | ||
|
||
Laravel Data provides a command to cache the analysis results of your data objects. This command will analyze all of your data objects and store the results in a Laravel cache of your choice: | ||
|
||
``` | ||
php artisan data:cache-structures | ||
``` | ||
|
||
That's it, the command will search for all the data objects in your application and cache the analysis results. Be sure to always run this command after creating or modifying a data object or when deploying your application to production. | ||
|
||
## Configuration | ||
|
||
The caching mechanism can be configured in the `data.php` config file. By default, the cache store is set to the default cache store of your application. You can change this to any other cache driver supported by Laravel. A prefix can also be set for the cache keys stored: | ||
|
||
```php | ||
'structure_caching' => [ | ||
'cache' => [ | ||
'store' => 'redis', | ||
'prefix' => 'laravel-data', | ||
], | ||
], | ||
``` | ||
|
||
To find the data classes within your application, we're using the [php-structure-discoverer](https://github.com/spatie/php-structure-discoverer) package. This package allows you to configure the directories that will be searched for data objects. By default, the `app/data` directory is searched recursively. You can change this to any other directory or directories: | ||
|
||
```php | ||
'structure_caching' => [ | ||
'directories' => [ | ||
'app', | ||
], | ||
], | ||
``` | ||
|
||
Structure discoverer uses reflection (enabled by default) or a PHP parser to find the data objects. You can disable the reflection based discovery and thus use the PHP parser discovery as such: | ||
|
||
```php | ||
'structure_caching' => [ | ||
'reflection_discovery' => [ | ||
'enabled' => false, | ||
], | ||
], | ||
``` | ||
|
||
When using reflection discovery, the base directory and root namespace can be configured as such if you're using a non-standard directory structure or namespace | ||
|
||
```php | ||
'structure_caching' => [ | ||
'reflection_discovery' => [ | ||
'enabled' => true, | ||
'base_path' => base_path(), | ||
'root_namespace' => null, | ||
], | ||
], | ||
``` | ||
|
||
You can read more about reflection discovery [here](https://github.com/spatie/php-structure-discoverer#parsers). |
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
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 |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<?php | ||
|
||
namespace Spatie\LaravelData\Commands; | ||
|
||
use Illuminate\Console\Command; | ||
use ReflectionClass; | ||
use Spatie\LaravelData\Support\Caching\CachedDataConfig; | ||
use Spatie\LaravelData\Support\Caching\DataClassFinder; | ||
use Spatie\LaravelData\Support\Caching\DataStructureCache; | ||
use Spatie\LaravelData\Support\DataClass; | ||
use Spatie\LaravelData\Support\DataConfig; | ||
|
||
class DataStructuresCacheCommand extends Command | ||
{ | ||
protected $signature = 'data:cache-structures {--show-classes : Show the data classes cached}'; | ||
|
||
protected $description = 'Cache the internal data structures'; | ||
|
||
public function handle( | ||
DataStructureCache $dataStructureCache, | ||
DataConfig $dataConfig | ||
): void { | ||
$this->components->info('Caching data structures...'); | ||
|
||
$dataClasses = DataClassFinder::fromConfig(config('data.structure_caching'))->classes(); | ||
|
||
$cachedDataConfig = CachedDataConfig::initialize($dataConfig); | ||
|
||
$dataStructureCache->storeConfig($cachedDataConfig); | ||
|
||
$progressBar = $this->output->createProgressBar(count($dataClasses)); | ||
|
||
foreach ($dataClasses as $dataClass) { | ||
$dataStructureCache->storeDataClass( | ||
DataClass::create(new ReflectionClass($dataClass)) | ||
); | ||
|
||
$progressBar->advance(); | ||
} | ||
|
||
$progressBar->finish(); | ||
|
||
$this->line(PHP_EOL); | ||
$this->line('Cached '.count($dataClasses).' data classes'); | ||
|
||
if ($this->option('show-classes')) { | ||
$this->table( | ||
['Data Class'], | ||
array_map(fn (string $dataClass) => [$dataClass], $dataClasses) | ||
); | ||
} | ||
} | ||
} |
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
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
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 |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
|
||
namespace Spatie\LaravelData\Support\Caching; | ||
|
||
use Spatie\LaravelData\Support\DataClass; | ||
use Spatie\LaravelData\Support\DataConfig; | ||
|
||
class CachedDataConfig extends DataConfig | ||
{ | ||
protected ?DataStructureCache $cache = null; | ||
|
||
public function __construct() | ||
{ | ||
parent::__construct([ | ||
'rule_inferrers' => [], | ||
'transformers' => [], | ||
'casts' => [], | ||
]); // Ensure the parent object is constructed empty, todo v4: remove this and use a better constructor with factory | ||
} | ||
|
||
public function getDataClass(string $class): DataClass | ||
{ | ||
return $this->cache?->getDataClass($class) ?? parent::getDataClass($class); | ||
} | ||
|
||
public function setCache(DataStructureCache $cache): self | ||
{ | ||
$this->cache = $cache; | ||
|
||
return $this; | ||
} | ||
|
||
public static function initialize( | ||
DataConfig $dataConfig | ||
): self { | ||
$cachedConfig = new self(); | ||
|
||
$cachedConfig->ruleInferrers = $dataConfig->ruleInferrers; | ||
$cachedConfig->transformers = $dataConfig->transformers; | ||
$cachedConfig->casts = $dataConfig->casts; | ||
|
||
$cachedConfig->dataClasses = []; | ||
$cachedConfig->resolvedDataPipelines = []; | ||
|
||
$dataConfig->morphMap->merge($cachedConfig->morphMap); | ||
|
||
return $cachedConfig; | ||
} | ||
} |
Oops, something went wrong.