带有邮件功能的php循环中的str_replace函数

时间:2014-11-30 20:19:54

标签: php

任何人都可以帮我弄清楚为什么while循环中的str_replace只替换电子邮件模板中的第一行?

以下是代码:

$vehicle=mysql_query("select * from tbl_vehicle where book_id='$booking_Id'");
$i=0;
while($rows=mysql_fetch_array($vehicle)){
    $make = $rows['make'];
    $model = $rows['model'];
    $message = str_replace("[make]",$make,$message);
    $message = str_replace("[model]",$model,$message);
$i++;}

和html模板;

<tr>
<td>Car Make</td>
<td>[make]</td>
</tr>
<tr>
<td>Car Model</td>
<td>[model]</td>

P.S我从数据库中提取模板。

问题是当一辆车预订时工作正常但如果预订的车辆超过一辆,则只能更换电子邮件中的第一辆车辆。

感谢您的帮助。

编辑; 例如,如果预订了1辆车,则在电子邮件模板中显示
制作:Make-One
型号:Model-One

如果预订了2辆车,则在电子邮件模板中显示
制作:Make-One
型号:Model-One

但它应该显示
制作:Make-One
型号:Model-One
制作:Make-Two
型号:Model-Two

希望这能解决问题。

UPDATE; Simon_w解决方案没有工作,但给了我一个想法(我不知道它的最佳方法)

while($rows=mysql_fetch_array($vehicle)){
    $make = $rows['make'];
    $model = $rows['model'];
$i++;
    if($i==2) {
    $message = str_replace("[make]",$make,$message);
    $message = str_replace("[model]",$model,$message);
    $message = str_replace("[make2]",$make,$message);
    $message = str_replace("[model2]",$model,$message);

    }
    else {
    $message = str_replace("[make]",$make,$message);
    $message = str_replace("[model]",$model,$message);
    }
}

和电子邮件模板

<tr>
<td>Car Make</td>
<td>[make]</td>
</tr>
<tr>
<td>Car Model</td>
<td>[model]</td>

<tr>
<td>Car Make</td>
<td>[make2]</td>
</tr>
<tr>
<td>Car Model</td>
<td>[model2]</td>

所以这解决了2车问题,两个细节都显示但是如果只有1辆车预订,那么在电子邮件模板[make2] [model2]中显示空白那么有没有办法在电子邮件模板中使用if语句呢?

3 个答案:

答案 0 :(得分:2)

这是因为您正在更改$message的值。您可以在while循环的开头重新加载它,也可以将其存储到单独的变量中,以便不会覆盖它。例如,您可以使用$body代替$message,这意味着$message的内容永远不会更改。

编辑:通过编辑原始问题,我已经改变了代码以建立电子邮件的正文,方法是在每个循环中附加模板。

$body = '';
while($rows=mysql_fetch_array($vehicle)){
    $make = $rows['make'];
    $model = $rows['model'];
    $body .= str_replace(array("[make]", "[model]"),array($make,$model),$message);
    $i++;
}

答案 1 :(得分:1)

str_replace()将替换字符串中的所有匹配项(即所有占位符),这意味着当您点击第二个DB记录时,没有剩余的占位符可供替换。来自str_replace() manual

  

此函数返回一个字符串或数组,其中所有出现的搜索都被替换为给定的替换值。

您可以使用preg_replace()代替限制为:

$i = 0;
foreach ($example_db_results as $rows) {
    $make = $rows['make'];
    $model = $rows['model'];
    $message = preg_replace("/\[make\]/", $make, $message, 1);
    $message = preg_replace("/\[model\]/", $model, $message, 1);
    $i++;
}

此处示例:https://eval.in/228673

编辑:关注您的评论 - 听起来像是与我的数据不一致...您的模板有固定数量的行,但您的数据库可以有很多行。您应该为每个循环取模板并将其添加到外部HTML变量中,以便HTML行数和数据库行数相等。

在这种情况下,您不需要限制替换,因为只会有其中一个,所以我会向您展示原始尝试的示例:

$i = 0;
$output = '';
foreach ($example_db_results as $rows) {
    $make = $rows['make'];
    $model = $rows['model'];
    // Define your temporary template variable
    $temp_template = $template;
    $temp_template = str_replace("[make]", $make, $temp_template);
    $temp_template = str_replace("[model]", $model, $temp_template);
    // Append the temp template to the output variable
    $output .= $temp_template;
    unset($temp_template);
    $i++;
}

