This article documents a practical, repeatable protocol to migrate Joomla 3 extensions to modern Joomla versions (4, and forward toward 5/6). It is written for site owners, designers and junior developers who need a structured workflow that reduces risk and helps produce stable releases. The protocol is stage-based: prepare, audit, automated fixes, manual refactor, database work, frontend and assets, testing, packaging and release.
Important: verify any version-specific API or manifest details against the official Joomla Developer Documentation before applying changes in production. Several technical claims below are flagged for verification in the checklist at the end of the article.
Overview: Why a repeatable protocol matters
Migrating extensions ad-hoc often leads to regressions, inconsistent upgrades and surprising support requests. A repeatable protocol helps you:
- Limit scope and focus effort on risky areas.
- Automate low-risk changes and reserve manual review for tricky API or database work.
- Deliver predictable results with clear rollback and test plans.
Expected effort and scope assessment
Classify the extension early so you can estimate effort. Typical categories:
- Plugin — single file or small set of files: minutes to a few hours for simple cases.
- Module — small UI with a few helpers: a few hours to a day.
- Component — admin & site areas, models, controllers, views, DB tables: days to weeks depending on complexity.
- Library / system plugin — can be high-risk if it touches core services.
Decision point: rewrite vs incremental refactor. Choose a rewrite if the codebase is extremely old, unmaintainable, or uses patterns incompatible with modern PHP. Otherwise, prefer incremental refactor to reduce risk.
Practical example
A simple content plugin that hooks into events and uses a few legacy calls may be updated in a couple of hours by replacing deprecated APIs and updating the manifest. A component with custom routing, many models and a large custom table requires a full audit, tests, upgrade SQL and multiple staging iterations.
- Do not run migrations directly on production sites without a tested rollback plan.
- Large extensions with custom database schemas have higher risk and need staged validation.
Pre-migration checklist (requirements & backups)
Preparation reduces surprises. Before changing code or database:
- Decide target Joomla versions to support (Joomla 4 only, or include planned J5/J6).
- Confirm the required PHP versions for the chosen Joomla targets — verify this against official Joomla release notes.
- Create full backups: files and database snapshots. Keep timestamped copies.
- Archive the current extension installer ZIP to your releases folder.
- Set up a local dev environment and a staging instance that mirrors production as closely as possible.
Verify PHP and Joomla core target versions
Before you refactor, check the minimum PHP required by your target Joomla version and plan for those constraints in your code. This affects syntax choices and dependency versions.
Backups and restore plan
Document the exact steps to restore a previous extension version and to restore the database. Example backup actions:
- Export DB: run a consistent dump (for MySQL: use mysqldump with routines and triggers if needed).
- Archive files: compress the site files or use a filesystem snapshot.
- Save installer: copy the installed extension ZIP to an archive directory.
- Confirm PHP & Joomla target versions (verify).
- Backup DB: mysqldump --single-transaction — ensure consistency.
- Archive site files to tar.gz.
- Save current extension ZIP to /releases/old/.
- Prepare local & staging sites.
- Backing up very large databases may require a snapshot or scheduled downtime for consistency.
- Never delete the original installer until the new release is fully validated on staging.
Stage 1 — Full extension audit
The audit identifies what to change. Create an inventory of files and behaviors and mark items by risk.
- Files to review: controllers, models, views, helpers, tables, language files, assets, XML manifest, installer scripts.
- Detect deprecated APIs and legacy classes (for example: direct uses of legacy factories or JTable patterns).
- Assess database schema and custom tables for changes.
- List bundled third-party libraries and licenses.
Audit: file and code inventory
Create a simple map such as a spreadsheet or YAML file listing each file and its responsibility. Include entry points and any scheduled or CLI tasks.
Automated scans for deprecated API usage
Use simple search tools to locate legacy patterns. Examples:
- Search for JFactory, JInput, JTable, JControllerLegacy.
- Search for direct include or require of Joomla core files and hardcoded URLs.
Use your shell search tool to find legacy references. Example patterns (adapt to your environment):
- Linux/macOS: grep -R "JFactory\|JTable\|JInput" /path/to/extension
- Windows (PowerShell): Select-String -Path .\* -Pattern "JFactory|JTable|JInput" -SimpleMatch -List
Validate results manually; automated scans return false positives.
- Automated scans can produce false positives; validate each flagged item manually.
- Do not remove legacy compatibility classes until verified in a test environment.
Stage 2 — Apply automated fixes and static checks
Automated tools accelerate fixes for repetitive patterns and enforce coding standards early in the process.
- Use code-mods or scripted replacements for low-risk, well-scoped changes.
- Run PHP CodeSniffer (phpcs) with Joomla rules and address obvious issues.
- Introduce static analysis (PHPStan or Psalm) to find type and API usage issues; tune the configuration for legacy code.
- If a composer.json file exists, run composer install and validate autoload.
Automated fixes: code-mods and scripts
Automated replacements can be safe for well-known patterns but be cautious. Example safe patterns include adding class aliases or replacing obvious, exact string API calls. Avoid broad regex that can change unintended code.
Static analysis and coding standards
Set up phpcs with the Joomla standard and run it early. Add PHPStan or Psalm incrementally and suppress noise in older code until you can address issues systematically.
- Run phpcs: phpcs --standard=Joomla path/to/extension
- Run PHPStan (example): vendor/bin/phpstan analyse src --level=5
Always re-run the extension's install and basic flows after automated replacements to catch runtime errors.
- Automated replacements can break code if patterns are ambiguous—always run tests afterwards.
- Static analyzers may require tuning to avoid excessive noise for older codebases.
Stage 3 — Manual refactor: code, API, and manifest updates
This is the core of the migration. Manual edits are required for namespace restructuring, replacing deprecated APIs with service-based calls, and updating the XML manifest for modern Joomla versions.
Namespaces and PSR-4 autoloading
Convert legacy non-namespaced classes into namespaced classes and reorganize files to match PSR-4 if you choose to adopt composer autoloading. A typical move includes adding a namespace line and updating class usage across the codebase. If you plan to use composer, include a composer.json with an autoload section.
Example (illustrative only — verify formats with docs): transform
Before: legacy class without namespace
class PlgContentExample { /* ... */ }
After: namespaced class (example)
namespace Vendor\Extension\Plugin\Content; class Example { /* ... */ }
API replacements and service usage
Identify common legacy patterns such as factory calls and replace them with service-based accessors where applicable. These replacements vary by Joomla version and should be verified against the official API documentation before final changes.
Manifest and installer updates
Update the extension XML manifest to include any new required elements and attributes for modern Joomla versions. If you plan to publish via composer, include appropriate metadata and consider whether you will support both traditional ZIP installers and composer distribution.
- Move to PSR-4 carefully: renaming and moving files can introduce class-not-found errors if autoloading is not configured correctly.
- Retain legacy class aliases while validating all entry points; remove aliases only once the staging verification is complete.
- Label any illustrative code snippets in your repo with a clear note: "example — verify against official docs."
- Moving to PSR-4 changes class resolution—test thoroughly to avoid class-not-found errors.
- Do not remove old class aliases until all entry points are validated in staging.
Stage 4 — Database and schema changes
Database changes are often the riskiest part. Plan idempotent upgrade steps and tie them to the extension update mechanism so they run during installation or update.
Upgrade SQL files and migration functions
Structure upgrade SQL files per version pair or use migration functions that check for existing columns. Example best practice: run SQL that checks for the existence of a column before adding it.
Testing database migrations
Always test migrations against a realistic copy of production data on staging. Provide rollback SQL or documented steps for manual recovery when fully reversible SQL is not feasible.
Example SQL stub that adds a column only if it does not exist (verify syntax and adapt to your DB engine):
-- Verify this SQL and adapt to your DB engine and Joomla update mechanism
- ALTER TABLE on large tables can lock the table and cause downtime; consider online schema change strategies or schedule a maintenance window.
- Always test migrations against a realistic dataset to detect performance regressions.
Stage 5 — Frontend, templates and assets
Modern Joomla has evolved frontend markup and asset registration patterns. Review template overrides and JS/CSS registration to avoid broken pages.
Templates and overrides
Locate template overrides in the site template that affect your extension. Keep overrides minimal and update layouts to match any changed variables or markup from the refactor.
Assets and JavaScript
Register scripts and styles via the recommended asset management mechanism for the Joomla version you support. Audit JS libraries and remove or update bundled libraries as needed. Avoid inline scripts relying on global legacy variables.
- Update a template override that referenced a removed layout variable by adjusting the override to use the new view data.
- Replace direct <script> insertion with registered assets where supported.
- Changing templates can alter frontend behavior—test on multiple devices and browsers.
- Replacing bundled third-party libraries may require license checks.
Stage 6 — Testing strategy (local, staging, CI)
Testing should be progressive: start with local manual checks, add automated unit and integration tests, and run these in CI before deploying to staging.
Unit and integration tests
Write unit tests for critical services and model logic. Create integration tests covering install/update, save operations, and permission checks. Configure PHPUnit to run tests for your extension; verify recommended configuration against Joomla testing docs.
CI pipeline basics
Example CI stages: checkout → composer install → phpcs → phpstan → phpunit → deploy to staging. Manage secrets for DB and use lightweight fixtures to keep jobs fast and stable.
Sample test matrix to adapt:
- PHP 7.4, 8.0, 8.1 (adjust according to target Joomla/PHP requirements)
- Joomla 4.x and target future versions you plan to support
- Running browser UI tests in CI increases complexity; begin with unit and integration tests.
- CI jobs must be reliable and fast—avoid unstable external services in test jobs.
Stage 7 — Packaging, versioning and release notes
Prepare the final package and communicate clearly to site administrators. Choose a versioning strategy and build an installer that matches your distribution model.
Packaging options
Decide between a traditional ZIP installer and composer distribution. Both are viable options; contrast them for your audience and document installation instructions for each. Verify current packaging recommendations from Joomla docs.
Release process and support
Include a changelog, compatibility statements (Joomla and PHP versions), known issues and upgrade steps. Provide a rollback plan and support contact for early adopters.
- Bump semantic version appropriately for breaking changes.
- Run phpcs/phpstan/phpunit and ensure green status.
- Generate final ZIP or composer tag and upload to distribution channel.
- Publish release notes with backup instructions and known issues.
- Do not force major refactors in a minor release without clear migration notes.
- If supporting multiple Joomla versions, ensure compatibility metadata is accurate to avoid installation blocks.
Troubleshooting common issues
Here are typical problems and how to diagnose them quickly.
- Class not found: check namespace, spelled class name, and autoload mapping.
- Missing assets: confirm asset registration and correct paths; clear caches.
- Broken routing: verify route definitions and task handling in controllers.
- Language mismatches: ensure language keys and file encodings are correct.
- Database upgrade failures: inspect the SQL run by the installer and compare errors in the PHP/DB logs.
Diagnostics and log checks
Enable Joomla debug and check logs in the administrator and server PHP error logs. Use Xdebug locally to step through failing code paths.
When and how to roll back
Rollback process should be documented in the pre-migration plan: reinstall the prior extension ZIP and restore the DB from the backup snapshot. Coordinate rollbacks with a maintenance window if the site is active.
Resolving a 'class not found' error: check the reported class name in the stack trace, ensure the file containing that class exists and that its namespace matches whichever autoloader you are using. If you recently moved files, regenerate autoload data (for composer) and clear opcode caches.
Warnings- Frequent rollbacks without addressing root causes reduce user trust—use rollback as a last resort.
- Be careful when restoring DB backups on active sites; coordinate with site owners and users.
Tools, resources and quick reference
Recommended tools and quick commands to speed migration tasks:
- phpcs (Joomla coding standard)
- PHPStan or Psalm for static analysis
- PHPUnit for unit/integration tests
- Composer for dependency management and autoloading
- Git and CI (GitHub Actions or GitLab CI) for continuous checks
Command-line quick tips
- Install deps: composer install
- Run phpcs: phpcs --standard=Joomla path/to/extension
- Run PHPStan: vendor/bin/phpstan analyse src --level=5
- Run PHPUnit: vendor/bin/phpunit
- Find legacy usages: grep -R "JFactory\|JTable\|JInput" path/to/extension
- Tooling configurations may need adaptation; do not assume default configs fit every extension.
- Pin tool versions in CI to prevent unexpected behavior from upstream changes.
Migration checklist (printable)
Use this condensed checklist to run a migration. Adapt items to your project.
Printable checklist items
- Pre-migration: verify PHP/Joomla targets, take backups (DB + files), archive current installer, prepare local & staging sites.
- Audit: inventory all files, identify deprecated API usages, map DB schema and third-party libs.
- Automated fixes: run phpcs and PHPStan, run safe code-mods, commit changes.
- Manual refactor: apply namespaces/PSR-4 if chosen, replace deprecated APIs, update manifest XML (verify schema).
- DB: write idempotent upgrade SQL, test on staging copy of production DB, document rollback steps.
- Frontend: update overrides, register assets via recommended mechanism, test JS/CSS.
- Testing: add unit/integration tests for critical flows, run CI, manual UAT on staging.
- Packaging: bump version, build ZIP/composer package, prepare release notes, publish and monitor.
- Automated tests pass in CI.
- Staging verified by manual acceptance tests.
- Backups available and rollback plan documented.
- Monitor error logs and user reports for 48–72 hours after release.
- Be prepared to publish a hotfix if critical issues appear.
FAQ
Do I need to rewrite my entire extension to support Joomla 4/5/6?
Not always. Many extensions can be updated incrementally using automated fixes and focused manual changes. Major rewrites are usually needed only for very old or heavily customized codebases. Perform an audit to decide whether a rewrite is justified.
Do I have to adopt PSR-4 and composer to migrate?
PSR-4 and composer are recommended best practices for modern PHP projects and simplify autoloading and dependency management. Whether they are required depends on Joomla's current extension requirements—verify against the official Joomla documentation before enforcing this in a project.
How do I test the migrated extension safely before production?
Use a local environment matching production, a staging site with production-like data, and an automated CI pipeline. Create a test matrix for PHP and Joomla versions, run unit/integration tests, and perform manual acceptance testing on staging.
What is the safest way to update the database schema?
Use idempotent upgrade SQL files or Joomla update scripts tied to extension version numbers; run migrations on a staging copy of production data first and prepare rollback SQL or documented recovery steps.
What are the most common causes of post-migration breakage?
Common causes include class autoloading issues, deprecated API calls not fully replaced, missing assets after asset manager changes, and untested database changes. Thorough testing reduces these risks.
How should I communicate breaking changes to users?
Publish clear release notes listing Joomla and PHP compatibility, breaking changes, required pre-update steps (backups), and a support contact method. Provide a short migration guide for administrators.
Conclusion
A staged, repeatable protocol reduces migration risk: prepare and backup, audit thoroughly, apply automated fixes, perform careful manual refactors, test in CI and staging, then package with clear release notes and rollback options. Adapt the protocol to your extension’s size and complexity and verify any version-specific technical details against official Joomla documentation before production changes.
Use the printable checklist in this guide as a baseline and expand it with project-specific steps. If uncertain about API replacements or manifest schema changes, consult the Joomla Developer Documentation and consider a small proof-of-concept migration on a non-critical extension first.



Add comment