php-standard-library/foundation
A lightweight PHP foundation library offering common building blocks and utilities to bootstrap projects. Provides reusable helpers and core abstractions to reduce boilerplate and standardize patterns across apps and packages.
Installation:
composer require php-standard-library/foundation
Add to composer.json under require or require-dev if only for testing.
First Use Case: Replace a custom exception or utility with the package’s equivalents. Example:
use Foundation\Exceptions\InvalidArgumentException;
use Foundation\Ref\Ref;
// Replace custom validation logic
if (!is_string($input)) {
throw new InvalidArgumentException('Input must be a string');
}
// Use Ref for immutable references (alternative to Laravel's helpers)
$ref = Ref::of($value);
$ref->set(fn($v) => strtolower($v));
Where to Look First:
Foundation\Exceptions for standardized error handling.Foundation\Ref for immutable references and functional operations.Foundation\Invariant for runtime assertions (e.g., preconditions).Exception Handling:
Illuminate\Support\MessageBag or custom exceptions with Foundation\Exceptions\*.use Foundation\Exceptions\NotFoundException;
if (!$user = User::find($id)) {
throw new NotFoundException("User with ID {$id} not found");
}
Immutable References (Ref):
Ref for functional programming patterns (e.g., chaining operations).use Foundation\Ref\Ref;
$result = Ref::of($data)
->map(fn($item) => strtolower($item))
->filter(fn($item) => strlen($item) > 3)
->toArray();
Invariants:
use Foundation\Invariant\Invariant;
public function process(array $data): void {
Invariant::that($data)->isNotEmpty()->isArray();
// ...
}
Integration with Laravel:
$this->app->bind(
Foundation\LoggerInterface::class,
Illuminate\Contracts\Logging\Logger::class
);
Ref for request/response transformations.
public function handle($request, Closure $next) {
$response = $next($request);
return Ref::of($response)
->tap(fn($r) => $r->header('X-Processed', 'true'))
->toResponse();
}
Testing:
$this->mock(Foundation\LoggerInterface::class)
->shouldReceive('error')
->once();
Modular Migration:
App\Helpers\ArrayHelper with Foundation\ArrayHelper.Domain-Driven Design (DDD):
Result types (if available) for domain logic.use Foundation\Result\Result;
public function createOrder(OrderData $data): Result {
return Result::try(fn() => Order::create($data->toArray()));
}
Event Handling:
use Foundation\Exceptions\Exception;
use Illuminate\Support\Facades\Event;
class CustomException extends Exception {
public function __construct(string $message) {
parent::__construct($message);
Event::dispatch(new ExceptionOccurred($this));
}
}
Illuminate\Support\Collection instead of Foundation\Collection).composer.json to shorten imports:
"autoload": {
"psr-4": {
"App\\": "app/",
"Foundation\\": "vendor/php-standard-library/foundation/src"
}
}
FoundationExtensions package for Laravel-specific adaptations.Framework Assumptions:
Foundation\Str might lack Laravel’s Str::of() behavior.Performance Overhead:
Ref) can introduce closure overhead in tight loops.Naming Conflicts:
Foundation\Array might conflict with Laravel’s Illuminate\Support\Arr.Testing Quirks:
partialMock or interface-based mocks.Dependency Bloat:
composer why-not).class LaravelException extends Foundation\Exceptions\Exception {
public function render(): Response {
return response()->json(['error' => $this->getMessage()], 400);
}
}
Foundation\Invariant\ViolationException. Catch and log with Laravel’s report():
try {
Invariant::that($value)->isNotNull();
} catch (ViolationException $e) {
report($e);
abort(400, $e->getMessage());
}
config/foundation.php. Use environment variables or a custom config file:
// config/foundation.php
return [
'default_locale' => env('FOUNDATION_LOCALE', 'en_US'),
];
AppServiceProvider:
public function register() {
$this->app->singleton(Foundation\LoggerInterface::class, function ($app) {
return new Foundation\Logger($app['log']);
});
}
Custom Exceptions:
Foundation\Exceptions\Exception for Laravel-specific behavior:
class HttpException extends Foundation\Exceptions\Exception {
public function __construct(string $message, int $status = 400) {
parent::__construct($message);
$this->status = $status;
}
public function toResponse(): Response {
return response()->json(['error' => $this->message], $this->status);
}
}
Ref Monads:
Ref:
Ref::extend('laravel', function ($ref) {
return $ref->tap(fn($value) => Log::debug('Ref value:', $value));
});
Invariant Rules:
use Foundation\Invariant\Rule;
class LaravelRule extends Rule {
public static function isValidatedBy(string $validator): self {
return new static(fn($value) => validator($value)->validate());
}
}
CONTRIBUTING.md to your repo outlining how to use the package (e.g., "Always use Foundation\Result for domain operations").Foundation\Collection vs. Laravel’s Illuminate\Support\Collection in benchmarks.if (!function_exists('Foundation\Ref\Ref::of')) {
function Ref_of($value) { /* fallback */ }
}
How can I help you explore Laravel packages today?