正如@ r3wt在他对你的问题的评论中提到的那样,你可以(并且应该)在执行此操作时将数组传递给str_replace()。如果占位符的数量会增加,那将是一个好主意。

此处示例:https://eval.in/228714

答案 2 :(得分:0)

您应该使用正则表达式以获得更好的结果。

示例:

$template = //email template
$wrapper  = '/\[+(.*?)\]/';
$matches  = array();
preg_match_all($wrapper, $template, $matches);

更新:为误解道歉。我碰巧有一个肮脏的课程,正是OP所要求的!唯一的区别是我使用[{()}]进行换行,并将[<loop>] [</loop>]用于可能包含多个值的元素。

你去;)

class StringTemplate{

    protected $template;
    protected $tokens;
    protected $wrapper;
    protected $loopTag;
    protected $widgets;
    protected $widgetWrapper;
    protected $loopBlock;
    protected $tokenMissed;
    protected $loopTemplate;


    protected $data;


    public function __construct($template)
   {

        $this->data     = array();
        $this->tokens   = array();
        $this->wrapper = '/\[\{\(+(.*?)\)\}\]/';

        $this->widgetWrapper = '/\[\{\(widget:+(.*?)\)\}\]/';


        $this->loopTag  = 'loop';
        $this->loopWrapper =    '/\[\<'.$this->loopTag.'\>\]+(.*?)\[\<\/'.$this->loopTag.'\>\]/s';

        $this->template = $template;



        if  (preg_match($this->loopWrapper, $this->template, $matches)){

            $this->loopBlock      = $matches[1]; 
            $this->loopTemplate = $matches[0]; // includes [<loop>]

        } 

        if  (preg_match_all($this->wrapper, $this->template, $matches)){

            $tokens = $matches[1];

            foreach ($tokens as $token){

                if (strpos($token, ':')){

                    $tokenDetails = explode(':', $token); 
                    $this->tokens[$tokenDetails[0]][] = $tokenDetails[1];

                } else {

                    $this->tokens[] = $token;

                }

            }

        } 
    }


    public function setData($data){

        $offsets = array();
        $missedToken = false;

        /* loop available    */
        if ($this->loopTemplate){

            if (!isset($data[$this->loopTag][0])){

                $missedToken = true;

            } else {

                $offsets = array_merge(array_keys($data), array_keys($data[$this->loopTag][0]));

            }

        } else {

            $offsets = array_keys($data);

        }

        foreach ($this->tokens as $key=>$token){

            if (is_array($token)){

                foreach ($token as $value){

                    if (!isset($data[$key.':'.$value])){

                        $this->tokenMissed[$key][] = $value;

                    }

                }

            } else if (!isset($data[$token])){

                $this->tokenMissed[] = $token;

            }

        }

        if (!$this->tokenMissed){

            // Loop first..

            $loopOutput = null;

            $output = $this->template;

            if (isset($data[$this->loopTag])){

                foreach ($data[$this->loopTag] as $loop){

                    $loopOutput .= $this->wrapData($this->loopBlock,array_merge($data,$loop));

                }

                $output = str_replace($this->loopTemplate, $loopOutput, $this->template);

            }


            $output = $this->wrapData($output,$data);

            return $output;

        }

        //print_r('<pre>');
        //print_r($data);
        //print_r($output);
        //print_r($this->tokenMissed);
        //print_r($offsets);
        //print_r($this->tokens);
        //print_r($this->loopTemplate);
        //print_r(array_diff($this->tokens, $offsets));
        //print_r($this->template);

        //print_r('</pre>');

        //die;



    }


    public function wrapData($template,$data) {

        $output = $template;

        if  (preg_match_all($this->wrapper, $template, $matches)){

            $tokens   = $matches[1];
            $wrappers = $matches[0];

            $values      =  array(); 

            foreach ($tokens as $token){

                if (isset($data[$token])){

                    $values[]  = $data[$token];
                }
            }

            $output = str_replace($wrappers, $values, $template);
        }

        return $output;

    }



    public function getTokens()
    {
        return $this->tokens;
    }




    public function getMissedTokens()
    {
        return $this->tokenMissed;  
    } 


}