- How can I use `draw/contracts` to decouple my Laravel services from Eloquent models?
- `draw/contracts` defines interfaces like `RepositoryInterface` or `ServiceInterface` that abstract database operations. Replace direct Eloquent calls with these contracts, then implement them in a separate layer (e.g., `UserRepository` for Eloquent, `UserApiRepository` for API clients). Laravel’s DI container resolves the interface to the concrete implementation.
- Will this package work with Laravel 10+? Are there version compatibility issues?
- The package is framework-agnostic, so it works with any Laravel version. However, if you use Laravel-specific contracts (e.g., `EloquentModelContract`), ensure your Laravel version supports the underlying PHP features (e.g., PHP 8.1+ for named arguments). Always check the package’s `composer.json` for PHP/Laravel constraints.
- Can I use these contracts for GraphQL APIs in Laravel (e.g., with Lighthouse or Nexus)?
- Yes. Define input/output contracts (e.g., `CreateUserInputContract`, `UserPayloadContract`) to enforce GraphQL schema validation. Use them in resolvers or services to ensure type safety. The package’s abstractions work well for both REST and GraphQL layers.
- How do I mock `draw/contracts` interfaces in PHPUnit/Pest tests without Laravel’s bootstrapping?
- Since the contracts are pure interfaces, mock them with PHPUnit’s `createMock()` or Pest’s `mock()`. For example: `$mockRepo = $this->mock(UserRepositoryInterface::class); $mockRepo->shouldReceive('find')->andReturn($user);`. This avoids Laravel’s service provider overhead in unit tests.
- Is there a recommended way to integrate these contracts with Laravel’s Service Provider?
- Manually bind interfaces to implementations in `register()`: `$this->app->bind(UserRepositoryInterface::class, UserRepository::class);`. For dynamic resolution (e.g., by tenant), use tags or context binding. The package doesn’t include Laravel-specific bindings, so you’ll need to define them yourself.
- How do I generate stubs or boilerplate for these contracts (e.g., for new repositories)?
- The package doesn’t include code generation tools, but you can create custom Artisan commands or use tools like `laravel-shift/blueprint` to scaffold contracts. Alternatively, define a base trait (e.g., `BaseRepositoryContract`) with common methods to reduce boilerplate.
- What’s the difference between `draw/contracts` and `laravelista/repository`? Should I switch?
- `draw/contracts` is a lightweight abstraction layer (interfaces only), while `laravelista/repository` provides concrete implementations for Eloquent. Use `draw/contracts` if you need framework-agnostic contracts or want to define custom interfaces. If you’re happy with Eloquent-based repositories, stick with `laravelista/repository`.
- Can I use these contracts outside Laravel (e.g., in Symfony or plain PHP)?
- Absolutely. The package is framework-agnostic. For Symfony, bind interfaces in `services.yaml` or use autowiring. In plain PHP, resolve dependencies via constructor injection. The abstractions are designed for reuse across frameworks.
- How do I handle breaking changes if the package evolves (e.g., new methods in interfaces)?
- Monitor the package’s changelog and update dependent classes incrementally. Use abstract base classes (e.g., `AbstractUserRepository`) to implement new methods with default behavior. For critical projects, consider forking the package to control contract evolution.
- Are there performance concerns with using interfaces instead of concrete classes directly?
- No. Interfaces add zero runtime overhead—they’re resolved at compile time (PHP 8+) or via DI containers. The performance impact is negligible compared to database queries or external API calls. The real benefit is decoupling, which improves maintainability and testability.