From 6a2dec21bb6a5bb0ab9f90123dcadc5e9b75608a Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Tue, 24 Mar 2026 11:49:54 +0000 Subject: [PATCH 1/5] Document PostgreSQL database support for Mautic 7.x Adds comprehensive developer documentation for PostgreSQL support: - Development setup: Added PostgreSQL configuration example alongside MySQL - Database compatibility: New section covering case-insensitive matching, column quoting, GROUP BY requirements, and platform detection - Testing: Added multi-database testing guidance with PostgreSQL config Co-Authored-By: Claude Opus 4.6 --- docs/development-environment/setup.rst | 23 ++++ docs/plugins/database.rst | 141 ++++++++++++++++++++++++- docs/testing/e2e_test_suite.rst | 58 ++++++++++ 3 files changed, 221 insertions(+), 1 deletion(-) diff --git a/docs/development-environment/setup.rst b/docs/development-environment/setup.rst index 44891d27..4b85ab10 100644 --- a/docs/development-environment/setup.rst +++ b/docs/development-environment/setup.rst @@ -20,6 +20,8 @@ You can also run the install process from command line: * Add a ``local.php`` file in ``app/config`` * Edit the ``local.php`` file using the following template (Mautic adapts to new local settings): +**MySQL/MariaDB configuration:** + .. code-block:: php 'bak_', ); +**PostgreSQL configuration:** + +.. code-block:: php + + 'pdo_pgsql', + 'db_host' => 'localhost', + 'db_table_prefix' => null, + 'db_port' => '5432', + 'db_name' => 'mautic', + 'db_user' => 'postgres', + 'db_password' => 'postgres_password', + 'db_backup_tables' => true, + 'db_backup_prefix' => 'bak_', + ); + +.. note:: + + PostgreSQL 16 or later is required for PostgreSQL support. Ensure the ``pdo_pgsql`` PHP extension is installed. + * Run the following command and add your own options: .. code-block:: bash diff --git a/docs/plugins/database.rst b/docs/plugins/database.rst index bcc43417..8e166533 100644 --- a/docs/plugins/database.rst +++ b/docs/plugins/database.rst @@ -363,4 +363,143 @@ Define migrations in the Plugin's ``Migrations`` directory. The file and class n :param array $columns: Array of columns to included in the index. :return: ``INDEX {tableName} ($columns...)`` statement - :returntype: string \ No newline at end of file + :returntype: string + +Database compatibility +********************** + +Mautic 7.x supports MySQL, MariaDB, and PostgreSQL. Follow these patterns to ensure your queries work across all platforms. + +Supported databases +=================== + +.. list-table:: + :widths: 30 30 40 + :header-rows: 1 + + * - Database + - Minimum version + - PHP extension + * - MySQL + - 8.0 + - ``pdo_mysql`` + * - MariaDB + - 10.6 + - ``pdo_mysql`` + * - PostgreSQL + - 16 + - ``pdo_pgsql`` + +.. vale off + +Case-insensitive string matching +================================ + +.. vale on + +MySQL and MariaDB use case-insensitive ``LIKE`` comparisons by default. PostgreSQL's ``LIKE`` is case-sensitive. Mautic provides helper methods in ``CommonRepository`` to handle this. + +**Using the helper methods:** + +.. code-block:: php + + // In a repository extending CommonRepository + $qb = $this->getEntityManager()->getConnection()->createQueryBuilder(); + + // Case-insensitive LIKE - uses ILIKE on PostgreSQL, LIKE on MySQL/MariaDB + $qb->andWhere( + $this->getILikeExpression($qb, 'l.email', ':search') + ); + + // Or wrap the column with LOWER() for case-insensitive comparison + $qb->andWhere( + $this->getLowerLikeExpression($qb, 'l.firstname', ':search') + ); + +**Available methods in CommonRepository:** + +- ``getILikeExpression(QueryBuilder $qb, string $column, string $parameter)``: Returns platform-appropriate case-insensitive ``LIKE`` expression +- ``getLowerLikeExpression(QueryBuilder $qb, string $column, string $parameter)``: Wraps the column with ``LOWER()`` for case-insensitive comparison +- ``isPostgreSql()``: Returns ``TRUE`` if connected to a PostgreSQL database + +.. vale off + +Column and alias quoting +======================== + +.. vale on + +PostgreSQL lowercases unquoted identifiers automatically. This causes issues with Mautic's ``camelCase`` column aliases. Always quote identifiers in raw SQL queries that use mixed-case names. + +**Use quoted identifiers for camelCase aliases:** + +.. code-block:: php + + // Correct - aliases are quoted + $qb->select('l.id, l.first_name AS "firstName", l.date_added AS "dateAdded"'); + + // Incorrect - PostgreSQL converts to lowercase + $qb->select('l.id, l.first_name AS firstName'); + +Doctrine's QueryBuilder handles quoting automatically when you use proper field mappings. You only need manual quoting for raw SQL or custom column aliases. + +.. vale off + +GROUP BY requirements +===================== + +.. vale on + +PostgreSQL enforces strict ``GROUP BY`` rules. Every column in the ``SELECT`` clause must appear in the ``GROUP BY`` clause or use an aggregate function. MySQL and MariaDB are more lenient by default. + +Mautic's Report Builder corrects ``GROUP BY`` clauses for PostgreSQL automatically. If you're building custom Reports or queries with aggregates, include all non-aggregated columns in the ``GROUP BY`` clause. + +**Correct pattern:** + +.. code-block:: php + + $qb->select('l.id, l.email, COUNT(e.id) as emailCount') + ->from('leads', 'l') + ->leftJoin('l', 'emails', 'e', 'e.lead_id = l.id') + ->groupBy('l.id, l.email'); // All non-aggregate columns included + +**Incorrect pattern:** + +.. code-block:: php + + // This fails on PostgreSQL - l.email not in GROUP BY + $qb->select('l.id, l.email, COUNT(e.id) as emailCount') + ->from('leads', 'l') + ->leftJoin('l', 'emails', 'e', 'e.lead_id = l.id') + ->groupBy('l.id'); + +Detecting the database platform +=============================== + +When you need platform-specific query logic, detect the database type using the connection's platform: + +.. code-block:: php + + use Doctrine\DBAL\Platforms\PostgreSQLPlatform; + + $connection = $this->getEntityManager()->getConnection(); + $platform = $connection->getDatabasePlatform(); + + if ($platform instanceof PostgreSQLPlatform) { + // PostgreSQL-specific logic + } else { + // MySQL/MariaDB logic + } + +Repositories extending ``CommonRepository`` can use the ``isPostgreSql()`` helper method. + +Best practices +============== + +1. **Use Doctrine's ORM and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. + +2. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. + +3. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. + +4. **Use repository helper methods** - ``CommonRepository`` provides cross-platform helpers for common operations like case-insensitive searches. \ No newline at end of file diff --git a/docs/testing/e2e_test_suite.rst b/docs/testing/e2e_test_suite.rst index 46821ac1..31367cc5 100644 --- a/docs/testing/e2e_test_suite.rst +++ b/docs/testing/e2e_test_suite.rst @@ -233,6 +233,64 @@ You can watch your tests run in an automated browser by visiting the following U ``Password: secret`` +Testing on multiple databases +***************************** + +Mautic supports MySQL, MariaDB, and PostgreSQL. The CI pipeline runs tests against all supported databases. Make sure your code works across all databases when developing features or writing tests. + +Supported database versions +=========================== + +.. list-table:: + :header-rows: 1 + + * - Database + - Tested versions + * - PostgreSQL + - 16, 18 + * - MariaDB + - 10.11, 11.4 + * - MySQL + - 8.4, 9.4 + +Configuring your test environment for PostgreSQL +================================================ + +To run tests locally against PostgreSQL: + +1. Update your ``.env.test.local`` with PostgreSQL credentials: + +.. code-block:: bash + + # .env.test.local + DB_DRIVER=pdo_pgsql + DB_HOST=localhost + DB_PORT=5432 + DB_USER=postgres + DB_PASSWD=your_password + DB_NAME=mautic_test + +2. Ensure the ``pdo_pgsql`` PHP extension is installed and enabled. + +3. Run the test suite as normal: + +.. code-block:: bash + + bin/phpunit + +Database-specific test considerations +===================================== + +Keep these database differences in mind when writing tests: + +- **Case sensitivity**: PostgreSQL ``LIKE`` is case-sensitive; MySQL/MariaDB ``LIKE`` isn't. Use Mautic's helper methods for case-insensitive matching. + +- **GROUP BY strictness**: PostgreSQL requires all non-aggregated ``SELECT`` columns in ``GROUP BY``. + +- **Identifier quoting**: PostgreSQL lowercases unquoted identifiers. Quote ``camelCase`` aliases in raw SQL. + +For detailed guidance on writing database-agnostic code, refer to the :doc:`/plugins/database` documentation. + Contributing ************ From 3b09a5dcb836c9898aa62d13159e663e61d332c6 Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Tue, 24 Mar 2026 22:48:24 +0000 Subject: [PATCH 2/5] Clarify GROUP BY strictness applies to MySQL 8+ strict mode too Updates the GROUP BY documentation to clarify that MySQL 8+ with ONLY_FULL_GROUP_BY SQL mode enabled also enforces strict GROUP BY rules, not just PostgreSQL. This ensures developers write compliant queries that work across all supported databases and SQL modes. --- docs/plugins/database.rst | 6 ++++-- docs/testing/e2e_test_suite.rst | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/plugins/database.rst b/docs/plugins/database.rst index 8e166533..2d164e9d 100644 --- a/docs/plugins/database.rst +++ b/docs/plugins/database.rst @@ -450,9 +450,11 @@ GROUP BY requirements .. vale on -PostgreSQL enforces strict ``GROUP BY`` rules. Every column in the ``SELECT`` clause must appear in the ``GROUP BY`` clause or use an aggregate function. MySQL and MariaDB are more lenient by default. +PostgreSQL enforces strict ``GROUP BY`` rules, and MySQL 8+ does the same when ``ONLY_FULL_GROUP_BY`` SQL mode is enabled - the default in strict mode. Every column in the ``SELECT`` clause must appear in the ``GROUP BY`` clause or use an aggregate function. -Mautic's Report Builder corrects ``GROUP BY`` clauses for PostgreSQL automatically. If you're building custom Reports or queries with aggregates, include all non-aggregated columns in the ``GROUP BY`` clause. +Writing compliant ``GROUP BY`` clauses ensures compatibility across all supported databases and SQL modes. + +Mautic's Report Builder corrects ``GROUP BY`` clauses automatically. If you're building custom Reports or queries with aggregates, include all non-aggregated columns in the ``GROUP BY`` clause. **Correct pattern:** diff --git a/docs/testing/e2e_test_suite.rst b/docs/testing/e2e_test_suite.rst index 31367cc5..8a19efa7 100644 --- a/docs/testing/e2e_test_suite.rst +++ b/docs/testing/e2e_test_suite.rst @@ -285,7 +285,7 @@ Keep these database differences in mind when writing tests: - **Case sensitivity**: PostgreSQL ``LIKE`` is case-sensitive; MySQL/MariaDB ``LIKE`` isn't. Use Mautic's helper methods for case-insensitive matching. -- **GROUP BY strictness**: PostgreSQL requires all non-aggregated ``SELECT`` columns in ``GROUP BY``. +- **GROUP BY strictness**: PostgreSQL and MySQL 8+ strict mode require all non-aggregated ``SELECT`` columns in ``GROUP BY``. - **Identifier quoting**: PostgreSQL lowercases unquoted identifiers. Quote ``camelCase`` aliases in raw SQL. From 28cf3348237fb093fef845d2fdfa81e3089c6758 Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Mon, 1 Jun 2026 13:53:59 +0000 Subject: [PATCH 3/5] Address PR review feedback from @adiati98 - Fix passive voice in setup.rst and e2e_test_suite.rst - Update method list formatting in database.rst - Add vale off/on directives around camelCase content - Convert best practices to numbered list format - Fix ordered list format and code block indentation in e2e_test_suite.rst - Add vale off/on around database-specific bullets and cross-reference --- docs/development-environment/setup.rst | 2 +- docs/plugins/database.rst | 21 +++++++++-------- docs/testing/e2e_test_suite.rst | 32 +++++++++++++++----------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/docs/development-environment/setup.rst b/docs/development-environment/setup.rst index 4b85ab10..8c9de63d 100644 --- a/docs/development-environment/setup.rst +++ b/docs/development-environment/setup.rst @@ -56,7 +56,7 @@ You can also run the install process from command line: .. note:: - PostgreSQL 16 or later is required for PostgreSQL support. Ensure the ``pdo_pgsql`` PHP extension is installed. + PostgreSQL support requires PostgreSQL 16 or later. Install the ``pdo_pgsql`` PHP extension before proceeding. * Run the following command and add your own options: diff --git a/docs/plugins/database.rst b/docs/plugins/database.rst index 2d164e9d..0c222c6e 100644 --- a/docs/plugins/database.rst +++ b/docs/plugins/database.rst @@ -418,8 +418,8 @@ MySQL and MariaDB use case-insensitive ``LIKE`` comparisons by default. PostgreS **Available methods in CommonRepository:** -- ``getILikeExpression(QueryBuilder $qb, string $column, string $parameter)``: Returns platform-appropriate case-insensitive ``LIKE`` expression -- ``getLowerLikeExpression(QueryBuilder $qb, string $column, string $parameter)``: Wraps the column with ``LOWER()`` for case-insensitive comparison +* ``getILikeExpression(QueryBuilder $qb, string $column, string $parameter)``: returns platform-appropriate case-insensitive ``LIKE`` expression +* ``getLowerLikeExpression(QueryBuilder $qb, string $column, string $parameter)``: wraps the column with ``LOWER()`` for case-insensitive comparison - ``isPostgreSql()``: Returns ``TRUE`` if connected to a PostgreSQL database .. vale off @@ -431,8 +431,12 @@ Column and alias quoting PostgreSQL lowercases unquoted identifiers automatically. This causes issues with Mautic's ``camelCase`` column aliases. Always quote identifiers in raw SQL queries that use mixed-case names. +.. vale off + **Use quoted identifiers for camelCase aliases:** +.. vale on + .. code-block:: php // Correct - aliases are quoted @@ -450,7 +454,7 @@ GROUP BY requirements .. vale on -PostgreSQL enforces strict ``GROUP BY`` rules, and MySQL 8+ does the same when ``ONLY_FULL_GROUP_BY`` SQL mode is enabled - the default in strict mode. Every column in the ``SELECT`` clause must appear in the ``GROUP BY`` clause or use an aggregate function. +PostgreSQL enforces strict ``GROUP BY`` rules, and MySQL 8+ does the same when ``ONLY_FULL_GROUP_BY`` SQL mode is active - the default in strict mode. Every column in the ``SELECT`` clause must appear in the ``GROUP BY`` clause or use an aggregate function. Writing compliant ``GROUP BY`` clauses ensures compatibility across all supported databases and SQL modes. @@ -498,10 +502,7 @@ Repositories extending ``CommonRepository`` can use the ``isPostgreSql()`` helpe Best practices ============== -1. **Use Doctrine's ORM and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. - -2. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. - -3. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. - -4. **Use repository helper methods** - ``CommonRepository`` provides cross-platform helpers for common operations like case-insensitive searches. \ No newline at end of file +#. **Use Doctrine's ORM and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. +#. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. +#. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. +#. **Use repository helper methods** - ``CommonRepository`` provides cross-platform helpers for common operations like case-insensitive searches. \ No newline at end of file diff --git a/docs/testing/e2e_test_suite.rst b/docs/testing/e2e_test_suite.rst index 8a19efa7..e9e260bf 100644 --- a/docs/testing/e2e_test_suite.rst +++ b/docs/testing/e2e_test_suite.rst @@ -258,21 +258,21 @@ Configuring your test environment for PostgreSQL To run tests locally against PostgreSQL: -1. Update your ``.env.test.local`` with PostgreSQL credentials: +#. Update your ``.env.test.local`` with PostgreSQL credentials: -.. code-block:: bash + .. code-block:: bash - # .env.test.local - DB_DRIVER=pdo_pgsql - DB_HOST=localhost - DB_PORT=5432 - DB_USER=postgres - DB_PASSWD=your_password - DB_NAME=mautic_test + # .env.test.local + DB_DRIVER=pdo_pgsql + DB_HOST=localhost + DB_PORT=5432 + DB_USER=postgres + DB_PASSWD=your_password + DB_NAME=mautic_test -2. Ensure the ``pdo_pgsql`` PHP extension is installed and enabled. +#. Install and enable the ``pdo_pgsql`` PHP extension. -3. Run the test suite as normal: +#. Run the test suite as normal: .. code-block:: bash @@ -283,14 +283,20 @@ Database-specific test considerations Keep these database differences in mind when writing tests: -- **Case sensitivity**: PostgreSQL ``LIKE`` is case-sensitive; MySQL/MariaDB ``LIKE`` isn't. Use Mautic's helper methods for case-insensitive matching. +.. vale off +* **Case sensitivity**: PostgreSQL ``LIKE`` is case-sensitive; MySQL/MariaDB ``LIKE`` isn't. Use Mautic's helper methods for case-insensitive matching. - **GROUP BY strictness**: PostgreSQL and MySQL 8+ strict mode require all non-aggregated ``SELECT`` columns in ``GROUP BY``. - - **Identifier quoting**: PostgreSQL lowercases unquoted identifiers. Quote ``camelCase`` aliases in raw SQL. +.. vale on + +.. vale off + For detailed guidance on writing database-agnostic code, refer to the :doc:`/plugins/database` documentation. +.. vale on + Contributing ************ From f9784a85eb38be97bfedd3c113ec42df8e324011 Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Fri, 5 Jun 2026 07:45:51 +0000 Subject: [PATCH 4/5] Fix isPostgreSql() list formatting and expand ORM acronym Address reviewer suggestions: - Use consistent `*` marker for isPostgreSql() method - Lowercase "returns" to match other method descriptions - Expand ORM to "Object Relational Mapper - ORM" - Add ORM to Vale vocabulary accept.txt --- .github/styles/config/vocabularies/Mautic/accept.txt | 1 + docs/plugins/database.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/styles/config/vocabularies/Mautic/accept.txt b/.github/styles/config/vocabularies/Mautic/accept.txt index 8593017e..7ea726e7 100644 --- a/.github/styles/config/vocabularies/Mautic/accept.txt +++ b/.github/styles/config/vocabularies/Mautic/accept.txt @@ -107,6 +107,7 @@ noindex OAuth OAuth1a OAuth2 +ORM Packagist patch PATCH diff --git a/docs/plugins/database.rst b/docs/plugins/database.rst index 0c222c6e..dffc65c2 100644 --- a/docs/plugins/database.rst +++ b/docs/plugins/database.rst @@ -420,7 +420,7 @@ MySQL and MariaDB use case-insensitive ``LIKE`` comparisons by default. PostgreS * ``getILikeExpression(QueryBuilder $qb, string $column, string $parameter)``: returns platform-appropriate case-insensitive ``LIKE`` expression * ``getLowerLikeExpression(QueryBuilder $qb, string $column, string $parameter)``: wraps the column with ``LOWER()`` for case-insensitive comparison -- ``isPostgreSql()``: Returns ``TRUE`` if connected to a PostgreSQL database +* ``isPostgreSql()``: returns ``TRUE`` if connected to a PostgreSQL database .. vale off @@ -502,7 +502,7 @@ Repositories extending ``CommonRepository`` can use the ``isPostgreSql()`` helpe Best practices ============== -#. **Use Doctrine's ORM and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. +#. **Use Doctrine's Object Relational Mapper - ORM - and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. #. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. #. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. #. **Use repository helper methods** - ``CommonRepository`` provides cross-platform helpers for common operations like case-insensitive searches. \ No newline at end of file From abb7fda52047a43848e9c050172ca30a22774bb4 Mon Sep 17 00:00:00 2001 From: "promptless[bot]" Date: Mon, 8 Jun 2026 07:32:47 +0000 Subject: [PATCH 5/5] Update database compatibility docs to use DatabasePlatform helpers Addresses review feedback from @wieslawgolec. The platform-specific logic has been refactored into the centralized DatabasePlatform class, so this updates the docs to reference the correct static methods instead of the deprecated CommonRepository instance methods. Changes: - Replace CommonRepository method references with DatabasePlatform static methods - Update code examples to use DatabasePlatform::getCaseInsensitiveLike() with flag parameter - Update platform detection to use DatabasePlatform::isPostgreSQL() - Add note that DatabasePlatform is the single source of truth - Update best practices to reference DatabasePlatform --- docs/plugins/database.rst | 45 +++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/docs/plugins/database.rst b/docs/plugins/database.rst index dffc65c2..8115e04e 100644 --- a/docs/plugins/database.rst +++ b/docs/plugins/database.rst @@ -397,30 +397,43 @@ Case-insensitive string matching .. vale on -MySQL and MariaDB use case-insensitive ``LIKE`` comparisons by default. PostgreSQL's ``LIKE`` is case-sensitive. Mautic provides helper methods in ``CommonRepository`` to handle this. +MySQL and MariaDB use case-insensitive ``LIKE`` comparisons by default. PostgreSQL's ``LIKE`` is case-sensitive. Mautic centralizes all platform-specific helpers in ``Mautic\CoreBundle\Doctrine\DatabasePlatform``. **Using the helper methods:** .. code-block:: php - // In a repository extending CommonRepository - $qb = $this->getEntityManager()->getConnection()->createQueryBuilder(); + use Mautic\CoreBundle\Doctrine\DatabasePlatform; + + $connection = $this->getEntityManager()->getConnection(); + $platform = $connection->getDatabasePlatform(); + $qb = $connection->createQueryBuilder(); // Case-insensitive LIKE - uses ILIKE on PostgreSQL, LIKE on MySQL/MariaDB $qb->andWhere( - $this->getILikeExpression($qb, 'l.email', ':search') + DatabasePlatform::getCaseInsensitiveLike($platform, 'l.email', ':search') ); - // Or wrap the column with LOWER() for case-insensitive comparison + // Apply LOWER() to the column for case-insensitive comparison $qb->andWhere( - $this->getLowerLikeExpression($qb, 'l.firstname', ':search') + DatabasePlatform::getCaseInsensitiveLike( + $platform, + 'l.firstname', + ':search', + DatabasePlatform::FLAG_LOWER_COLUMN + ) ); -**Available methods in CommonRepository:** +.. vale off + +**Available methods in DatabasePlatform:** + +.. vale on -* ``getILikeExpression(QueryBuilder $qb, string $column, string $parameter)``: returns platform-appropriate case-insensitive ``LIKE`` expression -* ``getLowerLikeExpression(QueryBuilder $qb, string $column, string $parameter)``: wraps the column with ``LOWER()`` for case-insensitive comparison -* ``isPostgreSql()``: returns ``TRUE`` if connected to a PostgreSQL database +* ``getCaseInsensitiveLike($platform, $column, $valueOrParameter, $flags)``: returns platform-appropriate case-insensitive ``LIKE`` expression. Supports flags for ``LOWER()`` handling and negation. +* ``getRegexpExpression($platform, $column, $pattern, $negative)``: handles ``REGEXP`` differences between MySQL and PostgreSQL. +* ``isPostgreSQL($platform)``: returns ``TRUE`` if the platform is PostgreSQL. +* ``isMySQL($platform)``: returns ``TRUE`` if the platform is MySQL or MariaDB. .. vale off @@ -482,22 +495,22 @@ Mautic's Report Builder corrects ``GROUP BY`` clauses automatically. If you're b Detecting the database platform =============================== -When you need platform-specific query logic, detect the database type using the connection's platform: +When you need platform-specific query logic, use the static helpers in ``DatabasePlatform``: .. code-block:: php - use Doctrine\DBAL\Platforms\PostgreSQLPlatform; + use Mautic\CoreBundle\Doctrine\DatabasePlatform; $connection = $this->getEntityManager()->getConnection(); - $platform = $connection->getDatabasePlatform(); + $platform = $connection->getDatabasePlatform(); - if ($platform instanceof PostgreSQLPlatform) { + if (DatabasePlatform::isPostgreSQL($platform)) { // PostgreSQL-specific logic } else { // MySQL/MariaDB logic } -Repositories extending ``CommonRepository`` can use the ``isPostgreSql()`` helper method. +``DatabasePlatform`` is the single source of truth for platform differences. Use its helpers instead of writing platform checks manually to avoid drift as the codebase evolves. Best practices ============== @@ -505,4 +518,4 @@ Best practices #. **Use Doctrine's Object Relational Mapper - ORM - and QueryBuilder** - Doctrine abstracts most database differences. Avoid raw SQL when possible. #. **Test on multiple databases** - Mautic's CI tests against MySQL, MariaDB, and PostgreSQL. Run your Plugin tests against all platforms before release. #. **Quote mixed-case aliases** - When using custom column aliases with ``camelCase`` names in raw SQL, always quote them. -#. **Use repository helper methods** - ``CommonRepository`` provides cross-platform helpers for common operations like case-insensitive searches. \ No newline at end of file +#. **Use DatabasePlatform helpers** - ``Mautic\CoreBundle\Doctrine\DatabasePlatform`` provides cross-platform helpers for case-insensitive searches, regular expressions, date handling, and platform detection. Consult its source for the full list of available methods. \ No newline at end of file