views:

37

answers:

3

Hi all,

I have an email xml file like this:

<?xml version='1.0' standalone='yes'?>
<emails>
 <email id="contract-expired">
    <description>We send this email when we want to inform a user that a contract is coming up to it's expiration date</description>
    <subject>Example: Contract Expiration</subject>
    <parameters>
        <param>name</param>
        <param>number_of_contracts</param>
    </parameters>
    <content>
        <html>
            <![CDATA[
            Dear %name%, <br />
            <p>
            <?php
                       foreach($contract as $value):
                         echo $value->getTitle()
                       endforeach;
                    ?>
            You have %number_of_contracts% contracts that are due to expire in under 30 days. Please log in to example.com to review the contracts.
            <br /><br />
            This is an automated email. Please do not reply.
            </p>
            ]]>
        </html>
        <plain>
            Dear %name%, You have %number_of_contracts% contracts that are due to expired in under 30 days. Please log in to example.com to review the contracts. This is an automated email. Please do not reply.
        </plain>
    </content>
 </email>
</emails>

I have a class that processes the email template.

I.e. you set a parameter like so:

$mail->setParameter("name", "Jamie");

And when you call setContent it will do a str_replace on the content for %name% and all other parameters. Simple enough.

And then I realised, what if I need to do a loop in the template to list out all contracts etc. I'd have to do a php loop in the xml file, but how can I pass through an object and then execute the content as php and receive the output?

Any ideas?

Thanks guy!

EDIT: Just to be clear on something. I don't wish to build up the html and then pass it through as a parameter. I'm using symfony and thus I want to keep html out of the controller.

This is where it's being called:

  public function executeContractExpired(sfWebRequest $request)
  {
    $mail = new Mail("contract-expired");
    $mail->setParameter("name", "Joe Bloggs");
    $mail->setParameter("number_of_contracts", 567);
    $mail->setContent();

    $message = $this->getMailer()->compose();
    $message->setSubject($mail->getSubject());
    $message->setTo("[email protected]");
    $message->setFrom(array("[email protected]"=>"Automated Message"));
    $message->setBody($mail->getHtmlContent(), 'text/html');
    $message->addPart($mail->getPlainContent(), 'text/plain');

    $this->getMailer()->send($message);
  }

Doing something like (in the action):

$contracts_html = "<ul>";
foreach($contracts as $contract)
{
    $contracts .= "<li>" . $contract->getTitle() . "</li>"
}
$contracts .= "</il>";

And then passing it through as a parameter:

$mail->addParameter("contracts", $contracts_html);

That method is just ugly.

A: 
$contractTitles = implode(',', $contract);

$mail->setParameter("contract_titles", $contractTitles);

Replace your for loop with %contract_titles%

            <![CDATA[
            Dear %name%, <br />
            <p>
           %contract_titles%
            You have %number_of_contracts% contracts that are due to expire in under 30 days. Please log in to example.com to review the contracts.
            <br /><br />
            This is an automated email. Please do not reply.
            </p>
            ]]>

So build a list of your contract titles and replace it into the message body.

Michael Robinson
Aha, I knew I would get this answer. The problem is, i'm using symfony, and i'm processing this email template in an action. So I don't wish to build up any html in an action, store it in a variable and then put it through as a parameter. I want to keep the html away from the controller.I should have mentioned this.
Jamie
+1  A: 

I'd suggest not having logic in the template. Add a placeholder %contracts% and teach your template handling class how to replace this from within PHP, not the template. You could write a helper class to go alongside your Mailer class. This way, you can keep it out of the controller. IMO, the code configuring the Mailer shouldnt be in there either, but in a Service class in the model.

On a sidenote, this seems to be a good candidate for XSLT.

Gordon
Hmmmm interesting....I shall look into this. Thanks.EDIT: The mail class is just for getting the email template and setting all parameters. It is a seperate entity from $this->getMailer. :-)
Jamie
@Jamie yeah, but still. You could add a class `ContractExpiredMailService` which exposes only the methods required for the Mail to be composed and mailed. All your controller would have to do then is handle the Request and delegate to the service and the service would take care of the rest. By configuring and sending the Mail in the controller, you are effectively handling business logic in the presentation layer.
Gordon
Absolutely. This is the plan....but for the moment i'm just doing some quick testing. Once I have a nice solution in place I will transition everything over to the relevant service classes etc. Thanks.
Jamie
A: 

may be you can use ob_start to prepare the output before it send to email

im sorry i don't do it on class mode. but i hope you this will give you insight.

code is something like this :

function callback($buffer)
{   
    // bundle of string you want to replace
    return str_replace("name", "Mr.John" , $buffer);
}

function getEmail($email_template_path, $contacts){
    ob_start();
    include($email_template_path);
    $email_to_send = ob_get_contents(); 
    ob_end_clean();

    return callback($email_to_send);
}

echo getEmail("/opt/lampp/htdocs/index.html",array("Mr. Smith", "Mrs.Smith"));
Swing Magic