5.6 KiB
5.6 KiB
Coding Conventions
Analysis Date: 2026-05-10
Naming Patterns
Files:
- PHP class files: PascalCase matching class —
classes/Product.php,classes/Cart.php - Module entry file: lowercase, matches directory —
modules/crosssellpro/crosssellpro.php - Smarty templates: camelCase per module —
cartCrossSell.tpl,checkoutCrossSell.tpl - Asset files: camelCase —
cartCrossSell.css,cartCrossSell.js
Functions / Methods:
- camelCase —
buildCrossSellProducts(),collectAccessoryIds(),getCombinationFlags(),presentProducts()(modules/crosssellpro/crosssellpro.php) - Hook handlers: literal prefix
hook+ PascalCase hook name —hookDisplayShoppingCartFooter(),hookActionFrontControllerSetMedia()
Variables:
- New custom code:
$camelCase—$cartProducts,$inCartProductIds,$productId - Legacy / DB-driven code:
$snake_case—$id_product,$id_cart,$id_shop(mirrors PrestaShop column names; expected when interacting with ObjectModel data)
Classes:
- PascalCase, suffixed
Corefor PrestaShop core —class ProductCore extends ObjectModel(classes/Product.php) - Module classes: PascalCase matching folder —
class Crosssellpro extends Module
Hook names (string identifiers):
- camelCase, registered as strings —
displayShoppingCartFooter,displayHeader,actionFrontControllerSetMedia
Code Style
PHP Formatting:
- 4-space indentation (no tabs)
- PSR-12-compatible style for new custom code
- Opening braces on same line:
class Crosssellpro extends Module { - Single quotes preferred for strings
- Escape filter pattern in templates:
{$product.name|escape:'htmlall':'UTF-8'}
JavaScript Formatting:
- 2-space indentation
- Legacy ES5 in custom module JS (
vardeclarations) —modules/crosssellpro/views/js/cartCrossSell.js - camelCase for functions/variables
- Data-attribute targeting:
[data-crosssellpro-block="1"]
Smarty:
{$variable|filter:'arg':'arg'}for output with escaping{if}…{/if},{foreach}…{/foreach},{assign}block syntax
Linting:
- No root-level
.php-cs-fixer.phporphpstan.neon - Per-module PHPStan/PHP-CS-Fixer config available in some PrestaShop modules (
modules/<m>/tests/phpstan/phpstan.neon)
Import Organization
PHP:
<?phpopener with no namespace declared in custom modules (PrestaShop legacy autoloader convention)usestatements for Symfony / vendor classes when needed- No enforced ordering — follow existing file's pattern
JS:
- Vanilla DOM manipulation in custom module JS — no module bundler
- Theme JS bundled in
themes/leo_gstore/assets/cache/
Error Handling
Patterns:
- PrestaShop convention: input via
Tools::getValue('key')(sanitizes; preferred over raw$_GET/$_POST) - DB queries via
Db::getInstance()withpSQL()for sanitization (legacy pattern; not parameterized) try/catchrare — exceptions surfaced viaTools::displayError()or logged- Hook methods generally return rendered output; failure typically silent (returns empty string)
Custom-code observations:
import-product.phphas minimal error handling, no transaction wrappingbuy-by-phone.phpaccesses$_POSTdirectly withoutTools::getValue()— seeconcerns.md
Logging
Framework:
- Symfony Monolog (admin layer) via
app/AppKernel.php - File logs at
errors.log(root) andiadmin/errors.log - No structured/contextual logging in custom code
Patterns:
- PrestaShop core
PrestaShopLogger::addLog()— used in some modules - Custom code prefers
error_log()or no logging
Comments
When to Comment:
- PHPDoc blocks above public methods (recommended)
- Inline
//for non-obvious business logic
PHPDoc style (used in custom module):
/**
* Builds presented products list from accessories of products currently in cart.
*
* @return array
*/
protected function buildCrossSellProducts()
Parameter form:
/**
* @param int[] $productIds
* @return array<int, bool>
*/
protected function getCombinationFlags(array $productIds)
Property form:
/** @var int Manufacturer identifier */
public $id_manufacturer;
TODO Comments:
- Format varies (
// TODO,// FIXME,// HACK) — found in core, rare in custom code
Function Design
Size:
- Module hook methods kept short; logic delegated to private helpers (e.g.
buildCrossSellProducts(),presentProducts()) - Long legacy scripts exist (
import-product.php813 lines) — anti-pattern
Parameters:
- Hook method signatures match PrestaShop dispatcher:
hookXxx(array $params)where$paramscarries context
Module Design (PrestaShop-specific)
Module class skeleton:
- Constructor sets
$this->name,$this->tab,$this->version,$this->author,$this->bootstrap, thenparent::__construct() install()callsparent::install()and chains$this->registerHook(...)callsuninstall()callsparent::uninstall()(cleans hook table)- Hook handlers named
hook<HookName>()
Template overrides:
- Module ships defaults in
modules/<m>/views/templates/hook/ - Theme overrides resolved at
themes/<theme>/modules/<m>/views/templates/hook/
Assets:
- Registered in
hookActionFrontControllerSetMedia()via$this->context->controller->registerStylesheet()/registerJavascript()
Override Design
- Place in
override/classes/<ClassName>.phporoverride/classes/controller/<Name>.php - Extend the core class verbatim and add/override methods only
- Document the why of each override (currently undocumented in this project — see
concerns.md)
Convention analysis: 2026-05-10 Update when patterns change