PHTML Templates

Prerequisites

Modifying core PHTML templates

To modify a core template, copy it from base/default to your {package}/{theme}:

# Core template
/app/design/frontend/base/default/template/catalog/product/view.phtml

# Custom template (for modifications)
/app/design/frontend/{package}/{theme}/template/catalog/product/view.phtml

The configured theme fallback determines which template applies.

Always replace Magento’s DocBlock with your project’s DocBlock so it’s glaringly obvious the file is customized.

Adding new PHTML templates

Sometimes themes themes and extensions require new templates. Storing them alongside core templates makes their origin amibuous:

  • Must trace fallback hierarchy to confirm template is not part of the core.
  • Hard to identify all non-core templates.
  • Hard to identify all templates from in-house or third-party developers.

New templates should be namespaced to the provider. Mirroring the module structure within each namespace keeps files separate but logically organized. For example:

# Given a new template for loading web fonts
web-font-loader.phtml

# Good: using "gravdept" namespace
/app/design/frontend/{package}/{theme}/template/gravdept/page/html/web-font-loader.phtml

# Bad: stuffed alongside core templates
/app/design/frontend/{package}/{theme}/template/page/html/web-font-loader.phtml

Naming conventions

Directory and file names should be descriptive, but succinct.

  • Lowercase only.
  • Separate words with dashes.
  • No underscores or special characters.

Temporary variables

The recommended way to manipulate data in PHTML templates is by extending the PHP class with additional methods. Sometimes this is overkill. Creating a temporary PHP variable in a template is acceptable in cases like loop iterators, data objects, or string manipulation. Beware the variable’s scope is global though.

Magento uses an underscore prefix to designate temporary variables. This convention is commonly seen for:

// Iteration counters
$_i = 0;

// Data objects
$_product = $this->getProduct();

I like to drop the underscore. There is a rationale for that syntax, but I prefer concise code.

// Iteration counters
$i = 0;

// Data objects
$product = $this->getProduct();

// Custom stuff
$fullName = $firstName . ' ' . $lastName;

Namespacing

If you want to get super fancy namespace your variables. I rarely do this anymore because the scope is limited to the template, and templates are pretty small.

Namespacing is a good way to prevent collisions and make the origin of that variable obvious though. Follow this format:

  • Lowercase namespace.
  • Underscore between namespace and variable name.
  • Variable name in camelcase.
// Syntax
${namespace}_{someVariableName}

// Good
$gravdept_someVariableName

// Bad
$some_variable_name