Wrapper & Traits
Wrappers and utility traits to enrich native objects and add functionality.
Wrapper
SplFileInfo
Enriched wrapper of Symfony SplFileInfo (not PHP native SplFileInfo).
use Atournayre\Wrapper\SplFileInfo;
// Creation (requires 3 parameters from Symfony Finder)
$file = SplFileInfo::of(
file: '/absolute/path/to/file.txt',
relativePath: 'relative/path',
relativePathname: 'relative/path/file.txt'
);
// File information
$pathname = $file->pathname(); // Path object
$filename = $file->filename(); // Filename object
$filenameWithoutExt = $file->filenameWithoutExtension(); // StringType
$extension = $file->extension(); // Extension object
$size = $file->size(); // Memory object
// Path information
$relativePath = $file->relativePath(); // Path object
$relativePathname = $file->relativePathname(); // Path object
// Content
$contents = $file->contents(); // Content object
// Logging
$logData = $file->toLog(); // ['pathname' => '...', 'size' => '1.5 MB']
Return Types
All methods return typed value objects:
$pathname = $file->pathname(); // \Atournayre\Common\Types\File\Path
$filename = $file->filename(); // \Atournayre\Common\Types\File\Filename
$extension = $file->extension(); // \Atournayre\Common\Types\File\Extension
$contents = $file->contents(); // \Atournayre\Common\Types\File\Content
$size = $file->size(); // \Atournayre\Common\VO\Memory
Usage with Symfony Finder
SplFileInfo is designed to work with Symfony Finder:
use Symfony\Component\Finder\Finder;
use Atournayre\Wrapper\SplFileInfo;
$finder = new Finder();
$finder->files()->in('/path/to/dir');
foreach ($finder as $symfonyFile) {
// $symfonyFile is already a Symfony SplFileInfo
// Wrap it with our SplFileInfo if needed
$file = SplFileInfo::of(
file: $symfonyFile->getPathname(),
relativePath: $symfonyFile->getRelativePath(),
relativePathname: $symfonyFile->getRelativePathname()
);
$size = $file->size(); // Memory object
}
Traits
DependencyInjectionTrait
Inject EntityDependencyInjection into entities.
use Atournayre\Traits\DependencyInjectionTrait;
use Atournayre\DependencyInjection\EntityDependencyInjection;
class User
{
use DependencyInjectionTrait;
// Immutable pattern (preferred)
public function notifyCreation(): self
{
$user = $this->withDependencyInjection(
dependencyInjection: $this->dependencyInjection
);
// Access command bus, query bus, logger
$this->dependencyInjection->commandBus()->dispatch(command: $event);
$this->dependencyInjection->logger()->info(message: 'User created');
return $user;
}
// Mutable pattern (for Doctrine PostLoad)
#[ORM\PostLoad]
public function postLoad(EntityDependencyInjection $di): void
{
$this->setDependencyInjection(dependencyInjection: $di);
}
}
See Dependency Injection for details.
CommandMessageTrait
Self-dispatch commands in events.
use Atournayre\Traits\CommandMessageTrait;
use Atournayre\Common\AbstractCommandEvent;
final class UserCreatedEvent extends AbstractCommandEvent
{
use CommandMessageTrait;
private function __construct(private readonly User $user) {}
public static function new(User $user): self
{
return new self(user: $user);
}
public function user(): User
{
return $this->user;
}
}
// Self-dispatch via command bus
$event = UserCreatedEvent::new(user: $user);
$event->command(); // Dispatches via CommandBus
See Domain Events for details.
QueryMessageTrait
Self-dispatch queries in events.
use Atournayre\Traits\QueryMessageTrait;
use Atournayre\Common\AbstractQueryEvent;
final class FindUserEvent extends AbstractQueryEvent
{
use QueryMessageTrait;
private function __construct(private readonly int $userId) {}
public static function new(int $userId): self
{
return new self(userId: $userId);
}
public function userId(): int
{
return $this->userId;
}
}
// Self-dispatch via query bus
$event = FindUserEvent::new(userId: 123);
$user = $event->query(); // Dispatches via QueryBus and returns result
See Domain Events for details.
EnumTrait
Add utility methods to enums.
use Atournayre\Traits\EnumTrait;
enum Status: string
{
use EnumTrait;
case Active = 'active';
case Pending = 'pending';
case Inactive = 'inactive';
}
// Note: Check actual implementation for available methods
// EnumTrait may provide helper methods for enum manipulation
Usage Patterns
Dependency Injection in Entities
use Atournayre\Traits\DependencyInjectionTrait;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
class Order
{
use DependencyInjectionTrait;
#[ORM\PostLoad]
public function postLoad(EntityDependencyInjection $di): void
{
$this->setDependencyInjection(dependencyInjection: $di);
}
public function complete(): self
{
$order = $this->withDependencyInjection(
dependencyInjection: $this->dependencyInjection
);
// Log the event
$this->dependencyInjection->logger()->info(
message: 'Order completed',
context: ['order_id' => $this->id]
);
// Dispatch domain event
OrderCompletedEvent::new(order: $order)->command();
return $order;
}
}
Self-Dispatching Events
class UserService
{
public function register(string $email, string $password): User
{
$user = User::create(email: $email, password: $password);
// Event dispatches itself via CommandBus
UserRegisteredEvent::new(user: $user)->command();
return $user;
}
}
Tests
use PHPUnit\Framework\TestCase;
use Atournayre\Wrapper\SplFileInfo;
class SplFileInfoTest extends TestCase
{
public function testFileWrapper(): void
{
$file = SplFileInfo::of(
file: __FILE__,
relativePath: '',
relativePathname: basename(__FILE__)
);
$this->assertEquals('php', $file->extension()->value()->toString());
$this->assertGreaterThan(0, $file->size()->toBytes());
}
}