Doctrine 1.2 自动加入 i18n?

Posted

技术标签:

【中文标题】Doctrine 1.2 自动加入 i18n?【英文标题】:Doctrine 1.2 auto-join i18n? 【发布时间】:2011-03-25 17:14:19 【问题描述】:

我想扩展 i18n 行为,以便它在任何类型的查询(DQL、关系、getTable)上自动加入转换表。 此外,它需要定义默认语言参数,所以当我在没有设置语言的情况下进行查询时,它会退回到默认语言。 注意:我正在寻找一种通用行为,因此它适用于所有 i18n 模型对象,而不是为每个类编写和覆盖。

这是一个例子: 表product -> id、category_id、价格... 表product_translation -> id、语言、名称、描述...

当我做这样的事情时,使用当前的解决方案:Doctrine_Core::getTable('Product')->findAll(),它可以在不加入翻译的情况下获得所有产品。 所以在控制器中我必须循环遍历所有记录并重新应用翻译值,$product->name = $product->Translation['en']->name

我想要这样的东西:

Doctrine_Core::getTable('Product')->findAll() 它应该得到 lang='en' 的连接值 Doctrine_Core::getTable('Product)->findAll('en')同上 它也应该适用于关系,例如,如果我有一个类 User 有很多产品 $user->Products 它应该返回一个包含翻译的集合。 类似$user->Products('en') 的东西也应该返回其他(非默认)语言的集合 魔术函数也不错(如果可能的话)...类似于Doctrine_Core::getTable('Product')->getByCategoryAndLang(1,'en')

有人可以帮忙吗?我正在查看模板和行为,我认为这是要走的路,但不知道如何实现这一点

编辑:我发现对此没什么兴趣,所以让我尝试一个更简单的问题。您通常如何通过关系获得 i18n 字段。例如,我如何致电$user->Products 并获取已加载翻译的产品?

【问题讨论】:

【参考方案1】:

我认为你不需要扩展标准的 Doctrine 行为,除非你想要这个完全自动化。但是您仍然可以像我们一样尝试这样做 - 我们使用 DAO(数据访问对象)返回具体的 Doctrine 实体(Doctrine 表表示):

\DAO::get('Some\Namespace\Classname')

其中Classname 代表php 类模型描述的表。我们的 DAO 类创建了 Classname 的实例,该实例封装在 proxy 中(请参阅设计模式)。

除了表类模型,我们为这个表创建了另一个类,它位于表模型之上并使用这个模型进行操作。在这个类中,我们编写了 getProducts($args)getProduct($id)getProductsByCategory($catId) 等方法。

我认为这就是你要找的……

在方法getProducts($args) 中,您可以在DQL 中实现->leftJoin(),它将通过$args 参数中给定的$lang 标识符加入翻译表。简单示例(未测试):

class Products extends \DAO 
    public function save($item) 
        $item->save();
    

    public function getProducts($args = array()) 
        $order = array('p.id');

        $result = \Doctrine_Query::create()
            ->from('Some\Namespace\Product p')
            ->where('1 = 1');

        if(!empty($args['lang'])) 
            $result = $result->leftJoin('Some\Namespace\ProductTranslation pt ON pt.product_id = p.id AND pt.language = ?', $args['lang']);
        

        $result = $result->orderBy($order);

        $result = $result->execute();

        return $result;
    

然后通过调用

$products = DAO::get('Some\Namespace\Product')->getProducts(array('lang' => 1));

您获得所有已加载英文翻译的产品...

它不是那么自动化,您必须为每个模型编写自己的 DAO 类,但这是一种很好的方法,因为您有 MVC/MVP 对象所需的不同数据定义类(模型)和数据操作类(控制器)面向应用架构...

【讨论】:

谢谢,但您的建议可以在没有 DAO 的情况下完成。只需声明 ProductTable 类,并添加与 Translation 进行连接的 getXy 方法。无论如何它并没有解决问题,因为我仍然无法使用 $product->name 访问这些字段,但是 $product->Translation['en']->name 您无法通过product 模型访问name 属性,因为此模型中没有描述(也不存在于 db 表中)。使用我的方法,您可以在一个对象中(在 Doctrine_Collection 中)获得所有列 - 并进行一次具体翻译。所以循环通过$products = DAO::get('Some\Namespace\Product')->getProducts(array('lang' => 1));foreach($products as $product) ...可以恕我直言访问$product->name。你不能吗? 嗯...我不认为你仍然可以访问它,就像你说它没有在模态中描述。我能做的是将它作为数组水化,然后重新排列结果(删除翻译,并将名称向上传播一级)。这就是我现在正在使用的。但是,与 Table 类中的普通定义方法相比,我看不出你的方法有什么不同

以上是关于Doctrine 1.2 自动加入 i18n?的主要内容,如果未能解决你的问题,请参考以下文章

Doctrine 1.2 hasOne 覆盖 hasMany 关系

教义 2 - i18n 的最佳实践?

Doctrine 1.2 多对多关系的列命名约定

将原始 MySQL 翻译成 Doctrine 1.2

Doctrine2 - 加入非相关表

Doctrine 1.2 保存记录关系 UPDATE 而不是 INSERT