
在使用 cakephp 3 的 `translatebehavior` 时,当用户在非默认语言环境下创建实体,可能会导致默认语言对应的实体字段为空。这会造成 cms 中出现“幽灵”实体,影响数据完整性。本文将介绍如何通过自定义 `translatebehavior`,重写 `aftersave` 事件,在保存非默认语言翻译后,自动填充默认语言实体中为空的字段,从而确保多语言数据的一致性。
CakePHP 3 的 TranslateBehavior 提供了强大的多语言支持,允许为模型中的特定字段存储多种语言的翻译。然而,一个常见的问题是,当网站的当前语言不是默认语言时,如果此时创建一个新的实体并保存,那么默认语言对应的实体记录中的翻译字段可能会保持为空。例如,如果默认语言是英语,当前语言是法语,当用户在法语环境下创建一个产品实体时,该产品的英语名称、描述等字段在数据库中会是 NULL。这在内容管理系统中会造成困扰,因为开发者会看到许多“空”的默认语言实体,影响数据管理和显示。
为了解决上述问题,我们可以通过扩展 CakePHP 3 默认的 TranslateBehavior,并重写其 afterSave 事件。在 afterSave 事件中,我们检查当前保存的实体是否为非默认语言的翻译。如果是,并且默认语言的对应字段为空,我们就将当前语言的翻译内容填充到默认语言的实体中。
首先,创建一个自定义的 TranslateBehavior 类,例如 App\Model\Behavior\TranslateBehavior.php,并让它继承 Cake\ORM\Behavior\TranslateBehavior:
<?php
namespace App\Model\Behavior;
use Cake\Datasource\EntityInterface;
use Cake\Event\Event;
use Cake\I18n\I18n;
use Cake\ORM\Behavior\TranslateBehavior as BaseTranslateBehavior;
use Cake\ORM\TableRegistry;
/**
* 自定义 Translate 行为
* 目的:在非默认语言下保存实体时,如果默认语言实体字段为空,则用当前翻译填充。
*/
class TranslateBehavior extends BaseTranslateBehavior
{
/**
* 在保存后填充原始(未翻译)实体,如果原始字段严格为 null。
*
* @param Event $event 触发的 afterSave 事件
* @param EntityInterface $entity 已翻译的实体
* @return void
*/
public function afterSave(Event $event, EntityInterface $entity)
{
// 调用父类的 afterSave 方法,确保默认的多语言逻辑被执行
parent::afterSave($event, $entity);
$defaultLocale = I18n::getDefaultLocale(); // 获取默认语言环境
$currentLocale = I18n::getLocale(); // 获取当前语言环境
// 如果当前语言环境就是默认语言环境,则无需特殊处理,直接返回
if ($currentLocale === $defaultLocale) {
return;
}
// 获取原始实体对应的 Table 对象
$table = TableRegistry::getTableLocator()->get($entity->getSource());
// 临时将 Table 的语言环境设置为默认语言,以便获取默认语言的实体
$table->setLocale($defaultLocale);
// 根据实体的主键获取默认语言的原始实体
$originalEntity = $table->get($entity->{$table->getPrimaryKey()});
// 遍历行为配置中定义的可翻译字段
$fields = $this->_config['fields'];
foreach ($fields as $field) {
// 如果原始实体的该字段严格为 null,则用当前翻译的字段值填充
if ($originalEntity->{$field} === null) {
$originalEntity->{$field} = $entity->{$field};
}
}
// 临时移除 Table 上的 Translate 行为,防止在保存 originalEntity 时触发递归
// 因为 originalEntity 的保存也会再次触发 afterSave 事件
$table->removeBehavior('Translate');
// 保存更新后的原始实体
$table->save($originalEntity);
// 重新添加 Translate 行为,并使用之前的配置
$table->addBehavior('Translate', $this->_config);
// 将 Table 的语言环境设置回当前语言
$table->setLocale($currentLocale);
}
}代码解析:
立即学习“PHP免费学习笔记(深入)”;
要使用这个自定义的 TranslateBehavior,你需要在你的 Table 类中加载它,替换掉默认的 TranslateBehavior。
例如,在你的 App\Model\Table\ArticlesTable.php 中:
// src/Model/Table/ArticlesTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
class ArticlesTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('articles');
$this->setDisplayField('title');
$this->setPrimaryKey('id');
// 加载自定义的 TranslateBehavior
// 替换掉默认的 'Translate'
$this->addBehavior('App\Model\Behavior\Translate', [
'fields' => ['title', 'body'], // 指定需要翻译的字段
// 其他 TranslateBehavior 配置...
]);
// ... 其他行为和关联
}
}请确保在 addBehavior 中指定了 fields 选项,列出所有需要进行多语言翻译的字段,这些字段将在 afterSave 方法中被遍历和检查。
通过实现这个自定义的 TranslateBehavior,你可以有效解决 CakePHP 3 在非默认语言环境下保存实体时,默认语言实体字段为空的问题,从而构建一个更加健壮和用户友好的多语言应用程序。
以上就是CakePHP 3 多语言行为:解决非默认语言保存导致原始实体为空的问题的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号