任何人都可以帮我弄清楚为什么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语句呢?
答案 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++;
}
编辑:关注您的评论 - 听起来像是与我的数据不一致...您的模板有固定数量的行,但您的数据库可以有很多行。您应该为每个循环取模板并将其添加到外部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()
。如果占位符的数量会增加,那将是一个好主意。
答案 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;
}
}