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

Pgsql Doctrine Random Function Laravel Package

aldaflux/pgsql-doctrine-random-function

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require aldaflux/pgsql-doctrine-random-function
    
  2. Configure Doctrine in config/packages/doctrine.yaml (Symfony 5+) or config/config.yml (older versions):
    doctrine:
        orm:
            dql:
                numeric_functions:
                    Random: Qbbr\PgsqlDoctrineRandomFunction\DQL\RandomFunction
    
  3. First use case: Fetch a random record from a table:
    $randomUser = $entityManager->createQueryBuilder()
        ->select('u')
        ->from('App\Entity\User', 'u')
        ->orderBy('RANDOM()')
        ->setMaxResults(1)
        ->getQuery()
        ->getOneOrNullResult();
    

Implementation Patterns

Core Workflows

  1. Random Sorting: Use RANDOM() in ORDER BY clauses to shuffle results:

    $query = $entityManager->createQueryBuilder()
        ->select('p')
        ->from('App\Entity\Product', 'p')
        ->orderBy('RANDOM()')
        ->getQuery();
    
  2. Random Sampling: Combine with setMaxResults() for pagination-like randomness:

    $randomProducts = $entityManager->createQueryBuilder()
        ->select('p')
        ->from('App\Entity\Product', 'p')
        ->orderBy('RANDOM()')
        ->setMaxResults(5)
        ->getQuery()
        ->getResult();
    
  3. Random Seeding: For reproducible randomness, use setRandomSeed() (PostgreSQL-specific):

    $query = $entityManager->createQueryBuilder()
        ->select('u')
        ->from('App\Entity\User', 'u')
        ->orderBy('RANDOM(42)') // Seed = 42
        ->getQuery();
    
  4. Dynamic Randomness in Repositories: Create a repository method for reusable random queries:

    // src/Repository/UserRepository.php
    public function findRandomUsers(int $limit = 10): array
    {
        return $this->createQueryBuilder('u')
            ->orderBy('RANDOM()')
            ->setMaxResults($limit)
            ->getQuery()
            ->getResult();
    }
    
  5. Random Joins: Apply randomness to joined tables:

    $query = $entityManager->createQueryBuilder()
        ->select('u, p')
        ->from('App\Entity\User', 'u')
        ->leftJoin('u.products', 'p')
        ->orderBy('RANDOM()')
        ->getQuery();
    

Integration Tips

  • Hybrid Queries: Combine with native SQL for complex random logic:
    $query = $entityManager->createNativeQuery(
        'SELECT * FROM users ORDER BY RANDOM() LIMIT 10'
    );
    
  • Caching: Cache random results if the dataset is static (e.g., product catalogs):
    $cacheKey = 'random_products_' . md5(filemtime(__FILE__));
    $randomProducts = $entityManager->getCache()->fetch($cacheKey, function() use ($entityManager) {
        return $entityManager->createQueryBuilder()
            ->select('p')
            ->from('App\Entity\Product', 'p')
            ->orderBy('RANDOM()')
            ->setMaxResults(10)
            ->getQuery()
            ->getResult();
    });
    
  • API Endpoints: Use for "random feature" endpoints:
    // src/Controller/RandomController.php
    public function randomFeature(EntityManagerInterface $em): JsonResponse
    {
        $feature = $em->getRepository(Feature::class)
            ->findRandomFeatures(1)
            ->first();
    
        return new JsonResponse(['feature' => $feature]);
    }
    

Gotchas and Tips

