2
votes

I'm using Cakephp and try to make my model to ActAs 'Translation'. But i have a problem. My Client model relations are:

public $belongsTo = array("User");
public $hasAndBelongsToMany = array(
    'Category' =>
        array(
            'className' => 'Category',
            'joinTable' => 'categories_clients',
            'foreignKey' => 'client_id',
            'associationForeignKey' => 'category_id',
            'unique' => true,
        ),
);

In Category Model:

public $name = 'Category';
public $hasMany = array(
    'Product'
);
public $displayField = 'title';
public $recursive = 1;
public $actsAs = array(
    'Tree',
    'Translate' => array(
        'title', 
        'alias', 
        'description',
    ),
    'Containable' => array('CategoryTranslations'),
);
public $translateModel = 'CategoryTranslations';
public $translateTable = 'category_translations';

When i query from Client Controller to get all Client and relative Category, i can't get field "title", "alias" and "description" of Category. Here is my code:

    if(isset($this->passedArgs['language_id'])){
        $language_id = $this->passedArgs['language_id'];
    }
    else{
        $language_id = Configure::read('Config.language_site');
    }
    $this->Client->Category->locale = $language_id;
    $this->Client->recursive = 1;
    $this->paginate = array('limit' => 20,'order' => array('User.id' => 'desc'));
    $Clients = $this->paginate();

Here is result:

array(
'Client' => array(
    'id' => '1',
    'user_id' => '1',
    'client_type' => 'tenderer',
    'image' => null,
    'image_list' => null,
    'code' => 'SG0593',
    'name' => 'Oorts',
    'address' => '1000 Huynh Tan Phat',
    'telephone' => '0987654321',
    'fax' => '0983213434',
    'email' => '[email protected]',
    'proxy' => 'Dat Nguyen',
    'position' => 'C.E.O',
    'mobile' => '0987654321',
    'referred_by' => 'noone',
    'order' => null,
    'status' => true,
    'created' => '2014-03-27 00:00:00',
    'modified' => '2014-03-27 00:00:00'
),
'User' => array(
    'password' => '*****',
    'id' => '1',
    'username' => 'admin',
    'group_id' => '1',
    'gender' => 'Male',
    'first_name' => 'Nguyễn',
    'middle_name' => 'Tuấn',
    'last_name' => 'Đạt',
    'email' => '[email protected]',
    'phone_number' => '(+84) 947235313',
    'image' => '/uploads/images/255443_102754699884371_1177788671_n.jpg',
    'status' => true,
    'created' => '2014-01-16 09:26:09',
    'modified' => '2014-01-22 06:47:25',
    'full_name' => 'Nguyễn Tuấn Đạt'
),
'Category' => array(
    (int) 0 => array(
        'id' => '1',
        'parent_id' => '0',
        'type' => 'product',
        'image' => '',
        'order' => '0',
        'status' => true,
        'lft' => '1',
        'rght' => '16',
        'created' => '2014-01-25 00:00:00',
        'modified' => '2014-01-25 00:00:00',
        'CategoriesClient' => array(
            'id' => '1',
            'category_id' => '1',
            'client_id' => '1'
        )
    )
)

)

Can you help me? Thank you!

2

2 Answers

0
votes

Restructure the code

Unfortunately because of how behaviors work - that's none-trivial to solve exactly as asked.

You can however do something like this:

$Clients = $this->paginate();

// extract category ids in the results
$categoryIds = array_unique(Hash::extract($Clients, '{n}.Category.{n}.id'));

$categories = $this->Client->Category->find('all', array(
    'conditions' => array(
        'Category.id' => $categoryIds
    )
));

// generate a category-id indexed array of categories
$categories = Hash::combine($categories, '{n}.Category.id', '{n}.Category');

// replace the untranslated category entries with translated category data
foreach($Clients as &$client) {
    foreach($client['Category'] as &$cat) {
        $id = $cat['id'];
        $cat = $categories[$id];
    }
}

This example is shown as pseudo controller code - you could also consider putting it in your Client afterFind method or a custom finder.

0
votes

Thank for help. I found a solution:

I added bellow code into AppModel->afterFind and it work fine

public function afterFind($results, $primary = false) {    
if(!empty($this->hasAndBelongsToMany)) {
    foreach($this->hasAndBelongsToMany as $model => $settings) {
        if(isset($this->{$model}->actsAs['Translate'])) {
            if(!empty($results[0][$model])) {
                foreach($results as $k => $v){
                    foreach($results[$k][$model] as $row => $result) {
                        $supplement = $this->{$model}->find('first', array(
                            'conditions' => array(
                                $model .'.id' => $result['id']),
                            'fields' => $this->{$model}->actsAs['Translate'],
                            'recursive' => -1));

                        if(!empty($supplement)) {
                            $results[$k][$model][$row] = array_merge($results[$k][$model][$row], array_diff($supplement[$model], $result));
                        }
                    }
                }// end foreach k=>v
            }
        }
    }
}

return $results;

}