Skip to content

daycry/doctrine

Repository files navigation

Donate

Doctrine

Doctrine ORM 3 integration for CodeIgniter 4.

PHPUnit PHPStan Psalm Rector Code Style Coverage Status Downloads GitHub release (latest by date) GitHub stars GitHub license

Features

  • ORM integration via \Daycry\Doctrine\Doctrine and \Config\Services::doctrine().
  • Server-side DataTables Builder with safe operator parsing, whitelisted columns, and [><] / [IN] / [OR] validation.
  • CodeIgniter Debug Toolbar collector with optional Second-Level Cache (SLC) statistics badge.
  • Doctrine Second-Level Cache wired to the framework cache backend (file, Redis, Memcached, array).
  • getFromCacheOrQuery() cache-aside helper backed by the configured PSR-6 result cache.
  • Multi-database group support — get a separate Doctrine instance per Config\Database group.

Requirements

  • PHP ≥ 8.2
  • CodeIgniter ^4
  • Doctrine ORM ^3, DBAL ^4
  • Symfony Cache ^7

See composer.json for the complete dependency graph.

Documentation Index

Installation

composer require daycry/doctrine

Then publish the configuration:

php spark doctrine:publish

This copies Config/Doctrine.php into your app namespace and cli-config.php into the project root for use with the Doctrine ORM CLI.

Quick Start

As a service

$doctrine = \Config\Services::doctrine();
$user     = $doctrine->em->getRepository(\App\Models\Entity\User::class)->find(1);

As a helper

Add doctrine_helper to your BaseController::$helpers:

protected $helpers = ['doctrine_helper'];
$doctrine  = doctrine_instance();             // default DB group
$reporting = doctrine_instance('reporting');  // alternate DB group

Constructing manually

$doctrine = new \Daycry\Doctrine\Doctrine();
$user     = $doctrine->em->getRepository(\App\Models\Entity\User::class)->find(1);

Manual Result Caching

getFromCacheOrQuery() is autoloaded as a global function (no use is needed beyond the function import). It looks up $cacheKey in the configured result cache pool and falls back to the closure on miss.

use function Daycry\Doctrine\Helpers\getFromCacheOrQuery;

$rows = getFromCacheOrQuery(
    cacheKey: 'projects_list_v1',
    ttl: 300,
    queryFn: fn () => $doctrine->em
        ->createQueryBuilder()
        ->select('p')
        ->from(\App\Models\Entity\Project::class, 'p')
        ->getQuery()
        ->getArrayResult(),
);

When the result cache is disabled (Config\Doctrine::$resultsCache = false) the closure runs every time. PSR-6 reserves the characters {}()/\@: in cache keys — avoid them.

See docs/usage.md for advanced API: getEm(), reOpen(), multi-database groups, Services::resetDoctrine(), and more.

Doctrine ORM CLI

Use the generated cli-config.php from the project root:

php cli-config.php orm:convert-mapping --namespace="App\Models\Entity\\" --force --from-database annotation .
php cli-config.php orm:generate-entities .
php cli-config.php orm:generate-proxies app/Models/Proxies

If you encounter the JMS Serializer error "The annotation @JMS\Serializer\Annotation\ExclusionPolicy was never imported", run composer dump-autoload to refresh annotation discovery.

DataTables

$datatables = (new \Daycry\Doctrine\DataTables\Builder())
    ->withColumnAliases([
        'id'   => 'p.id',
        'name' => 'p.name',
    ])
    ->withSearchableColumns(['p.name'])
    ->withCaseInsensitive(true)
    ->withMaxFilterValues(500) // cap [IN] / [OR] value lists; default 500
    ->withQueryBuilder(
        $this->doctrine->em->createQueryBuilder()
            ->select('p.id, p.name')
            ->from(\App\Models\Entity\Project::class, 'p'),
    )
    ->withRequestParams($this->request->getGet());

return $this->response->setJSON($datatables->getResponse());

If pagination throws "Not all identifier properties can be found in the ResultSetMapping", set ->setUseOutputWalkers(false) on the Builder.

Search modes

The Builder supports bracket-prefixed operators per column:

[%]   (LIKE, default)   [=]   [!=]   [>]   [<]   [IN]   [OR]   [><]

Synonyms [LIKE] and [%%] map to [%]. Unknown prefixes silently fall back to [%]. The DataTables regex: true flag is not supported — sending it raises InvalidArgumentException.

See docs/search_modes.md for the full operator matrix, validation rules, case-insensitivity behaviour and examples.

Debug Toolbar

A DoctrineCollector automatically captures every DBAL query so you can inspect them in the CodeIgniter Debug Toolbar.

  1. Register the collector in app/Config/Toolbar.php:

    public $collectors = [
        // ...
        \Daycry\Doctrine\Debug\Toolbar\Collectors\DoctrineCollector::class,
    ];
  2. Use Doctrine as usual — the middleware self-registers when you instantiate the service.

For long-running CLI workers you can cap the in-memory query log:

\Config\Services::doctrineCollector()->setMaxQueries(500); // FIFO; 0 disables the cap

See docs/debug_toolbar.md for the full collector API, the SLC stats badge, and the per-request reset filter.

Second-Level Cache (SLC)

Doctrine's Second-Level Cache reuses the framework cache backend (file / Redis / Memcached / array) and its ttl. Enable in app/Config/Doctrine.php:

public bool $secondLevelCache           = true;
public bool $secondLevelCacheStatistics = true;  // optional: hits/misses/puts badge
public ?int $secondLevelCacheTtl        = null;   // null = inherit Config\Cache::$ttl; 0 = no expiry

To reset SLC statistics at the start of every request (useful in development to read per-request hit ratios in the toolbar), register the filter:

// app/Config/Filters.php
public array $globals = [
    'before' => [
        \Daycry\Doctrine\Debug\Filters\DoctrineSlcReset::class,
    ],
];

The filter is a no-op unless secondLevelCacheStatistics is enabled.

See docs/second_level_cache.md and docs/second_level_cache_stats.md for full details.

Development

Available Composer scripts for contributors:

composer test          # PHPUnit test suite
composer phpstan       # PHPStan (level 6)
composer psalm         # Psalm static analysis
composer rector        # Rector dry-run
composer analyze       # phpstan + psalm + rector
composer cs            # PHP-CS-Fixer dry-run
composer cs-fix        # PHP-CS-Fixer apply

License

MIT. Issues and PRs welcome at https://github.com/daycry/doctrine.

About

Doctrine for Codeigniter 4

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors