Home PageКаталог Изменения НовыеКомментарии Пользователи Регистрация
CakePHP: Manual/Developing/Models/Associations ...
Это старая версия Manual/Developing/Models/Associations за 2009-02-25 13:04:40..

Ассоциации: связывание моделей


Одной из самых мощных особенностей CakePHP является способность создавать реляционные связи, предоставляемая моделью. В CakePHP, связи между моделями осуществляются с помощью ассоциаций.


Определение связей между различными объектами в вашем приложении должно быть естественным процессом. Например: рецепт может иметь много оценок, оценки принадлежат (поставлены) авторами, и авторы могут иметь много рецептов. Определив каким образом эти связи будут работать, вы легко сможете получить доступ к вашим данным.


Цель этого раздела – показать как определять и использовать ассоциации между моделями в CakePHP.


Данные могут получаться из разных источников. Наиболее распространенная форма хранения в веб-приложениях – это реляционная база данных. Об этом и пойдет речь в этом разделе.



Типы ассоциаций


В CakePHP существует четыре типа ассоциаций: hasOne, hasMany, belongsTo, hasAndBelongsToMany (HABTM).


Связь Тип ассоциации Пример
один к одному hasOne Пользователь имеет один профиль
один ко многим hasMany Пользователь имеет много рецептов
многие к одному belongsTo Рецепты принадлежат пользователю
многие ко многим hasAndBelongsToMany Рецепты имеют и принадлежат множеству тегов

Ассоциации определяются созданием переменной класса, имя которой совпадает с названием, определяемой вами, ассоциации. Эта переменная может быть простой, как строка, а может быть сложной, как многомерный массив, используемый для определения особенностей ассоциации.


<?php

class User extends AppModel {
    var 
$name 'User';
    var 
$hasOne 'Profile';
    var 
$hasMany = array(
        
'Recipe' => array(
            
'className'  => 'Recipe',
            
'conditions' => array('Recipe.approved' => '1'),
            
'order'      => 'Recipe.created DESC'
        
)
    );
}
?>


В приведенном примере в строке 'className' => 'Recipe', 'Recipe' – это алиас. Это идентификатор для связи и может быть любым. Обычно, вы будете выбирать такое же имя, которое имеет класс, на который ссылается данный класс. Алиасы должны быть уникальными как для отдельных моделей, так и с двух сторон связей belongsTo/hasMany или belongTo/hasOne. Выбор не уникальных имен для алиасов моделей, может стать причиной непредсказуемого поведения.


CakePHP будет автоматически создавать связи между ассоциируемыми объектами моделей. Таким образом, например, в вашей модели User вы можете получить доступ к модели Recipe:


<? $this->Recipe->someFunction(); ?>


Подобным образом, в вашем контроллере вы можете получить доступ к ассоциируемым моделям, без добавления их в массив $uses:


<? $this->User->Recipe->someFunction(); ?>


Помните, что ассоциации, определяются в одну сторону. Если вы определили User hasMany Recipe, 
то это ничего не дает модели Recipe. Вам необходимо определить Recipe belongsTo User для того, 
чтобы можно было обращаться к модели User из модели Recipe.



hasOne


Давайте создадим hasOne ассоциацию модели User с моделью Profile.


Во-первых, ваши таблицы БД должны иметь корректные ключи. Для того, чтобы связь hasOne работала, одна таблица должна содержать внешний (вторичный) ключ, который указывает на запись другой таблицы. В данном случае таблица profiles будет содержать поле с именем user_id.
hasOne: другая модель содержит внешний ключ.


Связь Схема данных
Apple hasOne Banana bananas.apple_id
User hasOne Profile profiles.user_id
Doctor hasOne Mentor mentors.doctor_id

Файл модели User будет сохранен в /app/models/user.php. Для определения ассоциации 'User hasOne Profile', добавьте свойство $hasOne в класс модели. Не забудьте создать модель Profile в /app/models/profile.php, иначе ассоциация не будет работать.


<?php

class User extends AppModel {
    var 
$name 'User';                
    var 
$hasOne 'Profile';   
}
?>


Существует два способа для описания этой связи в вашем файле модели. Самый простой – это присвоить переменной $hasOne строку, содержащую имя класса ассоциируемой модели (как мы сделали выше).


Если вам надо больше управления, то вы можете определить вашу ассоциацию, используя синтаксис массива. Например, вы можете захотеть ограничить ассоциацию, включая, только определенные записи.


