Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Contracts Laravel Package

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.

View on GitHub
Deep Wiki
Context7
## 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"
  1. Core Concepts

    • The package provides a declarative contract-first approach for defining API/Service Agreements.
    • Focuses on runtime validation of method signatures, return types, and constraints.
    • New in 4.5.0: Added support for a locale field in AnzuUser (if applicable to your use case).
    • Integrates with Laravel’s container for dependency injection and facades for fluent usage.
  2. 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'
        ]);
    
  3. 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
        });
    }
    
  4. Validate Usage Inject the contract-validated service:

    use AnzuSystems\Contracts\Facades\ContractValidator;
    
    $validator = ContractValidator::make('UserService');
    $userService = $validator->validate(new UserService());
    

Implementation Patterns

1. Contract Definition Workflows

Basic Contract

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']
    ]);

Grouped Methods (API Endpoints)

Contract::make('Api\V1\AuthController')
    ->group('auth', [
        'login' => ['params' => ['credentials' => 'array', 'locale' => ['type' => 'string', 'nullable' => true]], 'returns' => 'string'],
        'logout' => ['params' => [], 'returns' => 'void']
    ]);

Dynamic Contracts (Runtime)

$dynamicContract = Contract::dynamic('DynamicService')
    ->method('process', [
        'params' => ['data' => 'mixed', 'locale' => ['type' => 'string', 'nullable' => true]], // Dynamic type with locale
        'returns' => 'mixed'
    ]);

2. Integration with Laravel

Service Provider Binding

// app/Providers/AppServiceProvider.php
public function register()
{
    $this->app->when('UserService')
        ->needs('$contract')
        ->give(function () {
            return Contract::find('UserService');
        });
}

Middleware for Contract Validation

// app/Http/Middleware/ValidateContract.php
public function handle($request, Closure $next)
{
    $service = app('UserService');
    $validator = ContractValidator::make('UserService');
    $validator->validate($service);

    return $next($request);
}

Facade Usage

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());
}

3. Testing Contracts

Unit Testing

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));
}

Mocking Contracts

$mock = Mockery::mock('UserService');
$validator = ContractValidator::make('UserService');
$validator->validate($mock); // Ensures mock adheres to contract, including locale fields

4. Extending Contracts

Custom Validators for Locale

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,
],

Event-Based Extensions

// Listen for contract violations
Contract::onViolation(function ($contractName, $method, $error) {
    Log::error("Contract violation in {$contractName}->{$method}: {$error}");
});

Gotchas and Tips

Common Pitfalls

  1. Circular Dependencies

    • Contracts may fail if services depend on each other in a circular manner.
    • Fix: Use lazy loading or split contracts into smaller, focused groups.
  2. Overly Strict Contracts

    • Defining rigid return types (e.g., UserModel) may break if the implementation changes.
    • Tip: Use interfaces or abstract classes for return types:
      'returns' => \App\Contracts\UserContract::class
      
  3. Performance Overhead

    • Runtime validation adds a small overhead. Disable in production if unnecessary:
      Contract::disableValidation(); // Use sparingly!
      
  4. Facade Caching

    • Contract facades cache instances. Clear cache if contracts change:
      php artisan config:clear
      
  5. Locale Field Handling

    • If using the new locale field, ensure your contracts explicitly define it as nullable or required to avoid validation errors.

Debugging Tips

  1. Enable Verbose Logging

    Contract::enableDebugMode();
    // Logs violations to storage/logs/contracts.log
    
  2. Inspect Contracts

    $contract = Contract::find('UserService');
    dd($contract->getMethods()); // Dump all defined methods, including locale fields
    
  3. Partial Validation Validate only specific methods:

    $validator = ContractValidator::make('UserService');
    $validator->validateMethod('createUser', $userService);
    

Configuration Quirks

  1. 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,
    ],
    
  2. Contract Storage

    • Contracts are stored in memory by default. For persistence, implement a custom storage driver:
      'storage' => [
          'driver' => 'database', // or 'redis', 'file'
          'table' => 'contracts',
      ],
      
  3. Autoloading Contracts Auto-register contracts from a directory:

    Contract::autoLoadFrom(__DIR__.'/contracts');
    

Extension Points

  1. Custom Contract Storage Implement AnzuSystems\Contracts\ContractsStorageInterface for custom storage backends.

  2. Plugin System Extend contract behavior via events:

    Contract::on('beforeValidate', function ($contract, $service) {
        // Pre-validation logic, e.g., set default locale
    });
    
  3. IDE Support Generate PHPDoc blocks from contracts for better IDE autocom

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ilhamsyabani/laravel-volt-starter
thethunderturner/filament-latex
ghostcompiler/laravel-querybuilder
webrek/laravel-telescope-mongodb
anousss007/blatui
zatona-eg/zatona-eg-api
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat