Skip to content

Commit

Permalink
56 autoloading enhancements (#58)
Browse files Browse the repository at this point in the history
* Remove cache:clearing hook.

* Fix styling

* Autoload ignore & custom filter callback.

* Normalize filter paths to forward slashes.

* Fix styling

* Update config and readme.

* Change wording.

* Corrected autoload_ignore config key.

* Fix styling

* Update default migrations ignore folder.

* Typo.

* Another typo.

* Ensure config sample in readme is up-to-date.

* Add new autoload_ignore key to upgrade stub.

---------

Co-authored-by: JasperTey <[email protected]>
  • Loading branch information
JasperTey and JasperTey authored Apr 17, 2024
1 parent ad0605a commit 7f9edea
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 41 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to `laravel-ddd` will be documented in this file.

## [Unversioned]
### Added
- Ability to ignore folders during autoloading via config(`ddd.autoload_ignore`), or register a custom filter callback via `DDD::filterAutoloadPathsUsing(callable $filter)`.

### Changed
- Internal: Domain cache is no longer quietly cleared on laravel's `cache:clearing` event, so that `ddd:cache` yields consistent results no matter which order it runs in production (before or after `cache:clear` or `optimize:clear` commands).

## [1.1.0] - 2024-04-07
### Added
- Add `ddd:class` generator extending Laravel's `make:class` (Laravel 11 only).
Expand Down
64 changes: 52 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,27 @@ When `ddd.autoload.factories` is enabled, the package will register a custom fac

If your application implements its own factory discovery using `Factory::guessFactoryNamesUsing()`, you should set `ddd.autoload.factories` to `false` to ensure it is not overridden.

### Ignoring Paths During Autoloading
To specify folders or paths that should be skipped during autoloading discovery, add them to the `ddd.autoload_ignore` configuration option. By default, the `Tests` and `Migrations` folders are ignored.
```php
'autoload_ignore' => [
'Tests',
'Database/Migrations',
],
```

Paths specified here are relative to the root of each domain. e.g., `src/Domain/Invoicing/{path-to-ignore}`. If more advanced filtering is needed, a callback can be registered using `DDD::filterAutoloadPathsUsing(callback $filter)` in your AppServiceProvider's boot method:
```php
use Lunarstorm\LaravelDDD\Facades\DDD;
use Symfony\Component\Finder\SplFileInfo;

DDD::filterAutoloadPathsUsing(function (SplFileInfo $file) {
if (basename($file->getRelativePathname()) === 'functions.php') {
return false;
}
});
```

### Disabling Autoloading
You may disable autoloading by setting the respective autoload options to `false` in the configuration file as needed, or by commenting out the autoload configuration entirely.
```php
Expand All @@ -221,11 +242,14 @@ You may disable autoloading by setting the respective autoload options to `false
// 'factories' => true,
// ],
```

<a name="autoloading-in-production"></a>

## Autoloading in Production
In production, you should cache the autoload manifests using the `ddd:cache` command as part of your application's deployment process. This will speed up the auto-discovery and registration of domain providers and commands. The `ddd:clear` command may be used to clear the cache if needed.

<a name="config-file"></a>

## Configuration File
This is the content of the published config file (`ddd.php`):

Expand Down Expand Up @@ -356,34 +380,50 @@ return [
*/
'autoload' => [
/**
* When enabled, any class in the domain layer extending
* `Illuminate\Support\ServiceProvider` will be
* auto-registered as a service provider
* When enabled, any class within the domain layer extending `Illuminate\Support\ServiceProvider`
* will be auto-registered as a service provider
*/
'providers' => true,

/**
* When enabled, any class in the domain layer extending
* `Illuminate\Console\Command` will be auto-registered
* as a command when running in console.
* When enabled, any class within the domain layer extending `Illuminate\Console\Command`
* will be auto-registered as a command when running in console.
*/
'commands' => true,

/**
* When enabled, a custom policy discovery callback will be
* registered to resolve policy names for domain models,
* or fallback to Laravel's default otherwise.
* When enabled, the package will register a custom policy discovery callback to resolve policy names
* for domain models, and fallback to Laravel's default for all other cases.
*/
'policies' => true,

/**
* When enabled, a custom policy discovery callback will be
* registered to resolve factory names for domain models,
* or fallback to Laravel's default otherwise.
* When enabled, the package will register a custom factory discovery callback to resolve factory names
* for domain models, and fallback to Laravel's default for all other cases.
*/
'factories' => true,
],

/*
|--------------------------------------------------------------------------
| Autoload Ignore Folders
|--------------------------------------------------------------------------
|
| Folders that should be skipped during autoloading discovery,
| relative to the root of each domain.
|
| e.g., src/Domain/Invoicing/<folder-to-ignore>
|
| If more advanced filtering is needed, a callback can be registered
| using the `DDD::filterAutoloadPathsUsing(callback $filter)` in
| the AppServiceProvider's boot method.
|
*/
'autoload_ignore' => [
'Tests',
'Database/Migrations',
],

/*
|--------------------------------------------------------------------------
| Caching
Expand Down
20 changes: 20 additions & 0 deletions config/ddd.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,26 @@
'factories' => true,
],

/*
|--------------------------------------------------------------------------
| Autoload Ignore Folders
|--------------------------------------------------------------------------
|
| Folders that should be skipped during autoloading discovery,
| relative to the root of each domain.
|
| e.g., src/Domain/Invoicing/<folder-to-ignore>
|
| If more advanced filtering is needed, a callback can be registered
| using `DDD::filterAutoloadPathsUsing(callback $filter)` in
| the AppServiceProvider's boot method.
|
*/
'autoload_ignore' => [
'Tests',
'Database/Migrations',
],

/*
|--------------------------------------------------------------------------
| Caching
Expand Down
20 changes: 20 additions & 0 deletions config/ddd.php.stub
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,26 @@ return [
'factories' => true,
],

/*
|--------------------------------------------------------------------------
| Autoload Ignore Folders
|--------------------------------------------------------------------------
|
| Folders that should be skipped during autoloading discovery,
| relative to the root of each domain.
|
| e.g., src/Domain/Invoicing/<folder-to-ignore>
|
| If more advanced filtering is needed, a callback can be registered
| using `DDD::filterAutoloadPathsUsing(callback $filter)` in
| the AppServiceProvider's boot method.
|
*/
'autoload_ignore' => [
'Tests',
'Database/Migrations',
],

/*
|--------------------------------------------------------------------------
| Caching
Expand Down
28 changes: 28 additions & 0 deletions src/DomainManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Lunarstorm\LaravelDDD;

class DomainManager
{
/**
* The autoload path filter callback.
*
* @var callable|null
*/
protected $autoloadFilter;

public function __construct()
{
$this->autoloadFilter = null;
}

public function filterAutoloadPathsUsing(callable $filter): void
{
$this->autoloadFilter = $filter;
}

public function getAutoloadFilter(): ?callable
{
return $this->autoloadFilter;
}
}
18 changes: 18 additions & 0 deletions src/Facades/DDD.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Lunarstorm\LaravelDDD\Facades;

use Illuminate\Support\Facades\Facade;

/**
* @see \Lunarstorm\LaravelDDD\DomainManager
*
* @method static void filterAutoloadPathsUsing(callable $filter)
*/
class DDD extends Facade
{
protected static function getFacadeAccessor()
{
return \Lunarstorm\LaravelDDD\DomainManager::class;
}
}
16 changes: 0 additions & 16 deletions src/Facades/LaravelDDD.php

This file was deleted.

7 changes: 0 additions & 7 deletions src/LaravelDDD.php

This file was deleted.

10 changes: 6 additions & 4 deletions src/LaravelDDDServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Lunarstorm\LaravelDDD;

use Illuminate\Support\Facades\Event;
use Lunarstorm\LaravelDDD\Listeners\CacheClearSubscriber;
use Lunarstorm\LaravelDDD\Support\DomainAutoloader;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
Expand All @@ -12,6 +10,12 @@ class LaravelDDDServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
$this->app->scoped(DomainManager::class, function () {
return new DomainManager();
});

$this->app->bind('ddd', DomainManager::class);

/*
* This class is a Package Service Provider
*
Expand Down Expand Up @@ -69,7 +73,5 @@ public function packageBooted()
public function packageRegistered()
{
(new DomainAutoloader())->autoload();

Event::subscribe(CacheClearSubscriber::class);
}
}
27 changes: 25 additions & 2 deletions src/Support/DomainAutoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Lunarstorm\LaravelDDD\Factories\DomainFactory;
use Lunarstorm\LaravelDDD\ValueObjects\DomainObject;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Throwable;

class DomainAutoloader
Expand Down Expand Up @@ -122,6 +123,28 @@ protected function handleFactories(): void
});
}

protected static function finder($paths)
{
$filter = app('ddd')->getAutoloadFilter() ?? function (SplFileInfo $file) {
$pathAfterDomain = str($file->getRelativePath())
->replace('\\', '/')
->after('/')
->finish('/');

$ignoredFolders = collect(config('ddd.autoload_ignore', []))
->map(fn ($path) => Str::finish($path, '/'));

if ($pathAfterDomain->startsWith($ignoredFolders)) {
return false;
}
};

return Finder::create()
->files()
->in($paths)
->filter($filter);
}

protected static function discoverProviders(): array
{
$configValue = config('ddd.autoload.providers');
Expand All @@ -138,7 +161,7 @@ protected static function discoverProviders(): array
return [];
}

return Lody::classesFromFinder(Finder::create()->files()->in($paths))
return Lody::classesFromFinder(static::finder($paths))
->isNotAbstract()
->isInstanceOf(ServiceProvider::class)
->toArray();
Expand All @@ -162,7 +185,7 @@ protected static function discoverCommands(): array
return [];
}

return Lody::classesFromFinder(Finder::create()->files()->in($paths))
return Lody::classesFromFinder(static::finder($paths))
->isNotAbstract()
->isInstanceOf(Command::class)
->toArray();
Expand Down
Loading

0 comments on commit 7f9edea

Please sign in to comment.