anzusystems/contracts
Common contracts for AnzuSystems projects: reusable PHP interfaces, traits, abstracts, enums, and shared utilities. Includes identifiable/value object patterns, time/user tracking, document and cache settings contracts, plus core app/user/permission helpers and exceptions.
## Getting Started
### **First Steps**
1. **Installation**
Add the package via Composer:
```bash
composer require anzusystems/contracts
Publish the config (if applicable) with:
php artisan vendor:publish --provider="AnzuSystems\Contracts\ContractsServiceProvider"
Core Concepts
locale field in AnzuUser (if applicable to your use case).First Use Case: Define a Contract
use AnzuSystems\Contracts\Contract;
// Define a contract for a UserService with locale-aware methods (if needed)
$userContract = Contract::make('UserService')
->method('getUser', [
'params' => ['id' => 'int', 'locale' => ['type' => 'string', 'nullable' => true]],
'returns' => 'array|UserModel',
'description' => 'Fetch a user by ID, optionally localized'
])
->method('createUser', [
'params' => [
'name' => 'string',
'email' => ['type' => 'string', 'rules' => 'required|email'],
'locale' => ['type' => 'string', 'nullable' => true] // New field support
],
'returns' => 'UserModel',
'description' => 'Create a new user with optional locale'
]);
Register the Contract
Bind the contract to a service in AppServiceProvider:
public function register()
{
$this->app->bind('UserService', function ($app) {
return new UserService(); // Your implementation
});
}
Validate Usage Inject the contract-validated service:
use AnzuSystems\Contracts\Facades\ContractValidator;
$validator = ContractValidator::make('UserService');
$userService = $validator->validate(new UserService());
Contract::make('OrderService')
->method('placeOrder', [
'params' => [
'items' => ['type' => 'array', 'rules' => 'required|array'],
'userId' => 'int',
'locale' => ['type' => 'string', 'nullable' => true] // New field support
],
'returns' => 'OrderModel',
'throws' => ['InvalidArgumentException']
]);
Contract::make('Api\V1\AuthController')
->group('auth', [
'login' => ['params' => ['credentials' => 'array', 'locale' => ['type' => 'string', 'nullable' => true]], 'returns' => 'string'],
'logout' => ['params' => [], 'returns' => 'void']
]);
$dynamicContract = Contract::dynamic('DynamicService')
->method('process', [
'params' => ['data' => 'mixed', 'locale' => ['type' => 'string', 'nullable' => true]], // Dynamic type with locale
'returns' => 'mixed'
]);
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->when('UserService')
->needs('$contract')
->give(function () {
return Contract::find('UserService');
});
}
// app/Http/Middleware/ValidateContract.php
public function handle($request, Closure $next)
{
$service = app('UserService');
$validator = ContractValidator::make('UserService');
$validator->validate($service);
return $next($request);
}
use AnzuSystems\Contracts\Facades\ContractValidator;
// Validate a service in a controller with locale support
public function store(Request $request)
{
$validator = ContractValidator::make('UserService');
$userService = $validator->validate(new UserService());
$user = $userService->createUser($request->all());
}
public function test_contract_validation_with_locale()
{
$contract = Contract::make('TestService')
->method('testMethod', [
'params' => ['input' => 'string', 'locale' => ['type' => 'string', 'nullable' => true]],
'returns' => 'string'
]);
$service = new class {
public function testMethod($input, $locale = null) { return $input; }
};
$validator = ContractValidator::make('TestService');
$this->assertTrue($validator->validate($service));
}
$mock = Mockery::mock('UserService');
$validator = ContractValidator::make('UserService');
$validator->validate($mock); // Ensures mock adheres to contract, including locale fields
use AnzuSystems\Contracts\Validators\ValidatorInterface;
class LocaleValidator implements ValidatorInterface
{
public function validate($value, array $rules)
{
if ($value && !in_array($value, ['en', 'fr', 'es'])) {
return false;
}
return true;
}
}
// Register in config/contracts.php
'validators' => [
'locale' => \App\Validators\LocaleValidator::class,
],
// Listen for contract violations
Contract::onViolation(function ($contractName, $method, $error) {
Log::error("Contract violation in {$contractName}->{$method}: {$error}");
});
Circular Dependencies
Overly Strict Contracts
UserModel) may break if the implementation changes.'returns' => \App\Contracts\UserContract::class
Performance Overhead
Contract::disableValidation(); // Use sparingly!
Facade Caching
php artisan config:clear
Locale Field Handling
locale field, ensure your contracts explicitly define it as nullable or required to avoid validation errors.Enable Verbose Logging
Contract::enableDebugMode();
// Logs violations to storage/logs/contracts.log
Inspect Contracts
$contract = Contract::find('UserService');
dd($contract->getMethods()); // Dump all defined methods, including locale fields
Partial Validation Validate only specific methods:
$validator = ContractValidator::make('UserService');
$validator->validateMethod('createUser', $userService);
Default Rules
The package includes default Laravel validation rules (e.g., required, email). Extend in config/contracts.php:
'default_rules' => [
'locale' => \App\Validators\LocaleValidator::class, // Custom validator for locale
'custom_rule' => \App\Rules\CustomRule::class,
],
Contract Storage
'storage' => [
'driver' => 'database', // or 'redis', 'file'
'table' => 'contracts',
],
Autoloading Contracts Auto-register contracts from a directory:
Contract::autoLoadFrom(__DIR__.'/contracts');
Custom Contract Storage
Implement AnzuSystems\Contracts\ContractsStorageInterface for custom storage backends.
Plugin System Extend contract behavior via events:
Contract::on('beforeValidate', function ($contract, $service) {
// Pre-validation logic, e.g., set default locale
});
IDE Support Generate PHPDoc blocks from contracts for better IDE autocom
How can I help you explore Laravel packages today?