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

Doctrine Laravel Package

awaresoft/doctrine

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

Since this package is Symfony Doctrine-focused, Laravel developers will need to bridge it with Laravel's Eloquent or use it in a Symfony-based service layer. Here’s how to start:

  1. Install via Composer (if using Satis)

    composer require awaresoft/doctrine
    

    (Note: The package is not on Packagist; it’s hosted via Satis. Ensure your composer.json includes the Satis repo URL.)

  2. Symlink the Vendor (if modifying locally) Follow the README’s instructions to symlink /src/Awaresoft into your project. Run:

    php artisan vendor:publish --provider="Awaresoft\Doctrine\DoctrineServiceProvider" --tag="config"
    

    (If no provider exists, check the package’s src/ for a ServiceProvider class.)

  3. First Use Case: Query Filtering The package likely extends Doctrine’s query capabilities. Example:

    use Awaresoft\Doctrine\Query\FilterBuilder;
    
    // In a Laravel service or controller:
    $filter = new FilterBuilder();
    $filter->add('active', true); // Example: Filter active records
    $query = $entityManager->createQueryBuilder()
        ->where($filter->getExpression())
        ->getQuery();
    
  4. Laravel Integration Tip Wrap Doctrine calls in a Service Class to abstract Symfony dependencies:

    namespace App\Services;
    
    use Doctrine\ORM\EntityManagerInterface;
    use Awaresoft\Doctrine\Query\FilterBuilder;
    
    class DoctrineService {
        protected $em;
    
        public function __construct(EntityManagerInterface $em) {
            $this->em = $em;
        }
    
        public function getFilteredEntities(string $entityClass, array $filters) {
            $filter = new FilterBuilder();
            foreach ($filters as $field => $value) {
                $filter->add($field, $value);
            }
            return $this->em->createQueryBuilder()
                ->from($entityClass, 'e')
                ->where($filter->getExpression())
                ->getQuery()
                ->getResult();
        }
    }
    

    Register the service in Laravel’s IoC container:

    $this->app->bind(DoctrineService::class, function ($app) {
        return new DoctrineService($app->make(EntityManagerInterface::class));
    });
    

Implementation Patterns

1. Query Filtering & Dynamic Criteria

Pattern: Use FilterBuilder for reusable query conditions.

// Example: Dynamic "where" clauses
$filter = new FilterBuilder();
$filter->add('status', 'published') // Exact match
       ->add('created_at', '>=' . now()->subDays(7)->format('Y-m-d')) // Date range
       ->add('tags', 'like', '%php%'); // Partial match

$query = $this->em->createQueryBuilder()
    ->from(User::class, 'u')
    ->where($filter->getExpression())
    ->getQuery();

Laravel Tip: Convert Doctrine queries to Eloquent-like syntax for consistency:

public function scopeFilter($query, array $filters) {
    $filter = new FilterBuilder();
    foreach ($filters as $field => $value) {
        $filter->add($field, $value);
    }
    return $query->where($filter->getExpression());
}
// Usage: User::filter(['status' => 'active'])->get();

2. Entity Hydration & Custom Mappers

Pattern: Extend Doctrine’s hydration to return Laravel collections or DTOs.

use Awaresoft\Doctrine\Hydration\CustomHydrator;

$hydrator = new CustomHydrator();
$hydrator->addScalarMapping('id', 'user_id'); // Rename fields
$hydrator->addObjectMapping(User::class, 'user'); // Map to Eloquent model

$query = $this->em->createQuery('SELECT u FROM User u')
    ->setHydrationMode(CustomHydrator::HYDRATION_MODE);
$results = $query->getResult();

Laravel Tip: Use Hydrator in a repository pattern:

class UserRepository {
    public function findWithHydration(array $criteria) {
        $query = $this->em->createQueryBuilder()
            ->from(User::class, 'u')
            ->where(...);
        $hydrator = new CustomHydrator();
        $query->setHydrationMode($hydrator::HYDRATION_MODE);
        return $query->getResult();
    }
}

3. Event Listeners & Lifecycle Callbacks

Pattern: Hook into Doctrine events (e.g., prePersist, postLoad) via Symfony’s event system.

use Awaresoft\Doctrine\Event\LifecycleEventArgs;

$eventManager = $this->em->getEventManager();
$eventManager->addEventListener(
    'prePersist',
    function (LifecycleEventArgs $args) {
        $entity = $args->getEntity();
        if ($entity instanceof User) {
            $entity->setUpdatedAt(now());
        }
    }
);

Laravel Tip: Bind events in a service provider:

public function boot() {
    $this->app->booted(function () {
        $em = $this->app->make(EntityManagerInterface::class);
        $em->getEventManager()->addEventListener(
            'postLoad',
            function ($args) {
                // Post-load logic (e.g., lazy-loading relations)
            }
        );
    });
}

4. Bulk Operations

Pattern: Use Doctrine’s BulkOperation for efficient updates/deletes.

use Awaresoft\Doctrine\Bulk\BulkOperation;

$bulk = new BulkOperation($this->em);
$bulk->update(User::class)
     ->set('status', 'inactive')
     ->where('last_login < ?', new \DateTime('-30 days'))
     ->execute();

Laravel Tip: Wrap in a command for CLI usage:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Awaresoft\Doctrine\Bulk\BulkOperation;

class InactivateOldUsers extends Command {
    protected $signature = 'users:inactivate-old';
    public function handle() {
        $bulk = new BulkOperation($this->em);
        $bulk->update(User::class)
             ->set('status', 'inactive')
             ->where('last_login < ?', now()->subDays(30))
             ->execute();
        $this->info('Inactivated ' . $bulk->getAffectedCount() . ' users.');
    }
}

Gotchas and Tips

1. Backward Compatibility (BC) Pitfalls

  • Issue: The package enforces strict BC rules. Modifying methods or adding features may break dependent projects.
  • Tip: If extending the package:
    • Prefix new methods with internal or experimental.
    • Use interfaces for new features to avoid direct class modifications.
    • Example:
      interface FilterBuilderExtension {
          public function addOrCondition(string $field, $value);
      }
      

2. Dependency Conflicts

  • Issue: The package requires willdurand/faker-bundle (Symfony-specific) and assumes Doctrine ORM. Laravel’s Eloquent may clash.
  • Tip: Use a separate Symfony service container for Doctrine operations:
    // In a Symfony-compatible service
    $container = new Container();
    $container->loadFromExtension('doctrine', [
        'orm' => ['entity_managers' => ['default' => ['mappings' => [...]]]],
    ]);
    $em = $container->get('doctrine.orm.entity_manager');
    

3. Query Builder Quirks

  • Issue: FilterBuilder may generate SQL that differs from Eloquent’s expectations (e.g., table aliases).
  • Tip: Normalize queries before execution:
    $query = $this->em->createQueryBuilder()
        ->from(User::class, 'u')
        ->where($filter->getExpression())
        ->getQuery();
    $sql = $query->getSQL(); // Debug SQL
    $params = $query->getParameters();
    

4. Performance with Large Datasets

  • Issue: Bulk operations or complex filters can be slow without indexing.
  • Tip: Add Doctrine-specific indexes:
    # config/doctrine/orm/mappings/User.dcm.xml
    <entity name="App\Models\User">
        <indexes>
            <index name="IDX_USER_STATUS" columns="status"/>
            <index name="IDX_USER_LOGIN" columns="last_login"/>
        </indexes>
    </entity>
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor