Magento Email Template If Statements
Asked Answered
S

4

21

The Magento Email Template If Statements aren't evaluating to true when I expect them to. Can someone tell me what's wrong? Take a look at the following code:

{{var customer.group_id}}
{{if customer.group_id}}Print true{{else}}Print false{{/if}}
{{if customer.group_id==4}}Print true{{else}}Print false{{/if}}
{{if customer.group_id=4}}Print true{{else}}Print false{{/if}}
{{if customer.group_id eq 4}}Print true{{else}}Print false{{/if}}

The output is

4
Print True
Print False
Print False
Print False

I tried putting quotes around the 4, but same result. How do I evaluate equalities with magento email template if statements?

Sculpt answered 25/1, 2011 at 18:27 Comment(0)
D
16

Digging through the code, it looks like the template logic is implemented by Varien_Filter_Template (under lib\Varien not app\code) in the filter function which issues a callback to the ifDirective function if the pattern matches the regex. The ifDirective in turn uses the _getVariable function to evaluate your if condition. _getVariable then tokenizes the condition in Varien_Filter_Template_Tokenizer_Variable into either a property or a method.

if($this->isWhiteSpace()) {
            // Ignore white spaces
            continue;
        } else if($this->char()!='.' && $this->char()!='(') {
            // Property or method name
            $parameterName .= $this->char();
        } else if($this->char()=='(') {
            // Method declaration
            $methodArgs = $this->getMethodArgs();
            $actions[] = array('type'=>'method',
                               'name'=>$parameterName,
                               'args'=>$methodArgs);
            $parameterName = '';
        } else if($parameterName!='') {
            // Property or variable declaration
            if($variableSet) {
                $actions[] = array('type'=>'property',
                                   'name'=>$parameterName);
            } else {
                $variableSet = true;
                $actions[] = array('type'=>'variable',
                                   'name'=>$parameterName);
            }
            $parameterName = '';
        }

When the if condition is detected to be a method, it will execute that method, otherwise it simply returns the string value of the variable.

All of which means (I think!) that if you want to evaluate an expression inside the if statement, you need to add a new customer attribute (there are extensions available for this) that the template can evaluate. So if you define a boolean "isMemberOfGroupNameX" attribute, then the template should work.

I imagine this is not the answer that you're looking for, but I'm fairly sure that's the case.

HTH, JD

Dinge answered 25/1, 2011 at 23:59 Comment(3)
Correct me if I'm wrong, but from what you say, he could also create a method of some sort (maybe a helper method?) that could check this as well, right?Kauri
You might also be able to build the logic outside the template to populate a certain customer variable at runtime.Orna
@Joseph - yes, you could create a method, but I think it would need to be on the Customer object so that you could use {{if customer.isGroupMember()}} which requires you to extend the Customer model. Not something that I'd necessarily recommend for this requirement, but still a valid optionDinge
N
34

I solved this problem by using the 'block' technique.

What you do is you pass the order to a block and then do your logic inside that block.

Although my solution is for a different problem the approach should work here.

What I wanted was to have a pay by cheque option and some extra text in the confirmation email reminding them to pay. I added this into the new order template:

{{block type='core/template' area='frontend' template='paymentstatus/orderemail.phtml' order=$order}}<br />

Then I created a file app/design/frontend/default/default/template/paymentstatus/orderemail.phtml

This has the 'if' logic, in my case I wanted to see if the order status was that for a cheque and only then remind the customer that their order needed cleared funds.

<?php if($this->getData('order')->getStatus()=='cheque') {
echo "<p>Please note that we will require your cheque to clear before we can despatch your order.</p>"; }?>
Nanceenancey answered 8/7, 2011 at 17:58 Comment(7)
where is {{block type='core/template' area='frontend' template='paymentstatus/orderemail.phtml' order=$order}}<br /> this code you placedPsalterium
Thank you! Added instruction on Russian language, magefast.com/letter-template-magento-fantasticoThunderstone
I used the following code to retrieve the payment type: $payment_type = $this->getData('order')->getPayment()->getMethodInstance()->getCode();Sampson
Hi deanpodgornik, where did you add that code? To email template or to the orderemail.phtmlBlearyeyed
This worked in 1.9, but it broke the preview function in the admin -- not a bad trade-off.Choline
I like this idea, but am having trouble. Text from the additional template file is being included when the email template is previewed, but not when sending. I have tried using echo within PHP statements, as well as just including plain text in template and the result is always the same -- it is displayed when previewing but not included when sending. Any idea what I might check?Kela
Ack. Scratch that. Magento was looking in frontend/base/default/template/my_thing/email.phtml and file was in frontend/default/default/template/my_thing/email.phtml -- apparently preview could find it there, but send method could not. Resolved.Kela
D
16

Digging through the code, it looks like the template logic is implemented by Varien_Filter_Template (under lib\Varien not app\code) in the filter function which issues a callback to the ifDirective function if the pattern matches the regex. The ifDirective in turn uses the _getVariable function to evaluate your if condition. _getVariable then tokenizes the condition in Varien_Filter_Template_Tokenizer_Variable into either a property or a method.

if($this->isWhiteSpace()) {
            // Ignore white spaces
            continue;
        } else if($this->char()!='.' && $this->char()!='(') {
            // Property or method name
            $parameterName .= $this->char();
        } else if($this->char()=='(') {
            // Method declaration
            $methodArgs = $this->getMethodArgs();
            $actions[] = array('type'=>'method',
                               'name'=>$parameterName,
                               'args'=>$methodArgs);
            $parameterName = '';
        } else if($parameterName!='') {
            // Property or variable declaration
            if($variableSet) {
                $actions[] = array('type'=>'property',
                                   'name'=>$parameterName);
            } else {
                $variableSet = true;
                $actions[] = array('type'=>'variable',
                                   'name'=>$parameterName);
            }
            $parameterName = '';
        }

When the if condition is detected to be a method, it will execute that method, otherwise it simply returns the string value of the variable.

All of which means (I think!) that if you want to evaluate an expression inside the if statement, you need to add a new customer attribute (there are extensions available for this) that the template can evaluate. So if you define a boolean "isMemberOfGroupNameX" attribute, then the template should work.

I imagine this is not the answer that you're looking for, but I'm fairly sure that's the case.

HTH, JD

Dinge answered 25/1, 2011 at 23:59 Comment(3)
Correct me if I'm wrong, but from what you say, he could also create a method of some sort (maybe a helper method?) that could check this as well, right?Kauri
You might also be able to build the logic outside the template to populate a certain customer variable at runtime.Orna
@Joseph - yes, you could create a method, but I think it would need to be on the Customer object so that you could use {{if customer.isGroupMember()}} which requires you to extend the Customer model. Not something that I'd necessarily recommend for this requirement, but still a valid optionDinge
L
7

I was able to more or less accomplish this right in the template using {{depend}} template tags.

{{depend somevar}}
Print this if somevar evaluates to true
{{/depend}}

You will have to conjure up this variable in app/code/local/Mage/Sales/Model/Order.php in the methods like sendNewOrderEmail() and so forth.

Langrage answered 14/8, 2011 at 8:59 Comment(1)
Would it be possible to detect free shipping method? {{depend $order.freeshippingmethod}} ... help appreciatedWoermer
M
0

Within normal Magento blocks/classes you would use $customer->getGroupId() to access the group id value. The CMS/Email template equivalent is customer.getGroupId(), not customer.group_id like you wrote.

Murrey answered 19/9, 2014 at 19:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.