<?php

class User extends AppModel {
    var 
$name 'User';          
    var 
$hasOne = array(
        
'Profile' => array(
            
'className'    => 'Profile',
            
'conditions'   => array('Profile.published' => '1'),
            
'dependent'    => true
        
)
    );    
}

?>


Возможные индексы для hasOne ассоциации:



После того, как эта ассоциация определена, find методы модели User будут также выбирать данные ассоциированной модели Profile, если они существуют:


//Образец результатов после вызова $this->User->find().

Array
(
    [User] => Array
        (
            [id] => 121
            [name] => Gwoo the Kungwoo
            [created] => 2007-05-01 10:31:01
        )
    [Profile] => Array
        (
            [id] => 12
            [user_id] => 121
            [skill] => Baking Cakes
            [created] => 2007-05-01 10:31:01
        )
)



belongsTo


Теперь у нас есть доступ к модели Profile из модели User, давайте определим ассоциацию belongsTo в модели Profile для того, чтобы получить доступ к данным модели User. Ассоциация belongsTo – естественное дополнение к hasOne и hasMany: она позволяет нам видеть данные в обратном направлении.


При создании ключей таблиц БД для ассоциации belongsTo следуйте следующему соглашению:


Связь Схема данных
Banana belongsTo Apple bananas.apple_id
Profile belongsTo User profiles.user_id
Mentor belongsTo Doctor mentors.doctor_id

Если модель (таблица) содержит внешний ключ, то она belongsTo другой модели (таблице).


Мы можем определить belongsTo ассоциацию в нашей модели Profile в /app/models/profile.php, используя строковый синтаксис:


<?php

class Profile extends AppModel {
    var 
$name 'Profile';                
    var 
$belongsTo 'User';   
}
?>


Мы так же можем определить и более специфическую связь, используя синтаксис массива:


<?php

class Profile extends AppModel {
    var 
$name 'Profile';                
    var 
$belongsTo = array(
        
'User' => array(
            
'className'    => 'User',
            
'foreignKey'    => 'user_id'
        
)
    );  
}
?>


Возможные индексы для массивов belongsTo ассоциации:



После того, как данная ассоциация определена, find операции модели Profile будут также выбирать данные из модели User, если таковые имеются:


//Образец результатов после вызова $this->Profile->find().

Array
(
   [Profile] => Array
        (
            [id] => 12
            [user_id] => 121
            [skill] => Baking Cakes
            [created] => 2007-05-01 10:31:01
        )    
    [User] => Array
        (
            [id] => 121
            [name] => Gwoo the Kungwoo
            [created] => 2007-05-01 10:31:01
        )
)



hasMany


Следующий шаг: определение ассоциации “User hasMany Comment”. Ассоциация hasMany позволит нам получать все комментарии пользователя, когда мы выбираем этого пользователя.


При создании ключей таблиц БД для ассоциации hasMany следуйте следующему соглашению:


Связь Схема данных
User hasMany Comment Comment.user_id
Cake hasMany Virtue Virtue.cake_id
Product hasMany Option Option.product_id

Мы можем определить ассоциацию hasMany в нашей модели User в /app/models/user.php, используя строковый синтаксис:


<?php

class User extends AppModel {
    var 
$name 'User';                
    var 
$hasMany 'Comment';   
}
?>


Мы так же можем определить и более специфическую связь, используя синтаксис массива:


<?php

class User extends AppModel {
    var 
$name 'User';                
    var 
$hasMany = array(
        
'Comment' => array(
            
'className'     => 'Comment',
            
'foreignKey'    => 'user_id',
            
'conditions'    => array('Comment.status' => '1'),
            
'order'    => 'Comment.created DESC',
            
'limit'        => '5',
            
'dependent'=> true
        
)
    );  
}
?>


Возможные индексы для массивов hasMany ассоциации:


Второй параметр метода Model->delete() должен быть установлен в true для включения рекурсивного удаления.



 
Комментарии
Может быть, в HABTM кейк создаст модель Recipes Tags?, а не Recipes Tag??
80.64.175.115.sta.211.ru (2009-07-09 13:51:17)
HABTM выносит мозк :)
214.206.150.178.triolan.net (2012-01-22 16:57:10)
Добавить комментарий:

Файлов нет. [Показать файлы/форму]