CakePHP does not save to the database - php

So I have three tables, the users, groups and users_groups which is a join table.
--
-- Table structure for table `groups`
--
CREATE TABLE `groups` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`description` text NOT NULL,
`all_versions_available` tinyint(1) unsigned NOT NULL DEFAULT '1',
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`,`created`,`modified`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(40) NOT NULL,
`email` varchar(80) NOT NULL,
`password` varchar(50) NOT NULL,
`role` varchar(20) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`fullname` varchar(80) NOT NULL,
`password_token` varchar(40) NOT NULL,
PRIMARY KEY (`id`),
KEY `nickname` (`username`,`email`,`password`),
KEY `role` (`role`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
-- --------------------------------------------------------
--
-- Table structure for table `users_groups`
--
CREATE TABLE `users_groups` (
`user_id` int(11) unsigned NOT NULL,
`group_id` int(11) unsigned NOT NULL,
KEY `user_id` (`user_id`,`group_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Before I have implemented the HABTM in my Group and User models, the code I have below worked fine, now, I am getting all the data I need but I am unable to save.
So, my Group Model looks like this:
<?php
class Group extends AppModel {
public $hasAndBelongsToMany = array(
'Application' => array(
'className' => 'Application',
'joinTable' => 'applications_groups',
'foreignKey' => 'group_id',
'associationForeignKey' => 'application_id',
'unique' => 'keepExisting',
),
'User' => array(
'className' => 'User',
'joinTable' => 'users_groups',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
)
);
public $validate = array(
'name' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Group name is required'
)
)
);
public function saveGroup($id, $name, $description) {
$id = (int)$id;
if ($id) {
$this->id = $id;
}
else {
$this->create();
}
$this->set('name', $name);
$this->set('description', $description);
$this->save();
return $this;
}
public function getAll() {
$options = array('order' => array('Group.name' => 'ASC'));
$data = $this->find('all', $options);
return $data;
}
public function getOne($id) {
$id = (int)$id;
return $this->find('first', array('conditions' => array('Group.id' => $id)));
}
}
My User model looks like this:
<?php
class User extends AppModel {
public $hasAndBelongsToMany = array(
'Group' => array(
'className' => 'Group',
'joinTable' => 'users_groups',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
)
);
public function getOne($id) {
$this->id = $id;
$data = $this->read(null, $id);
unset($data['User']['password']);
unset($data['User']['password_token']);
if (isset($data['User'])) $data['User']['gravatar_url'] = 'http://www.gravatar.com/avatar/'.md5($data['User']['email']).'.jpg';
return $data;
}
private function addGravatars($data) {
foreach ($data as $key=>$user) {
$data[$key]['User']['gravatar_url'] = 'http://www.gravatar.com/avatar/'.md5($user['User']['email']).'.jpg';
}
return $data;
}
public function getAll() {
$data = $this->find('all', array('order' => array('User.fullname' => 'ASC')));
$data = $this->addGravatars($data);
return $data;
}
public function countAll() {
return $this->find('count');
}
}
I have been using model for the join table:
<?php
class UsersGroup extends AppModel {
public function deleteAllWithGroup($groupId) {
$id = (int)$groupId;
return $this->deleteAll(array('UsersGroup.group_id' => $id), false);
}
public function saveUsersForGroup($users, $groupId=0) {
$this->deleteAllWithGroup($groupId);
$data = array();
foreach ($users as $id=>$user) {
$data[] = array('user_id'=>(int)$id, 'group_id'=>$groupId);
}
$this->saveMany($data);
}
}
And this is my Groups controller:
<?php
class GroupsController extends AppController {
var $uses = array('Group', 'User', 'UsersGroup');
public function index() {
$this->set('groups', $this->Group->getAllWithInfo());
}
public function edit($id=0) {
$this->set('group', $this->Group->getOne($id));
$this->set('usersList', $this->User->getAllWithGroupInfo($id));
if ($this->request->is('post')) {
$group = $this->Group->saveGroup($this->request->data['id'], $this->request->data['name'], $this->request->data['description']);
// Saving users
if (!isset($this->request->data['user']) || empty($this->request->data['user'])) {
$this->UsersGroup->deleteAllWithGroup($group->id);
}
else $this->UsersGroup->saveUsersForGroup($this->request->data['user'], $group->id);
}
}
public function view($id) {
App::uses('Platforms', 'Lib/Platform');
$this->setPageIcon('group');
$this->set('group', $this->Group->getOne($id));
}
public function delete($id) {
$this->Group->delete((int)$id);
return $this->redirect(array('action' => 'index'));
}
}
There is a couple of issues, the system above works if I remove the HABTM configs, second, I don't, for some very specific reasons not using the forms helper to generate the form and unfortunately for the complexity of the code (this is just a little bit) I can't so I have to name everything manually myself (that's where I see the biggest potential for failure) and lastly when I fire this code now I get:
Database Error
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'deleteAllWithGroup' at line 1
SQL Query: deleteAllWithGroup
Notice: If you want to customize this error message, create app/View/Errors/pdo_error.ctp
So the UsersGroup model is not being registered, nothing changes when I even delete the file, it is trying to use the name of the method I have previously used to delete the old join data as an SQL command. I have tried all the possible suggestions for naming and structure of the data I have found on Stack but failed, furthest I got was when I got only one of the join items to save, always the last one in the array ...
Anyone can help with this one?
Cheers,
O.

Be conventional
The main problems here seem to be caused by being unconventional
Table names
The docs describe the following:
This new join table’s name needs to include the names of both models involved, in alphabetical order, and separated with an underscore ( _ )
As such by default CakePHP will expect the join table for such a relationship to be called groups_users.
Model names
Given the above the join model for the relationship will be GroupsUser. Defining the hasAndBelongsToMany relationship as follows:
public $hasAndBelongsToMany = array(
'Group' => array(
'className' => 'Group',
'joinTable' => 'users_groups',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
)
);
Means that CakePHP will still try and user a model named GroupsUser giving it the table name users_groups. To forcibly user a different join model it's necessary to define which model to use - with with:
public $hasAndBelongsToMany = array(
'Group' => array(
'className' => 'Group',
'joinTable' => 'users_groups',
'foreignKey' => 'group_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting',
'with' => 'UsersGroup'
)
);
Though it would be better to rename the join table and the join model, therefore the config could be reduced to the following, as everything else would be the defaults:
public $hasAndBelongsToMany = array(
'Group' => array(
'unique' => 'keepExisting'
)
);
Calls to a model function that don't exist becomes sql queries
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'deleteAllWithGroup' at line 1
SQL Query: deleteAllWithGroup
All this demonstrates, is that a query was made on a class which did not implement the called function. This can be verified by checking the class of the object:
debug($this->UsersGroup);
// Most likely "AppModel"
Note that the join model itself does not have any associations defined, as such doing this:
$this->UsersGroup->unbind(...);
Will have no effect - the associations are defined on the models User and Group in the question, even if the class UsersGroup were to be loaded - it does not have any associations defined, much less a habtm relationship to something else (which would require a total of 5 tables!)
Finally, and probably most importantly: this function isn't necessary:
HABTM data is treated like a complete set, each time a new data association is added the complete set of associated rows in database is dropped and created again
It won't cause problems to fix the code so the method is called except that the join table records are deleted whether the save succeeds or not with the code in the question; whereas CakePHP's logic will only delete the join table records upon success.
Be wary of creating thin wrapper functions
While there's nothing wrong with creating methods on your models to encapsulate logic - if that logic is very easily expressed using the existing model api all that does is make the code harder for others to read/debug. Code like this:
public function getOne($id) {
$this->id = $id;
$data = $this->read(null, $id);
unset($data['User']['password']);
unset($data['User']['password_token']);
if (isset($data['User'])) $data['User']['gravatar_url'] = 'http://www.gravatar.com/avatar/'.md5($data['User']['email']).'.jpg';
return $data;
}
Can easily be replaced with a find('first') call and adding a afterFind filter to the User model to add gravatar_url keys to returned results. This leads to less and simpler code.

Related

How to save images with Cakephp-File-Storage?

UPDATE
So I added some logs to the action upload in ProductsController and the method upload in MediasTable to find out what is happening. The entity from ProductsController this->Products->Medias->newEntity() was pass to MediasTable but it wasn't save.
It is necessary to upload the file to save the data in the db? Like if all the data is ok but the file is no present the event will be reject the data and do nothing in the db?
I'm using cakephp 3.1 with the file-storage plugin. I'm following the quickstart guide from the docs: Quick-Start but I don't understand some parts and doesn't upload, insert in database neither make thumbnails.
This is my database:
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
product_name VARCHAR(255) NOT NULL,
quantity INT NOT NULL,
sold INT NOT NULL,
description VARCHAR(1000),
price DECIMAL(7,2) NOT NULL,
old_price DECIMAL(7,2) NOT NULL,
visited INT NOT NULL,
status INT NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE media_types (
id INT AUTO_INCREMENT PRIMARY KEY,
name_media_type VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE medias (
id INT AUTO_INCREMENT PRIMARY KEY,
media_type_id INT NOT NULL,
product_id INT NOT NULL,
path VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME,
FOREIGN KEY media_type_key (media_type_id) REFERENCES media_types(id),
FOREIGN KEY product_key (product_id) REFERENCES products(id)
);
MediasTable:
...
use Burzum\FileStorage\Model\Table\ImageStorageTable;
class MediasTable extends ImageStorageTable {
public function initialize(array $config) {
parent::initialize($config);
$this->table('medias');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('MediaTypes', [
'foreignKey' => 'media_type_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Products', [
'foreignKey' => 'product_id',
'joinType' => 'INNER'
]);
}
...
public function upload($productId, $entity) {
$media = $this->patchEntity($entity, [
'adapter' => 'Local',
'model' => 'Media',
'foreign_key' => $productId
]);
Log::write('debug', $media);
return $this->save($media);
}
}
ProductsTable:
class ProductsTable extends Table {
public function initialize(array $config) {
parent::initialize($config);
$this->table('products');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('Medias', [
'className' => 'Medias',
'foreignKey' => 'foreign_key',
'conditions' => [
'Medias.model' => 'Media'
]
]);
}
...
}
ProductsController:
class ProductsController extends AppController {
public function upload($productId = null) {
$productId = 2;
$entity = $this->Products->Medias->newEntity();
if ($this->request->is(['post', 'put'])) {
$entity = $this->Products->Medias->patchEntity(
$entity,
$this->request->data
);
if ($this->Products->Medias->upload($productId, $entity)) {
$this->Flash->set(__('Upload successful!'));
}
}
$this->set('productImage', $entity);
}
...
}
In config/local_store.php is the same as the example (I include this file in boostrap.php)
...
$listener = new LocalFileStorageListener();
EventManager::instance()->on($listener);
$listener = new ImageProcessingListener();
EventManager::instance()->on($listener);
Configure::write('FileStorage', [
'imageSizes' => [
'Medias' => [
'large' => [
...
]);
FileStorageUtils::generateHashes();
StorageManager::config('Local', [
'adapterClass' => '\Gaufrette\Adapter\Local',
'adapterOptions' => [TMP, true],
'class' => '\Gaufrette\Filesystem'
]);
upload.ctp
echo $this->Form->create($productImage, array('type' => 'file'));
echo $this->Form->file('file');
echo $this->Form->error('file');
echo $this->Form->submit(__('Upload'));
echo $this->Form->end();
In the quick start there is two upload methods: uploadImage and uploadDocument
but in the controller they use "upload".
There is another association in Products in the example, I need this?:
$this->hasMany('Documents', [
'className' => 'FileStorage.FileStorage',
'foreignKey' => 'foreign_key',
'conditions' => [
'Documents.model' => 'ProductDocument'
]
]);
I found this question (from there is the db I'm using) Getting Started with cakephp-file-storage quickstart guide and upload and insert but doesn't make the thumbnails and if I change the table to ImageStoreTable shows an error "Class not found"
So if anybody can help me I will be very grateful!

Error when creating a virtual field inside a model

I'm having a hard time setting up a virtual field in one of my model. I've been setting virtualfields like this in all of my models without any issue. However, for some reason I can't figure out, it's not working at all in this model.
Error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'databases WHERE id = `DataSourceName`.`database_id`) AS `DataSourceName__databa' at line 1
Model:
<?php
App::uses('AppModel', 'Model');
/**
* DataSourceName Model
*
* #property Database $Database
*/
class DataSourceName extends AppModel {
public $virtualFields = array(
'database' => 'SELECT name FROM databases WHERE id = DataSourceName.database_id',
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Database' => array(
'className' => 'Database',
'foreignKey' => 'database_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
SQL:
CREATE TABLE IF NOT EXISTS data_source_names(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) DEFAULT NULL,
description VARCHAR(255) DEFAULT NULL,
database_id INT(10) UNSIGNED DEFAULT NULL,
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL,
created_by INT(10) UNSIGNED DEFAULT NULL,
modified_by INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB
AUTO_INCREMENT = 1
CHARACTER SET utf8
COLLATE utf8_unicode_ci;
Update 1
SQL failing:
(SELECT name FROM databases WHERE id = `DataSourceName`.`database_id`) AS `DataSourceName__database`
Here's what I ended up using for the SQL:
SELECT name FROM my_db.databases WHERE id = `DataSourceName`.`database_id`
Note the database name prefix (ie. my_db) in front of the table databases. Probably due to databases being a reserved word.
Final Model:
<?php
App::uses('AppModel', 'Model');
/**
* DataSourceName Model
*
* #property Database $Database
*/
class DataSourceName extends AppModel {
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$fields = get_class_vars('DATABASE_CONFIG');
$this->virtualFields['database'] = sprintf(
'SELECT name FROM %s.databases WHERE id = DataSourceName.database_id', $fields['default']['database']
);
}
//The Associations below have been created with all possible keys, those that are not needed can be removed
/**
* belongsTo associations
*
* #var array
*/
public $belongsTo = array(
'Database' => array(
'className' => 'Database',
'foreignKey' => 'database_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}

Can't figure out how to associate tables with php active record

I must be missing something important but I can't sort this thing out
I would like to associate many addresses to a person so ... here we go with my settlement:
Is there anyone to help?
CREATE TABLE `testpersons` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
CREATE TABLE `testaddresses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
CREATE TABLE `testassociate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`testuser_id` int(11) NOT NULL,
`testgroup_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
Then I create my objects:
class Testperson extends ActiveRecord\Model {
static $table_name = 'testpersons';
static $has_many = array(
array('testaddress',
'through'=>'test_associate',
'foreign_key'=>'testgroup_id',
'primary_key'=>'testuser_id',
'class_name'=>'Testaddress')
);
}
class Testaddress extends ActiveRecord\Model {
static $table_name = 'addresses';
static $belongs_to = array(
array('testperson',
'through'=>'test_associate',
'foreign_key'=>'testuser_id',
'primary_key'=>'testgroup_id')
);
}
Then trying to get my result:
$person = Testperson::find(2);
echo var_dump ( $person);
Gives that:
object(Testperson)[16]
public 'errors' => null
private 'attributes' (ActiveRecord\Model) =>
array (size=2)
'id' => int 2
'name' => string 'tata' (length=4)
private '__dirty' (ActiveRecord\Model) =>
array (size=0)
empty
private '__readonly' (ActiveRecord\Model) => boolean false
private '__relationships' (ActiveRecord\Model) =>
array (size=0)
empty
private '__new_record' (ActiveRecord\Model) => boolean false
Could someone tell me what's wrong with my association?
Many thx
If all you want to do is associate many Address to one Person, than your db structure is wrong and unnecessarily complex.
What you want is this:
CREATE TABLE `testpeople` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `testaddresses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`testperson_id` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
);
Now your model would be like this:
class Testaddress extends ActiveRecord\Model {
static $belongs_to = array(
array('testperson')
);
}
class Testperson extends ActiveRecord\Model {
static $table_name = 'testpeople';
static $has_many = array(
array('testaddress')
);
}
That should be enough.
However, when you want to use through, you should have also a model for the intermediate table with the respective relationship.
For example sake, I'll use your db structure.
class Testperson extends ActiveRecord\Model {
static $table_name = 'testpeople';
static $has_many = array(
array('testassociate', 'foreign_key' => 'testuser_id'),
array('testaddress', 'through' => 'testassociate', 'foreign_key' => 'testgroup_id')
);
}
class Testassociate extends ActiveRecord\Model {
static $belongs_to = array(
array('testperson', 'foreign_key' => 'testuser_id'),
array('testaddress', 'foreign_key' => 'testgroup_id'),
);
}
class Testaddress extends ActiveRecord\Model {
static $has_one = array(
array('testassociate', 'foreign_key' => 'testgroup_id'),
array('testaddress', 'through' => 'testassociate', 'foreign_key' => 'testuser_id'),
);
}
Regarding the empty __relathionships, it's because that's a cache variable that will be populated when you request some relation, such as $person->testaddresses.

cakephp foreign key dropdown not working in scaffold

My schema is quite simple-
Each user has an id and name.
There are jobs which belong to a user. Actual schema-
CREATE TABLE `users` (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`name` varchar(20)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `jobs` (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`user_id` INT UNSIGNED ,
`type` int,
FOREIGN KEY (user_id) references users(id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
My JobsController looks like this-
<?php
class JobsController extends AppController {
public $scaffold;
public $name = 'Job';
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
}
And UsersController as-
<?php
class UsersController extends AppController {
public $scaffold;
public $name = 'User';
public $hasMany = array(
'Job' => array(
'className' => 'Job',
'foreignKey' => 'user_id'
)
);
}
Problem:
When I visit http://hostname/Jobs/add I can see a drop-down for user but its empty.
I've created few users which I can see from http://hostname/Users/
Why is drop-down empty? I am able to add jobs but when I view them, user field is shown empty.
Associations belong in the Model, not the controller.
In app/Model/User.php:
class User extends AppModel {
public $name = 'User';
public $hasMany = array('Job');
}
In app/Model/Job.php
class Job extends AppModel {
public $name = 'Job';
public $belongsTo = array('User');
}

many-to-many relationship on kohana 3.2

I've got some trouble trying to make this work. I have 2 models, User_Pro and Category. I read the relationships documentation on kohana guide and I understand i need to define a $_has_many relationship on the User_Pro and Category models and create the model user_pro_categories with the belongs_to field.
User_Pro model:
protected $_has_many = array(
'categories' => array(
'model' => 'TM_Category',
'through' => 'user_pro_categories',
'foreign_key' => 'id_user_pro',
),
);
Category model:
protected $_has_many = array(
'users_pro' => array(
'model' => 'TM_User_Pro',
'through' => 'user_pro_categories',
'foreign_key' => 'id_category',
),
);
user_pro_categories model:
protected $_belongs_to = array(
'user_pro' => array(
'model' => 'TM_User_Pro',
'foreign_key' => 'id_user_pro',
),
'category' => array(
'model' => 'TM_Category',
'foreign_key' => 'id_category',
),
);
The error I'm getting is:
Database_Exception [ 1054 ]: Unknown column 'tm3_user_pro_categories.category_id' in
'on clause' [ SELECT `tm3_tm_category`.* FROM `tm3_categories` AS `tm3_tm_category` JOIN
`tm3_user_pro_categories` ON (`tm3_user_pro_categories`.`category_id` = `tm3_tm_category`.`id_category`)
WHERE `tm3_user_pro_categories`.`id_user_pro` = '2' ]
It's like it doesn't care about the fk's i defined and it want's to use the suffix thing... any idea?
Here is the example to give you quick idea how Kohana ORM works. And wish it will be helpful for others too.
Student Model
<?php defined('SYSPATH') or die('No direct script access.');
class Model_Student extends ORM {
protected $_primary_key = 'idstudent'; // take a look
protected $_has_many = array(
'courses'=> array(
'model' => 'course', // Course model
'through' => 'students_courses', // many-to-may through
'far_key' => 'id_for_course', // "column name" relating to the Course Model in "students_courses" table
'foreign_key' => 'id_for_student' // "column name" relating to the Student Model in "students_courses" table
),
);
}
Course Model
<?php defined('SYSPATH') or die('No direct script access.');
class Model_Course extends ORM {
protected $_primary_key = 'idcourse'; // take a look
protected $_has_many = array(
'students'=> array(
'model' => 'student',
'far_key' => 'id_for_student',
'through' => 'students_courses',
'foreign_key' => 'id_for_course'
),
);
}
SQL Script
CREATE TABLE IF NOT EXISTS `students` (
`idstudent` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`idstudent`)
) ENGINE=MyISAM;
INSERT INTO `students` (`idstudent`, `name`) VALUES
(1, 's1'),
(2, 's2');
/* column idcourse and PR idcourseS ? */
CREATE TABLE IF NOT EXISTS `courses` (
`idcourse` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`idcourse`)
) ENGINE=MyISAM;
INSERT INTO `courses` (`idcourse`, `name`) VALUES
(1, 'c1'),
(2, 'c2'),
(3, 'c3');
CREATE TABLE IF NOT EXISTS `students_courses` (
`id_for_student` int(10) unsigned NOT NULL,
`id_for_course` int(10) unsigned NOT NULL
) ENGINE=MyISAM;
INSERT INTO `students_courses` (`id_for_student`, `id_for_course`) VALUES
(1, 1),
(1, 3);
$student = new Model_Student(1);
$courses = $student->courses->find_all();
echo Debug::vars($courses);
foreach($courses as $course) {
echo Debug::vars($course->object());
}
Running code above will create following SQL query.
SELECT `course`.* FROM `courses` AS `course` JOIN `students_courses` ON (`students_courses`.`id_for_course` = `course`.`idcourse`) WHERE `students_courses`.`id_for_student` = '1'
You don't need to create a model for pivot table for many-to-many relationship. Just define the through option in both models, make sure your primary/foreign keys follow Kohana convention and you're ready to go. Below example from Kohana ORM User and Role models:
class Model_User
{
protected $_has_many = array(
'roles' => array('model' => 'role', 'through' => 'roles_users'),
);
}
class Model_Role
{
protected $_has_many = array(
'users' => array('model' => 'user', 'through' => 'roles_users')
);
}

Categories