本文目录导读:

- 使用
str_replace简单替换 - 使用正则表达式批量替换
- 使用 Laravel Str::replaceArray
- 创建独立的短信模板类
- 使用数据库存储模板
- 完整的 send 服务示例
- 控制器中使用
- 单元测试
- 推荐的实现方式
在Laravel中实现短信模板变量替换,我推荐以下几种方法:
使用 str_replace 简单替换
<?php
namespace App\Services;
class SmsService
{
/**
* 短信模板变量替换
*/
public function replaceTemplateVariables(string $template, array $variables): string
{
foreach ($variables as $key => $value) {
$template = str_replace('{' . $key . '}', $value, $template);
}
return $template;
}
// 使用示例
public function sendVerificationCode(string $phone, string $code): void
{
$template = '您的验证码是{code},{minutes}分钟内有效。';
$variables = [
'code' => $code,
'minutes' => 5
];
$message = $this->replaceTemplateVariables($template, $variables);
// 发送短信逻辑
}
}
使用正则表达式批量替换
<?php
namespace App\Services;
class SmsTemplateService
{
/**
* 正则替换模板变量
*/
public function replaceVariables(string $template, array $variables): string
{
return preg_replace_callback(
'/\{(\w+)\}/',
function($matches) use ($variables) {
$key = $matches[1];
return isset($variables[$key]) ? $variables[$key] : $matches[0];
},
$template
);
}
}
使用 Laravel Str::replaceArray
<?php
namespace App\Services;
use Illuminate\Support\Str;
class SmsService
{
public function send(string $template, array $variables): string
{
// 方法一:使用 Str::replaceArray
$keys = array_map(fn($key) => '{' . $key . '}', array_keys($variables));
$message = Str::replaceArray($template, $keys, array_values($variables));
// 方法二:使用 Str::replace
foreach ($variables as $key => $value) {
$template = Str::replace('{' . $key . '}', $value, $template);
}
return $template;
}
}
创建独立的短信模板类
<?php
namespace App\Services\Sms;
class SmsTemplate
{
/**
* 模板内容
*/
protected string $content;
/**
* 模板变量
*/
protected array $variables = [];
/**
* 可用的短信模板
*/
const TEMPLATE_LOGIN_CODE = '您的登录验证码是{code},请勿泄露。';
const TEMPLATE_REGISTER = '欢迎注册,您的验证码为{code},有效期{minutes}分钟。';
const TEMPLATE_ORDER = '您的订单{order_no}已支付成功,金额{amount}元。';
public function __construct(string $template)
{
$this->content = $template;
}
public function with(array $variables): self
{
$this->variables = $variables;
return $this;
}
public function render(): string
{
$content = $this->content;
foreach ($this->variables as $key => $value) {
$content = str_replace('{' . $key . '}', $value, $content);
}
return $content;
}
// 快捷方法
public static function loginCode(string $code): string
{
return (new self(self::TEMPLATE_LOGIN_CODE))
->with(['code' => $code])
->render();
}
public static function order(string $orderNo, float $amount): string
{
return (new self(self::TEMPLATE_ORDER))
->with([
'order_no' => $orderNo,
'amount' => number_format($amount, 2)
])
->render();
}
}
使用数据库存储模板
<?php
namespace App\Services;
use App\Models\SmsTemplate;
use Illuminate\Support\Facades\Cache;
class SmsTemplateService
{
/**
* 从数据库获取模板并渲染
*/
public function renderByCode(string $code, array $variables): string
{
// 缓存模板
$template = Cache::remember("sms_template_{$code}", 3600, function() use ($code) {
return SmsTemplate::where('code', $code)->first();
});
if (!$template) {
throw new \Exception("短信模板不存在: {$code}");
}
// 替换变量
$content = $template->content;
foreach ($variables as $key => $value) {
$content = str_replace('{' . $key . '}', $value, $content);
}
return $content;
}
}
// 数据库迁移示例
Schema::create('sms_templates', function (Blueprint $table) {
$table->id();
$table->string('code')->unique();
$table->text('content');
$table->string('description')->nullable();
$table->timestamps();
});
完整的 send 服务示例
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class SmsService
{
protected $apiUrl;
protected $appKey;
protected $appSecret;
public function __construct()
{
$this->apiUrl = config('services.sms.api_url');
$this->appKey = config('services.sms.app_key');
$this->appSecret = config('services.sms.app_secret');
}
/**
* 发送验证码
*/
public function sendVerificationCode(string $phone, string $code, int $minutes = 5): bool
{
$template = '验证码:{code},{minutes}分钟内有效,请勿泄露给他人。';
$content = $this->renderTemplate($template, [
'code' => $code,
'minutes' => $minutes
]);
return $this->send($phone, $content);
}
/**
* 发送订单通知
*/
public function sendOrderNotification(string $phone, array $orderData): bool
{
$template = '您的订单{order_no}已支付成功,支付金额¥{amount}元。';
$content = $this->renderTemplate($template, [
'order_no' => $orderData['order_no'],
'amount' => $orderData['amount']
]);
return $this->send($phone, $content);
}
/**
* 渲染模板
*/
protected function renderTemplate(string $template, array $variables): string
{
$search = array_map(fn($key) => '{' . $key . '}', array_keys($variables));
$replace = array_values($variables);
return str_replace($search, $replace, $template);
}
/**
* 实际发送短信
*/
protected function send(string $phone, string $content): bool
{
$response = Http::post($this->apiUrl, [
'phone' => $phone,
'content' => $content,
'app_key' => $this->appKey,
'timestamp' => time(),
'sign' => $this->generateSign($phone, $content)
]);
if ($response->successful()) {
Log::info('短信发送成功', [
'phone' => $phone,
'content' => $content
]);
return true;
}
Log::error('短信发送失败', [
'phone' => $phone,
'content' => $content,
'response' => $response->json()
]);
return false;
}
/**
* 生成签名
*/
protected function generateSign(string $phone, string $content): string
{
$params = [
'phone' => $phone,
'content' => $content,
'timestamp' => time()
];
ksort($params);
$str = http_build_query($params) . $this->appSecret;
return md5($str);
}
}
控制器中使用
<?php
namespace App\Http\Controllers;
use App\Services\SmsService;
use Illuminate\Http\Request;
class SmsController extends Controller
{
protected $smsService;
public function __construct(SmsService $smsService)
{
$this->smsService = $smsService;
}
public function sendCode(Request $request)
{
$request->validate([
'phone' => 'required|phone'
]);
$code = random_int(100000, 999999);
// 保存验证码到 session 或 cache
cache()->put('sms_code_' . $request->phone, $code, now()->addMinutes(5));
$result = $this->smsService->sendVerificationCode(
$request->phone,
$code
);
return response()->json([
'success' => $result
]);
}
}
单元测试
<?php
namespace Tests\Feature;
use Tests\TestCase;
class SmsServiceTest extends TestCase
{
public function test_template_replacement()
{
$service = new \App\Services\SmsService();
$template = '您的验证码是{code},{minutes}分钟内有效。';
$result = $this->invokePrivateMethod($service, 'renderTemplate', [
$template,
['code' => '123456', 'minutes' => 5]
]);
$this->assertEquals('您的验证码是123456,5分钟内有效。', $result);
}
protected function invokePrivateMethod($object, $methodName, $parameters = [])
{
$reflection = new \ReflectionClass($object);
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
}
}
推荐的实现方式
如果项目简单,推荐使用方式1(简单数组替换);如果项目复杂且需要管理多个模板,推荐使用方式4(独立模板类)或方式5(数据库存储模板),这样更好维护和扩展。
使用 Laravel 的 翻译函数也可以实现类似功能:
__('sms.verification_code', ['code' => $code, 'minutes' => 5]);
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播