Pitfalls

  1. Performance:

    • ORDER BY RANDOM() can be slow on large tables. Use indexes on filtered columns first:
      // Bad: Full table scan
      $query->orderBy('RANDOM()');
      
      // Better: Filter first, then randomize
      $query->where('u.active = :active')
            ->setParameter('active', true)
            ->orderBy('RANDOM()');
      
    • For very large tables, consider materialized views or pre-computed random samples.
  2. Doctrine Version:

    • Requires Doctrine ORM ≥2.2.0. Test with your version to avoid ClassNotFoundException.
  3. PostgreSQL-Specific:

    • The RANDOM() function is PostgreSQL-only. This package will not work with MySQL, SQLite, or other databases. Ensure your DATABASE_URL points to PostgreSQL.
  4. QueryBuilder Limitation:

    • The RANDOM() function cannot be used in HAVING or subqueries directly. Workaround: Use native SQL or fetch results first:
      // Workaround for complex cases
      $results = $query->getResult();
      $filtered = array_filter($results, fn($item) => $item->getPrice() > 100);
      
  5. Seeding Behavior:

    • Without a seed, RANDOM() returns a different value on every query. For reproducibility, always use RANDOM(seed):
      // Unpredictable
      $query->orderBy('RANDOM()');
      
      // Reproducible
      $query->orderBy('RANDOM(12345)');
      

Debugging

  1. Check Configuration:

    • Verify the numeric_functions key in doctrine.yaml is correctly set. A misconfiguration will silently fail (no error, but RANDOM() won’t work).
  2. Enable SQL Logging:

    • Debug queries to confirm the RANDOM() function is being generated:
      $query->getQueryPart('orderBy'); // Should show "RANDOM()"
      
    • Or enable Doctrine SQL logging in config/packages/dev/doctrine.yaml:
      doctrine:
          dbal:
              logging: true
              profiling: true
      
  3. Fallback for Non-PostgreSQL:

    • If accidentally used with another database, catch the exception:
      try {
          $query->orderBy('RANDOM()');
      } catch (\Doctrine\ORM\Query\QueryException $e) {
          // Fallback logic (e.g., use a different random method)
      }
      

Extension Points

  1. Custom Random Functions:

    • Extend the base class to add seeded or weighted randomness:
      // src/DQL/WeightedRandomFunction.php
      namespace App\DQL;
      
      use Qbbr\PgsqlDoctrineRandomFunction\DQL\RandomFunction as BaseRandomFunction;
      
      class WeightedRandomFunction extends BaseRandomFunction
      {
          public function parse(\Doctrine\ORM\Query\Parser $parser)
          {
              $parser->match(Lexer::T_IDENTIFIER);
              $parser->match(Lexer::T_OPEN_PARENTHESIS);
              $weights = $parser->StringPrimary();
              $parser->match(Lexer::T_COMMA);
              $parser->match(Lexer::T_CLOSE_PARENTHESIS);
      
              $this->weightExpression = $weights;
              return $this;
          }
      
          public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
          {
              return 'RANDOM() * (' . $this->weightExpression . ')';
          }
      }
      
    • Register in doctrine.yaml:
      doctrine:
          orm:
              dql:
                  numeric_functions:
                      WeightedRandom: App\DQL\WeightedRandomFunction
      
  2. Database-Specific Logic:

    • Override the SQL generation to support PostgreSQL-specific features like TABLESAMPLE:
      public function getSql(SqlWalker $sqlWalker)
      {
          return 'TABLESAMPLE SYSTEM(' . $sqlWalker->walkArithmeticPrimary($this->expr) . ')';
      }
      
  3. Integration with QueryBuilder Methods:

    • Create a custom QueryBuilder method for reusable random queries:
      // src/Doctrine/QueryBuilderExtensions.php
      namespace App\Doctrine;
      
      use Doctrine\ORM\QueryBuilder;
      
      class QueryBuilderExtensions
      {
          public function random(QueryBuilder $qb, string $alias, int $limit = 10)
          {
              return $qb->orderBy("RANDOM()")
                        ->setMaxResults($limit);
          }
      }
      
    • Use via a service or trait:
      // src/Repository/BaseRepository.php
      trait RandomQueryTrait
      {
          public function findRandom(int $limit = 10)
          {
              return $this->createQueryBuilder('e')
                          ->
      
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.
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
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle