No results found

Try a different search query

Popular searches:

Add to Cart

Cart

You have no purchases yet

Browse Marketplace

OCMOD in OpenCart: code modifications without changing system files

How OCMOD works in OpenCart 2.x and 3.x: structure of install.xml, search and add tags, version differences, typical modifier errors and their debugging.

7 min read
683
1
OCMOD in OpenCart: code modifications without changing system files

A classic story: a developer fixed a couple of lines directly in catalog/controller/product/product.php, the store started working properly, everyone forgot about it. Half a year later, an engine update or migration to another hosting server, files get overwritten, the fix disappears. No one remembers exactly what was changed, because no trace was left behind. And sometimes it's worse: dozens of fixes pile up, scattered throughout the entire catalog, and you can only distinguish the author's code from the system code by running a diff against a clean build.

That's exactly what OCMOD saves you from. It's the standard modification system for OpenCart, built in starting from version 2.0 (the ideological successor to vQmod, only without a separate installation). The concept is simple: you describe the fix in an XML file according to the principle "find such a line and insert such code," and the engine applies it itself without touching the originals.

 

What happens under the hood

 

OCMOD never edits system files. Instead, it takes the original, makes changes to its copy, and stores it in the modifications cache: system/storage/modification/. When the site runs, the autoloader first looks for the file there, and only if the modified copy doesn't exist—it takes the original.

The XML instructions themselves are stored in the database, in the oc_modification table. The Refresh button in the Extensions → Modifications section rereads all active modifications from the database and rebuilds the cache from scratch. Until you click it, your fixes won't be applied.

 

Minimal modifier

 

A working example: we add our code to the home page.

<?xml version="1.0" encoding="utf-8"?>
<modification>
    <name>My first modifier</name>
    <code>my_first_mod</code>
    <version>1.0</version>
    <author>You</author>
    <link>https://example.com</link>

    <file path="catalog/controller/common/home.php">
        <operation>
            <search><![CDATA[$data['column_left'] = $this->load->controller('common/column_left');]]></search>
            <add position="after"><![CDATA[
            $data['my_variable'] = 'Hello from OCMOD';
            ]]></add>
        </operation>
    </file>
</modification>

 

The header (name, code, version, author, link) is mandatory: without it, the installer won't accept the file. code must be unique, otherwise the new modifier will overwrite the old one with the same code in the database. Sometimes this is used intentionally for updates, but more often it's a surprise when two different modules from the same author suddenly "eat" each other.

Always wrap all code in search and add in <![CDATA[ ]]>. PHP code is full of characters like <, >, &, and without CDATA you'll get invalid XML.

 

search and add: where the nuances hide

 

The <search> tag searches for occurrences within a single line. This is the most important thing to know about OCMOD, and most beginners stumble on it. If you put a three-line code block in search, the modifier silently won't be applied. For multi-line scenarios, there's formally the offset attribute and regular expressions, but both will have caveats below.

 

Attributes of search:

  • trim="true" — trims whitespace at the edges before comparison (it's true by default anyway, but useful to know);
  • index if the searched line appears in the file multiple times, limits the fix to specific occurrences. Numbering starts from zero: index="0" — first occurrence, index="2" — third. You can list multiple: index="0,2". This is a classic trap for those transitioning from vQmod, because there the count starts from one. Without index, the fix will apply to all matches, which is sometimes exactly what you need, and sometimes a disaster;

Attributes of add:

  • positionbefore, after, or replace. Default is replace, so if you forgot to specify position, your code won't be added to the found line, it will replace it. Check this first when "somehow" a piece of original code disappeared;
  • offset="2" — offset in lines. For example, position="after" offset="2" will insert code not immediately after the found line, but two lines later. And position="replace" offset="2" will replace the found line plus the next two.

 

But offset has a problem that I wouldn't touch it at all because of. It counts lines blindly, without looking at what's in them. If another modifier inserted its code near your anchor, or a theme or engine update shifted the file by a line or two, offset will silently replace or touch something completely different from what you intended. The error log stays clean: search found its line, the operation is formally successful. Such bugs are caught very hard later.

 

A more reliable tactic: instead of searching for one line with offset, split the fix into several operations, where each search latches onto a unique meaningful line. That way the modifier either applies exactly where needed, or doesn't apply at all and honestly reports it in the log. The second behavior is much better than "applied in the wrong place". Leave offset for the last resort, when there's simply no stable line nearby to anchor to, and always with a minimal value.

 

Regular expressions are a separate story. When regex="true", attributes position, trim, and offset don't work: everything is controlled by the expression itself, like in preg_replace. Only limit is available to limit the number of replacements. And keep in mind an old bug: combining regex with position before/after behaved incorrectly and deleted the found fragment, so with regular expressions it's safe to rely only on the logic of full replacement. Honestly, in nine out of ten cases you don't need regular expressions in OCMOD. Regular search with index covers almost everything and reads much easier.

 

Separately about paths. Masks work in path, and this saves you when working with themes:

<file path="catalog/view/theme/*/template/product/product.twig">

An asterisk instead of a theme name means "apply to all themes." Without it, a modifier written for default simply won't find the files of your theme Promo or any other.

 

OpenCart 2.x vs 3.x: what changed

 

The difference is significant, and it's exactly where internet instructions break.

In OpenCart 2.x, through Extensions → Installer you could upload both an archive *.ocmod.zip and a bare file *.ocmod.xml. An archive could contain install.sql with database queries and install.php, which would execute during installation.

In OpenCart 3.x, the installer only accepts *.ocmod.zip. Inside the archive, the modifier must be strictly named install.xml, and module files must be in the upload/ folder (the folder structure mirrors the site structure). And fundamentally: install.php and install.sql no longer execute by default in 3.x. If a module for 3.x requires database changes, it makes them through the install() method of its controller, not through an SQL file in the archive. Old manuals for 2.x are frankly harmful here: a person packs install.sql, uploads it, and the tables don't appear in the database and looks for the problem in the wrong place.

If the admin panel is inaccessible for some reason or the installer is acting up with permissions, nothing stops you from throwing the contents of upload/ manually via FTP, and adding the install.xml itself through a third-party modifications editor. But that's already plan B.

 

Typical pitfalls

 

Forgot to click "Refresh." The leader by a wide margin. The modifier is installed, active, and nothing changed on the site. Extensions → Modifications → Refresh, and magic happens.

search doesn't find the line. The second most common reason for a "non-working" module. You're searching for a line from clean OpenCart, but it's already different in the file: the theme has overridden the template, or another modifier previously replaced this fragment with position="replace". OCMOD applies modifications sequentially, and each next one works with the result of the previous ones.

Manual editing of the original had no effect. The mirror situation: you manually edit the system file, but the site ignores the changes. Remember the cache: the site reads a copy from system/storage/modification/, not your edited original. After manual edits to files covered by modifications, the cache must be rebuilt with the same "Refresh" button.

 

And one more small thing that costs hours: OCMOD doesn't strictly validate attributes. You write possition instead of position, and the XML loads without a word of complaint, it just silently uses the default replace. Before looking for complex reasons, reread the attributes letter by letter.

 

If the store crashes after a modifier

 

It happens: a broken modifier replaced the wrong thing, and there's a white page on the site. Don't panic, the originals are intact. Here's what to do: go to the admin panel (it usually survives because the catalog breaks more often), disable the suspicious modifier, click "Refresh." If the admin panel also crashed, delete the contents of system/storage/modification/ via FTP — the site will immediately start working on clean originals, without any modifications. Then calmly go to the admin panel, find the culprit, and rebuild the cache.

 

By the way, there's a log in the modifications section for diagnostics: messages fall there about which operations didn't apply and why. Before blaming the module developer, check it, the answer is often on the surface: search didn't find the line because a neighboring modifier already rewrote it.

 

For whom OCMOD is not the best choice

 

For extending controller logic in OpenCart 2.2+ there's an events system (events): subscription to before/after calls without any line searching. Events are more resilient to updates and don't conflict with each other the way text replacements do. A rule from practice: for PHP logic, first see if the task can be solved with an event, and leave OCMOD for templates, language files, and those places where events can't reach. And one more limitation by definition: OCMOD works with engine files, so it can't make edits in the cache files themselves or in third-party scripts outside the OpenCart structure. But events — that's a separate article.

 

Checklist: writing and installing a modifier

  1. Check the XML header: name, code, version, author, link in place, code is unique.
  2. All code in search and add wrapped in CDATA.
  3. In search only one line of code. Split multi-line fixes into separate operations with unique anchors, offset — only as a last resort.
  4. position specified explicitly, even if it's replace.
  5. For theme templates, the path has a mask theme/*/.
  6. For OC 3.x: archive *.ocmod.zip, inside install.xml plus folder upload/. Don't count on install.sql.
  7. After installation — Extensions → Modifications → Refresh. Always.
  8. Changes didn't apply — first check the modifications log, then verify that the searched line exists in the cached file.
  9. Site crashed — disable the modifier and update the
OCTemplates

OCTemplates

OCTemplates — команда розробників та дизайнерів з України з досвідом у веброзробці з 2002 року. З 2015 року спеціалізуються на шаблонах та модулях для OpenCart: швидких, SEO-оптимізованих і готових до роботи в реальних умовах e-commerce. Продукти OCTemplates використовують тисячі інтернет-магазинів у Європі, Азії, Північній Америці та Австралії. Кожен покупець отримує не лише готове рішення, а й технічну підтримку та консультації з налаштування магазину.

articles
15
views
5,134
likes
5
followers
0

Related Posts

Comments (0)

Replying to

Please log in to leave a comment

Log In

No comments yet

Be the first to comment on this article!

We use cookies

We use cookies and similar technologies to improve your experience, analyse traffic, and show personalised ads. Read our Cookie Policy for details.