Skip to the content
Documentation
Help Start
Reading in:
  • German: 9,059 of 9,059 pages
About the help in other languages
All help pages

PHP developer FAQ

Short answers to the questions PHP developers ask most about Exponential - PHP versions, PSR-4 and namespaces, type declarations, class not found, settings not applied, edits that do nothing under Velocity, databases…

Download as PDF

Address: https://doc.exponential.earth/learninminutes/exphelp/viewer/help/php-developers/php-developer-faq.md

On this page

PHP developer FAQ

This page is for PHP developers who want a quick answer. Each answer links to the page with the details.

Warning

.htaccess slows down every request. When .htaccess files are enabled (AllowOverride anything but None), let alone used, Apache looks for them and reads and evaluates them on every request, in every directory of the path, and page loading times go up drastically (measured). The only real fix is to switch the feature off for the virtual host: AllowOverride None in the HTTPS virtual host, and the rules in the virtual host's own configuration as mod_rewrite rules. That is far faster in production speed tests and well worth the time it takes to optimize a production configuration. Switch over right away: copy the rules of the example HTTPS virtual host into your virtual host (with the static cache, also staticcache_offload.conf), set AllowOverride None, run apachectl configtest, reload Apache and test the site. The same rules for other servers: nginx, LiteSpeed, Caddy, IIS, Velocity (built in); where virtual host rules go in a control panel: Plesk, cPanel, DirectAdmin, ISPConfig. On LiteSpeed or OpenLiteSpeed, the server's own page cache can also answer anonymous visitors and crawlers without PHP: Page caching with LiteSpeed and OpenLiteSpeed.

Contents

  1. Platform and language
  2. Classes and settings
  3. Velocity and deploys
  4. Databases
  5. Tests and CI
  6. Where to start

Platform and language

Which PHP versions must my code support? PHP 8.0 to 8.5 (PHP 7.4 usable without support). PHP 8.0 is the oldest because it is the stock PHP of RHEL 9 (Supported PHP versions: 8.0 to 8.5).

Can I use enums, readonly properties or foo(...)? Not in code that ships with or for Exponential: PHP 8.0 cannot parse them (Writing code that runs on PHP 8.0).

Why no declare( strict_types=1 ) and no return types? The coding standard forbids them in new code, for consistency with the existing code, compatibility of subclasses and PHP 8.0 (Why the code has no type declarations).

Why array() and not []? The house style, measured on the existing code and checked by phpcs.xml.dist (The coding standard).

Does Exponential follow PSR-4 or PSR-12? No. Classes are found through generated class maps, and the code style is the kernel's own (PHP, PHP-FIG and Composer standards).

May I use namespaces? Yes. The kernel uses them for commands, cronjob parts, views and services (Exponential\Command\...); other classes are global with a prefix (Class naming and the exp prefix).

Is there a Symfony layer? Exponential 6 runs on its own kernel. The legacy bridge runs it inside a Symfony platform installation (Symfony and the legacy bridge).

What are the ezc* classes, and where do they come from? They are the kernel's libraries (ezcMail, ezcArchive, ezcWebdavServer, ezcMvcController ...). Since 6.0.15 they come from the expcomponents (se7enxweb/expcomponents-*), Exponential's fork of the Zeta Components, under the Apache License 2.0; the class names and APIs did not change. A bug in one of them goes to that fork's repository (Exponential Components, Contributing to expcomponents).

My extension requires zetacomponents/mail. Must I change it? No: each fork replaces its upstream name, so the requirement is met. Rename it to se7enxweb/expcomponents-mail in your next release (Upgrade notes: the switch to expcomponents).

Classes and settings

My new class is "not found". Run php bin/php/ezpgenerateautoloads.php -e; under Velocity also restart the workers (exp:velocity deploy) (Autoloads and class maps).

I changed a setting and nothing happened. Clear the INI cache with --clear-tag=ini (not --clear-id=ini), check the layer that wins with exp:ini where, and restart Velocity's workers (Reading settings with eZINI).

How do I create .htaccess and config.php? ./console exp:setup:htaccess --apply and ./console exp:setup:config --apply copy them from .htaccess_root and config.php-RECOMMENDED; an existing file that differs is shown as a diff and kept unless --force (Setting up .htaccess and config.php from the console).

How do I change a config.php setting without an editor? ./console exp:config:set <NAME> <value> [--type=bool|int|octal|float|string|null] --apply. The file is read as PHP tokens, never run; only the value of that one define() changes, and the result must pass php -l. A constant of your own extension needs --allow-unknown. Under Velocity restart the workers afterwards (Setting up .htaccess and config.php from the console).

Should I rename eZContentObject and the other eZ classes? Never. They are real identifiers that every extension uses; new code uses exp or your own prefix.

How do I change one kernel view without copying it? Subclass its class and register the subclass in site.ini [RunnableSettings] Implementation[] (Module views as classes).

Velocity and deploys

My edit to a PHP file does nothing. Under Velocity the workers keep loaded classes: exp:velocity deploy. With the engine archive on, a kernel edit needs a rebuild, which the deploy does (The engine archive (phar) for PHP developers).

A page shows another user's or siteaccess's data, only under Velocity. State kept between requests: a function static, a cache keyed by too little, a register-once flag (Static state traps).

My download view prints the page after the file. eZExecution::cleanExit() is inside a catch ( Exception ). Under Velocity it ends the request with an exception; do not catch it (Velocity persistent workers for PHP developers).

Does FrankenPHP keep state between requests? No. It runs in classic mode, a clean state per request (FrankenPHP for PHP developers).

Databases

Which database should I develop on? SQLite 3 is the default and needs nothing; test on a server database too before you release (Code for every supported database).

How do I avoid SQL injection? escapeString() for strings, (int) for numbers, or eZPersistentObject conditions (SQL with eZDB, safely).

My SQL returns nothing on MongoDB. The adapter translates the kernel's SQL shapes only; untranslatable SQL returns an empty result and logs MONGO TODO.

Tests and CI

Do I need a database to run the tests? No. vendor/bin/phpunit runs the DB-less suites; database tests run separately with tests/runtests.php --dsn ... (PHPUnit without a database, Database and live tests).

PHPStan fails on code I did not touch. Only findings missing from phpstan-baseline.neon fail; check whether your change moved or changed that code (Static analysis with PHPStan).

CI is red but everything passes locally. Usually a test reads your installation's settings, or CI runs an older PHPUnit or PHP (CI and reproducing a red check).

The commit-msg hook refuses my commit. Start the subject with Added: , Updated: , Fixed: , Removed: or Renamed: (Git hooks and make targets).

Where to start

Read Exponential for PHP developers, set up a checkout, then do Write your first module view. The full order is The PHP developer's reading path.

Become an Exponential Partner

Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.

Something wrong on this page? Report an error

Documentation license

This documentation is free documentation, licensed under the GNU Free Documentation License 1.3 or later.

Exponential Copyright © 1998-2026 Exponential Foundation and 7x