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

Common Laravel Package

black/common

Common utilities for Black projects: an abstract Doctrine Manager helper with convenience methods plus simple specification classes (and/or/not). Install via Composer and reuse across apps needing lightweight Doctrine-oriented shared code.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation Add the package to your composer.json with a specific version (avoid @stable):

    composer require black/common:1.0.0
    

    Register a custom service provider (e.g., BlackCommonServiceProvider) in config/app.php:

    'providers' => [
        // ...
        App\Providers\BlackCommonServiceProvider::class,
    ],
    
  2. First Use Case: Basic Query Specification Use the DoctrineManager abstract class to wrap Doctrine’s EntityManager and apply specifications:

    // In a repository or service
    use Black\Common\Doctrine\Specification\AndSpecification;
    use Black\Common\Doctrine\Specification\NotSpecification;
    use Black\Common\Doctrine\Specification\FieldEquals;
    
    $doctrineManager = app(DoctrineManager::class);
    $spec = new AndSpecification(
        new NotSpecification(new FieldEquals('active', false)),
        new FieldEquals('role', 'admin')
    );
    
    $results = $doctrineManager->findBy($spec, User::class);
    
  3. Key Files to Inspect

    • vendor/black/common/src/Doctrine/AbstractManager.php: Abstract base for Doctrine operations.
    • vendor/black/common/src/Doctrine/Specification/: Specification classes (AndSpecification, OrSpecification, NotSpecification).
    • vendor/black/common/src/Doctrine/Specification/FieldSpecification.php: Base for field-based specs (e.g., FieldEquals, FieldGreaterThan).

Implementation Patterns

Usage Patterns

  1. Repository Layer Integration Extend the abstract DoctrineManager in a repository to encapsulate domain-specific queries:

    namespace App\Repositories;
    
    use Black\Common\Doctrine\AbstractManager;
    use App\Models\User;
    
    class UserRepository extends AbstractManager
    {
        public function findActiveAdmins()
        {
            $spec = new AndSpecification(
                new FieldEquals('active', true),
                new FieldEquals('role', 'admin')
            );
            return $this->findBy($spec, User::class);
        }
    }
    
  2. Dynamic Filtering in APIs Use specifications to build composable filters for API endpoints:

    // In a controller
    public function index(Request $request)
    {
        $spec = $this->buildFilterSpecification($request->query());
        $users = $this->userRepository->findBy($spec, User::class);
        return response()->json($users);
    }
    
    private function buildFilterSpecification(array $filters)
    {
        $specs = [];
        foreach ($filters as $field => $value) {
            $specs[] = new FieldEquals($field, $value);
        }
        return new AndSpecification(...$specs);
    }
    
  3. Admin Panel Filters Leverage OrSpecification for multi-criteria searches (e.g., search by name or email):

    $searchTerm = $request->input('q');
    $spec = new OrSpecification(
        new FieldContains('name', $searchTerm),
        new FieldContains('email', $searchTerm)
    );
    $results = $doctrineManager->findBy($spec, User::class);
    

Workflows

  1. Composing Complex Queries Chain specifications to build nested conditions:

    $spec = new AndSpecification(
        new FieldGreaterThan('created_at', '2023-01-01'),
        new OrSpecification(
            new FieldEquals('status', 'pending'),
            new AndSpecification(
                new FieldEquals('status', 'approved'),
                new FieldLessThan('value', 100)
            )
        )
    );
    
  2. Negation Logic Use NotSpecification to invert conditions (e.g., "not active"):

    $spec = new NotSpecification(new FieldEquals('active', true));
    $inactiveUsers = $doctrineManager->findBy($spec, User::class);
    
  3. Performance Optimization

    • Cache Specifications: Reuse specification objects for repeated queries.
    • Limit Results: Use findBy() with setMaxResults():
      $query = $doctrineManager->createQueryBuilder(User::class)
          ->where($spec->getDql())
          ->setMaxResults(50);
      

Integration Tips

  1. Laravel Service Container Bind the abstract DoctrineManager to a concrete implementation in your service provider:

    public function register()
    {
        $this->app->bind(
            DoctrineManager::class,
            fn() => new class($this->app['doctrine.orm.entity_manager']) extends AbstractManager {}
        );
    }
    
  2. Doctrine Event Listeners Extend the DoctrineManager to listen to Doctrine events (e.g., postLoad) for side effects:

    use Doctrine\ORM\Event\LifecycleEventArgs;
    
    public function postLoad(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();
        // Custom logic (e.g., lazy-loading)
    }
    
  3. Testing Mock the DoctrineManager in tests using interfaces or abstract classes:

    $mockManager = Mockery::mock(DoctrineManager::class);
    $mockManager->shouldReceive('findBy')
        ->withArgs([$spec, User::class])
        ->andReturn([$mockUser]);
    $this->app->instance(DoctrineManager::class, $mockManager);
    

Gotchas and Tips

Pitfalls

  1. Archived Package Risks

    • No Updates: The package is archived; assume no future compatibility fixes for Doctrine updates.
    • Security: No patches for Doctrine CVEs. Fork and maintain if critical.
    • Debugging: Undocumented internals may require reverse-engineering (e.g., Specification::getDql() logic).
  2. Doctrine Version Mismatch

    • The package may target an older Doctrine ORM version (e.g., ^2.5). Test with:
      composer why-not black/common
      
    • Workaround: Fork the package and update Doctrine dependencies.
  3. DQL Complexity

    • No toSql(): Unlike Laravel’s Query Builder, DQL lacks a direct toSql() method. Debug with:
      $query = $doctrineManager->createQuery($spec->getDql());
      $query->getSQL(); // Requires Doctrine 2.7+
      
    • Performance: Deeply nested specifications can generate unoptimized DQL. Use EXPLAIN in your database to check query plans.
  4. Laravel Integration Gaps

    • No Eloquent Support: The package is Doctrine ORM-only. Avoid mixing with Eloquent models.
    • Service Container: The abstract DoctrineManager requires manual binding to Laravel’s EntityManager.
  5. Specification Validation

    • No Built-in Validation: Specifications like FieldEquals don’t validate field existence. Add checks:
      if (!property_exists(User::class, $field)) {
          throw new \InvalidArgumentException("Field '$field' does not exist on User.");
      }
      

Debugging Tips

  1. Log DQL Queries Extend the DoctrineManager to log generated DQL:

    public function findBy(Specification $spec, string $entityClass)
    {
        $dql = $spec->getDql();
        \Log::debug("Generated DQL: $dql");
        return parent::findBy($spec, $entityClass);
    }
    
  2. Test Specifications Isolated Unit test specifications to ensure correct DQL generation:

    public function testAndSpecification()
    {
        $spec = new AndSpecification(
            new FieldEquals('active', true),
            new FieldEquals('role', 'admin')
        );
        $this->assertEquals(
            '(u.active = :d0 AND u.role = :d1)',
            $spec->getDql()
        );
    }
    
  3. Handle Doctrine Exceptions Wrap DoctrineManager calls in try-catch blocks for malformed DQL:

    try {
        $results = $doctrineManager->findBy($spec, User::class);
    } catch (\Doctrine\ORM\Query\QueryException $e) {
        \Log::error("Invalid specification DQL: " . $e->getMessage());
        throw new \RuntimeException("Query failed: " . $e->getMessage());
    }
    

Extension Points

  1. Custom Specifications Extend Black\Common\Doctrine\Specification\Specification to create domain-specific specs:
    class StatusInSpecification extends Specification
    {
        private $statuses;
    
        public function __construct(array $statuses)
        {
            $this->statuses = $statuses;
    
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.
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed