You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 9中如何编写可复用的占位符文本替换通用函数/文件

邮件编辑器通用占位符动态替换方案需求与实现思路

需求背景

我正在开发一个邮件内容编辑器项目,需要将编辑器中的默认占位符替换为数据库存储的用户数据。编辑器部分已完成,但不知道如何编写可在全项目复用的通用函数/文件,实现占位符与关联模型动态值的替换。

占位符示例

原始内容:

"Hello {customer_name}, This is your content of the day {content_date}"

替换后效果:

"Hello Mano, This is your content of the day 3-Feb-2023"

注意:项目采用一对多关联模型获取内容数据,实现时需遵循该结构。

现有实现及痛点

目前已通过硬编码str_replace实现替换,以下两段代码均可正常运行,但每次新增或修改占位符都需修改业务代码,无法集中维护:

示例代码1

$contents = EmailContent::all();
foreach($contents as $inv)
{
    $message = $inv->email_content;
    $message = str_replace('{customer_name}' , $inv->customer->name, $message);
    $message = str_replace('{content_date}', $inv->content_date, $message);
}

示例代码2

$contents = EmailContent::all();
foreach($contents as $inv)
{
    $userData = User::find($inv->user_id);
    $message = $inv->email_content;
    $message = str_replace('{user_fullname}', $userData->fullname, $emailBody);
    $message = str_replace('{user_company_name}' , $userData->company_name, $emailBody);
}

期望实现

希望将所有占位符的替换规则集中管理在公共位置,后续新增或更新占位符时无需修改业务代码,最终需实现的替换逻辑如下:

$message = str_replace('{customer_name}' , $inv->customer->name, $message);
$message = str_replace('{content_date}', $inv->content_date, $message);
$message = str_replace('{user_fullname}', $userData->fullname, $emailBody);
$message = str_replace('{user_company_name}' , $userData->company_name, $emailBody);
// return $message;
// or 
// echo $message;

可行实现方案

方案1:配置文件+辅助函数(推荐)

  1. 创建占位符配置文件
    在config/placeholders.php中集中定义占位符和对应的取值逻辑:
return [
    '{customer_name}' => function($data) {
        return $data['inv']->customer->name;
    },
    '{content_date}' => function($data) {
        return $data['inv']->content_date;
    },
    '{user_fullname}' => function($data) {
        return $data['user']->fullname;
    },
    '{user_company_name}' => function($data) {
        return $data['user']->company_name;
    },
];
  1. 编写通用替换辅助函数
    在app/helpers.php中实现核心替换逻辑:
function replace_placeholders($content, $data) {
    $placeholders = config('placeholders');
    foreach ($placeholders as $placeholder => $callback) {
        $content = str_replace($placeholder, $callback($data), $content);
    }
    return $content;
}
  1. 业务代码中调用
$contents = EmailContent::all();
foreach($contents as $inv)
{
    $userData = User::find($inv->user_id);
    $message = replace_placeholders($inv->email_content, [
        'inv' => $inv,
        'user' => $userData
    ]);
    // 使用替换后的$message
}

方案2:专用服务类封装

创建app/Services/PlaceholderReplacer.php类,封装所有替换逻辑:

namespace App\Services;

class PlaceholderReplacer
{
    protected $placeholders = [
        '{customer_name}' => 'getCustomerName',
        '{content_date}' => 'getContentDate',
        '{user_fullname}' => 'getUserFullname',
        '{user_company_name}' => 'getUserCompanyName',
    ];

    protected $data;

    public function __construct($data)
    {
        $this->data = $data;
    }

    public function replace($content)
    {
        foreach ($this->placeholders as $placeholder => $method) {
            $content = str_replace($placeholder, $this->$method(), $content);
        }
        return $content;
    }

    protected function getCustomerName()
    {
        return $this->data['inv']->customer->name;
    }

    protected function getContentDate()
    {
        return $this->data['inv']->content_date;
    }

    protected function getUserFullname()
    {
        return $this->data['user']->fullname;
    }

    protected function getUserCompanyName()
    {
        return $this->data['user']->company_name;
    }
}

业务代码调用:

$contents = EmailContent::all();
foreach($contents as $inv)
{
    $userData = User::find($inv->user_id);
    $replacer = new \App\Services\PlaceholderReplacer([
        'inv' => $inv,
        'user' => $userData
    ]);
    $message = $replacer->replace($inv->email_content);
    // 使用替换后的$message
}

方案3:模型访问器(仅适用于EmailContent场景)

如果替换逻辑仅和EmailContent模型绑定,可在模型中定义访问器:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class EmailContent extends Model
{
    public function getReplacedContentAttribute()
    {
        $content = $this->email_content;
        $userData = User::find($this->user_id);
        
        $replacements = [
            '{customer_name}' => $this->customer->name,
            '{content_date}' => $this->content_date,
            '{user_fullname}' => $userData->fullname,
            '{user_company_name}' => $userData->company_name,
        ];

        return str_replace(array_keys($replacements), array_values($replacements), $content);
    }
}

调用时直接获取属性:

$contents = EmailContent::all();
foreach($contents as $inv)
{
    $message = $inv->replaced_content;
    // 使用替换后的$message
}

内容的提问来源于stack exchange,提问作者Mano Mahe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 13:21:24