php-standard-library/interoperability
Lightweight PHP interoperability helpers in the php-standard-library ecosystem. Provides small, standards-oriented utilities to bridge common interfaces and behaviors between components, improving compatibility and reuse without pulling in heavy dependencies.
Installation:
composer require php-standard-library/interoperability
Add to composer.json under require or require-dev depending on use case.
First Use Case:
Convert a native PHP DateTime to a PSL DateTimeInterface (or vice versa) for cross-library compatibility.
use PhpStandardLibrary\Interoperability\DateTimeConverter;
$converter = new DateTimeConverter();
$nativeDateTime = new \DateTime('now');
$pslDateTime = $converter->toPsl($nativeDateTime); // PSL DateTimeInterface
$nativeDateTimeAgain = $converter->toNative($pslDateTime); // Back to \DateTime
Where to Look First:
src/Interfaces/ for available contracts (e.g., DateTimeInterface, MessageInterface).src/Converters/ for utility classes to bridge PHP stdlib and PSL types.Adapter Pattern for Third-Party Libraries: Create adapters to wrap non-PSL/Laravel libraries into PSL interfaces.
use PhpStandardLibrary\Interoperability\MessageInterface;
use Symfony\Component\Mailer\MailerInterface as SymfonyMailer;
class SymfonyMailerAdapter implements MessageInterface
{
public function __construct(private SymfonyMailer $mailer) {}
public function send(string $message): void
{
$this->mailer->send($message);
}
}
Laravel Service Binding: Bind PSL interfaces to Laravel’s container for dependency injection.
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->bind(
\PhpStandardLibrary\Interoperability\MessageInterface::class,
\App\Adapters\SymfonyMailerAdapter::class
);
}
Cross-Cutting Concerns: Standardize interfaces for logging, messaging, or caching.
// Use PSL LoggerInterface in a service
public function __construct(private \PhpStandardLibrary\Interoperability\LoggerInterface $logger) {}
Data Conversion: Use converters for type-safe interactions between PSL and native PHP.
$converter = new \PhpStandardLibrary\Interoperability\DateTimeConverter();
$pslDate = $converter->toPsl(new \DateTime());
Microservice Integration:
OrderServiceInterface).Legacy System Modernization:
Logger implementations with LoggerInterface.ArrayConverter for DTOs).Testing:
$this->mock(\PhpStandardLibrary\Interoperability\MessageInterface::class)
->shouldReceive('send')
->once();
Leverage Laravel’s Facades: Create facades for PSL interfaces to maintain Laravel-like syntax.
// app/Facades/PSL.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class PSL extends Facade
{
protected static function getFacadeAccessor()
{
return \PhpStandardLibrary\Interoperability\MessageInterface::class;
}
}
Usage: PSL::send($message).
Compose with Laravel’s Contracts: Extend PSL interfaces to add Laravel-specific methods.
use PhpStandardLibrary\Interoperability\LoggerInterface;
interface LaravelLoggerInterface extends LoggerInterface
{
public function logToMonitor(string $level, string $message);
}
Performance Optimization: Cache converter instances if used frequently (e.g., in request pipelines).
$this->app->singleton(\PhpStandardLibrary\Interoperability\DateTimeConverter::class);
Contract Collisions:
Illuminate\Contracts may overlap with PSL interfaces (e.g., LoggerInterface).App\Contracts\LoggerInterface) or alias interfaces in config/app.php.'aliases' => [
'PSLLogger' => \PhpStandardLibrary\Interoperability\LoggerInterface::class,
],
Circular Dependencies:
Performance Overhead:
PSL → Native → PSL) can slow down hot paths.Xdebug and optimize critical paths.Testing Complexity:
Mockery or PHPUnit with clear expectations for interface methods.Laravel-Specific Quirks:
IlluminateLoggerToPSLAdapter).BindingResolutionException:
AppServiceProvider bindings and ensure adapters are registered.php artisan container:inspect PhpStandardLibrary\Interoperability\MessageInterface
Adapter Logic Errors:
public function __construct(private SymfonyMailer $mailer)
{
if (!$mailer instanceof SymfonyMailer) {
throw new \InvalidArgumentException('Expected SymfonyMailer instance.');
}
}
Data Conversion Issues:
DateTime → DateTimeInterface → Carbon).$converter = new \PhpStandardLibrary\Interoperability\DateTimeConverter();
$this->assertEquals(
$converter->toNative($converter->toPsl(new \DateTime('2023-01-01'))),
new \DateTime('2023-01-01')
);
Autoloading: Ensure PSL interfaces are autoloaded by running:
composer dump-autoload
Namespace Conflicts:
If PSL interfaces conflict with your project’s namespaces, use use statements explicitly.
use PhpStandardLibrary\Interoperability\LoggerInterface as PSLLoggerInterface;
Laravel’s config/app.php:
Add PSL interfaces to the providers or aliases array if needed for global access.
'aliases' => [
'PSL' => \PhpStandardLibrary\Interoperability\Facades\PSL::class,
],
Custom Interfaces: Extend PSL interfaces to add domain-specific methods.
use PhpStandardLibrary\Interoperability\MessageInterface;
interface DomainMessageInterface extends MessageInterface
{
public function setPriority(int $priority);
}
New Converters: Implement custom converters for unsupported types.
use PhpStandardLibrary\Interoperability\ConverterInterface;
class CustomTypeConverter implements ConverterInterface
{
public function toPsl($native): mixed { /* ... */ }
public function toNative($psl): mixed { /* ... */ }
}
Adapter Composition: Chain adapters for complex transformations.
class CompositeAdapter implements MessageInterface
{
public function __construct(
private MessageInterface $primary,
private MessageInterface $fallback
) {}
public function send(string $message): void
{
try {
$this->primary->send($message);
} catch (\Exception $e) {
$this->fallback->send($message);
}
}
}
Laravel Events: Dispatch PSL events using Laravel’s event system.
use PhpStandardLibrary\Interoperability\EventInterface;
class PSLEventDispatcher
{
How can I help you explore Laravel packages today?