1

In my custom module I want to rewrite parts of several .phtml files. For example, in app/design/frontend/base/default/template/bundle/catalog/product/price.phtml, I want to rewrite <div class="price-box">.

Please note: I do not want to override the entire file, just this one div.

Given that when I override blocks and models I can rewrite individual functions of specific core classes by simply extending the class, I would expect that I could also rewrite a single element of a .phtml file by using SimpleXMLElement::xpath to use xpath to manipulate the XML of the .phtml file itself. That way I could make my module automatically detect if the parts of the .phtml file it's overriding have been changed (say, by an update, or by the installation of another module) and automatically disable my module and warn the user should this occur.

How would I go about approaching doing this? It seems that every guide I can find to how to override a .phtml file takes the rather draconian, brutal, and ugly approach of having a separate folder outside the module's main folder (/app/code/{codePool}/{nameSpace}/{moduleName}), instead putting it into /app/design/frontend/{rest of the path}. This seems very non-ideal because not only does it mean the module is not self-contained in a single directory (for everything but the module's main XML file) but also it requires overriding the entire .phtml file (not just the part you are changing) and it can lead to major problems down the road should there be updates to the file you're overriding (since your module has no way to detect those changes and overrides the entire file).

I just want to find a better way. Is there one?

EDIT:

Clarification: lets say I have a .phtml file with a single div. In that div there are appx. 210 lines of code (some are HTML lines, some are PHP lines). What I want to do is inject 160 new lines of code (some HTML, some PHP) prior to the existing lines that are inside that div, before it gets executed by the PHP interpreter.

3 Answers 3

1

This seems very non-ideal because not only does it mean the module is not self-contained in a single directory ...

What is "non-ideal" about it other than your lack of taste for it? Why does it all have to be in a single directory? Some parts go in design, some parts go in a code pool. If you know what should go where, it is not really an issue most of the time.

... but also it requires overriding the entire .phtml file (not just the part you are changing) ...

There are a number of ways to change content. The approach that it sounds like you're taking is one of "let's do this in a way that nobody would suspect instead of using the built-in tools Magento provides us".

You could, instead, design your own block that does what you want it to do and use your module's layout update XML to remove the old one and add your new one. Nobody says you must rewrite a template.

Please note: I do not want to override the entire file, just this one div.

But, that's the only div in that template.

... and it can lead to major problems down the road should there be updates to the file you're overriding (since your module has no way to detect those changes and overrides the entire file).

Again, nobody says you have to override a file, and even then, if you do there is a package/design system for a reason.


EDIT

If the condition being checked is an admin config value, you can also use the ifconfig attribute to adjust the template being loaded, see: Conditionally show/hide blocks in layout XML

13
  • I see you do not have an answer to my question. But I will at least answer yours: what is non-ideal about it is that it is inconsistent with the manner in which blocks and models get overridden (where you can override just one method as opposed to the entire file). While you're correct that the .phtml file I reference has just the one div, that's besides the point, what about cases where there are more than one div? Maybe I was wrong to hope Magento would have a consistent manner for overriding things. But in the case of the module I'm writing, just doing it in the blocks is not possible.
    – CommaToast
    Commented Jul 29, 2014 at 22:12
  • And that's the thing about "overriding" things in Magento. There is a difference between "I want to use my code instead of Magento's" and "overriding a class/block/file/etc". You don't have to override things to have Magento use your code.
    – pspahn
    Commented Jul 29, 2014 at 23:51
  • Why is it not possible to create your own block class (extended from Mage_Bundle_Block_Catalog_Product_Price), then remove the existing block with your layout update XML and inject your block instead (with appropriate code changes)?
    – pspahn
    Commented Jul 29, 2014 at 23:56
  • That would be much more complicated because it would involve a layout update XML and a lot of duplicated code, which as I stated is what I'm trying to avoid doing, since all that duplicated code could potentially be modified in a future Magento update thus requiring an otherwise unnecessary update to my extension. As I said in the original question, this method would involve me putting in a .phtml file that would be identical except for the 160 lines of new code. It would be much more elegant if I could simply inject that code into the existing file before it gets executed.
    – CommaToast
    Commented Jul 31, 2014 at 2:00
  • 1
    I guess it should depend on what that 160 lines of code does. While I agree that being able to target a specific DOM element without having to resort to Javascript could be handy, I fail to see how its need is warranted here as Magento provides you a way (Layout XML) to add your changes to an existing template.
    – pspahn
    Commented Jul 31, 2014 at 2:17
0

You can use event core_block_abstract_to_html_after, get the block HTML and modify it with regular expression or as XML via DOM / simplexml. No rewrites.

10
  • Well I don't want to rewrite the html after the .phtml has already been run. I want to modify the .phtml file before it gets turned into regular html. Does that make sense? The reason why is because if I have to do what you're saying it will require more code and it won't let me check if the contents of the original .phtml have changed before I rewrite them.
    – CommaToast
    Commented Jul 29, 2014 at 20:45
  • The .phtml file is usual PHP scripth with a lot of HTML code inside. If you want to modify the script structure from the script itself you may think about php.net/manual/en/intro.reflection.php may be...
    – Amasty
    Commented Jul 29, 2014 at 20:53
  • But a .phtml file is specifically not a .php file. Surely there is a place where the .phtml file gets handled by Magento before it gets sent directly to the PHP interpreter?
    – CommaToast
    Commented Jul 29, 2014 at 21:46
  • stackoverflow.com/questions/11859015/…
    – Amasty
    Commented Jul 29, 2014 at 21:53
  • There are some cases where templates do get interpreted (email templates, for example) but other than that, Magento just treats .phtml as a PHP file.
    – pspahn
    Commented Jul 29, 2014 at 21:53
-1

I came across your question when about to ask exactly the same thing myself. It feels as though overriding a whole phtml file is like using a hammer when what you really want is a scalpel. By reading the answers you've received I have convinced myself why things have to be this way.

The big difference between rewriting class methods and the code within a phtml file is what you can sensibly reference. The structure of a class is simple and more importantly predictable, it has methods and properties, nothing else, so its easy to refer to a method and swap it out. What elements would you suggest referencing in a phtml file so that you could inject your code; the div's, span's, fieldset's, line numbers? There are just no natural candidates.

Manipulating the phtml via a DOM would be great, but the phtml files are not well formed XML; try loading one with simpleXML and see how far you get! I think that to be able to manipulate the phtml files, you'd require a manipulator which could also interpret PHP.

Another way of looking at this problem is to reverse your argument. You hold up the ability to override individual class methods as good design, but you don't go on to grumble that its not possible to override individual lines within a class method. All the reasons you gave why its bad you can't modify individual lines within a phtml file apply just as strongly as to why can't modify lines within a class method.

It all boils down to what you can reference. Its easy to reference complete files and methods within a file, but it would be very difficult to reference elements within a phtml file.

I agree that finding overrides during an update is a pain. I use the following algorithm for dealing with this:

  1. Generate a list of all core files which have been overridden - look in app/design/mytheme, app/code/local etc
  2. Compare this list with a list of all files changed by the patch
  3. Merge the changes into the overrides

I've semi automated the first two steps with a small PHP script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.