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

56 autoloading enhancements #58

Merged
merged 14 commits into from
Apr 17, 2024
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