Coding Standards & Best Practices

Every rule on this page was already stated somewhere earlier in this tutorial — this page just collects them in one place instead of leaving you to remember which lesson mentioned which convention.

Naming and structure

  • CamelCase directories, underscore class names. A module living at modules/Custom/HelloWorld/ has classes named Custom_HelloWorld, Custom_HelloWorldCommon, Custom_HelloWorldInstall — the underscore stands in for the directory separator. Keep folder name and class name prefix in sync or the autoloader won't find your class. See Architecture Overview.
  • Version-suffix your main class file (Modulename_0.php). Bump the number for a breaking rewrite of the module's core class.
  • Never edit the default theme in place. Copy it to a new theme folder under /data/Base/Theme/templates/ first — see Creating Theme.

Security

  • Every module PHP file starts with an access guard:

    defined("_VALID_ACCESS") || die('Direct access forbidden');

    This is the first line of every example in this tutorial for a reason — it stops the file from being requested directly, outside Epesi's own bootstrap. Don't skip it, including in template/include files.

Data and fields

  • Reach for RBO for new data-driven modules, not raw DB::Execute() or hand-rolled RecordBrowser arrays. See the Architecture Overview for why, and Utils/RBO for the field-type reference.
  • Use RBO's fluent setters explicitlyset_visible(), set_required(), set_length() — rather than relying on defaults. A field with no set_visible() is deliberately hidden (used for internal/autonumber fields); make sure that's what you meant.

Translation

  • Wrap every user-facing string in __(), _M(), or _V() rather than hardcoding English text — see Using Translations. This is what makes your module usable in the ~40 languages the Epesi community has already translated the core app into, and it costs nothing to do from the start versus retrofitting later.

Patches (upgrading installed modules)

The Patch page has its own detailed guidelines (checkpoints, require_time, avoiding die()) — the short version: write patches as if they might run twice, check whether a table/column already exists before creating it, and never assume you can silently overwrite a user's existing data.

While developing

  • Use soft refresh (click the Epesi logo, top-left) instead of a full browser reload to see your changes — a full reload restarts the whole session. See the Hints on the tutorial's landing page.

_(An older version of this page also recommended toggling a CACHE_COMMON_FILES config define during development — that mechanism is dead code in current Epesi and no longer does anything, so it's been removed rather than left as stale advice.)_

What's not covered here

This page is a checklist of conventions already documented elsewhere on this site, not a formal style guide, and there's no documented automated linting/testing setup for Epesi modules (no PHPUnit examples, no CI configuration referenced anywhere in this tutorial). If your team needs one, that's worth raising with the Epesi team directly rather than inferring a standard from this page.