I have problem with Kohana 3.3 and ORM relationship has_many_through. I have two models
Model_Category
class Model_Category extends ORM {
protected $_table_name = 'category';
protected $_primary_key = 'category_id';
protected $_has_many = array(
'question' => array(
'model' => 'Question',
'through' => 'cat_question'
),
);
}
Model_Question
class Model_Question extends ORM {
protected $_table_name = 'question';
protected $_primary_key = 'question_id';
protected $_has_many = array(
'category' => array(
'model' => 'Category',
'through' => 'cat_question'
),
);
}
And in table cat_question there are two columns, category_id, question_id,
in table question: question_id, title, content, date,
in category: category_id, name
But it's not working preety good.. When i do it like that
$orm = ORM::factory('Question')->find_all();
foreach($orm as $el) {
var_dump($el->category->name);
}
They shows me NULL, but I don't know why.
I handle with this,
Question model should be looks like that :
class Model_Question extends ORM {
protected $_table_name = 'question';
protected $_primary_key = 'question_id';
protected $_has_many = array(
'category' => array(
'model' => 'Category',
'through' => 'cat_question',
'far_key' => 'category_id',
'foreign_key' => 'question_id',
),
);
}
And Category models
class Model_Category extends ORM {
protected $_table_name = 'category';
protected $_primary_key = 'category_id';
protected $_has_many = array(
'question' => array(
'model' => 'Question',
'far_key' => 'question_id',
'through' => 'cat_question',
'foreign_key' => 'category_id'
),
);
}
And if we want all category with count question is in, do something like that:
public function get_category_and_question() {
$orm = ORM::factory('Category');
$find = $orm->find_all();
foreach ($find as $element) {
$count = ORM::factory('Category', $element->category_id)->question->count_all();
$new_array[] = array(
'name' => $element->name,
'id' => $element->category_id,
'how_much' => $count
);
}
return $new_array;
}
I'm not pretty sure if that is really good solve but is not bad for me.
The problem is, that has_many_through means many-to-many. So one Category holds multiple Questions and vice versa. Now if you had followed Kohana's standards, your db name would be categories, questions, categories_questions and the name would be a plural, so accessible via categories or questions.
But you didn't, to work your code needs to look like the following
$orm = ORM::factory('Question')->find_all();
foreach($orm as $el)
{
$categories = $el->category->find_all();
foreach ($categories as $category)
{
var_dump($category->name);
}
}
Related
Let's say I have a Model_Post that has_may Model_Comment.
Is there any way that the updated_at field of Model_Post gets updated every time that a new comment is saved? I checked the documentation for the observers, but I cannot find how to do that in a "ORM way".
This code doesn't seem to work:
class Model_Comment extends \Orm\Model
{
protected static $_properties = array(
'id',
'post_id',
'text',
);
protected static $_belongs_to = array('post');
protected static $_observers = array(
'Orm\\Observer_UpdatedAt' => array(
'events' => array('before_save'),
'relations' => array('post')
)
);
}
class Model_Post extends Model
{
protected static $_properties = array(
'id',
'title',
'text',
'updated_at'
);
protected static $_has_many = array('comments');
}
I create a new comment using this code:
$comment = Model_Comment::forge();
$comment->message_id = Input::post('message_id');
$comment->text = Input::post('text');
$comment->save();
Instead of mucking about with observers, seeing as you want an ORM-centric approach, you can fetch the parent, update its updated_at, then commit both objects to the DB via the ORM.
However, you're not implementing the whole observer config:. You're missing the property key, and the mysql_timestamp key.
// Adding it with config:
// - only needs to run on before_save
// - use mysql timestamp (uses UNIX timestamp by default)
// - use just "updated" instead of "updated_at"
protected static $_observers = array(
'Orm\\Observer_UpdatedAt' => array(
'events' => array('before_save'),
'mysql_timestamp' => true,
'property' => 'updated',
'relations' => array(
'my_relation',
),
),
);
FuelPHP Observer_UpdatedAt
If you use the relations property of the observer config you can have the updated_at update when relations change. As long as your child model has a relation to the parent model you can add the relation name into the relations property and the ORM will do the rest for you when you save the model.
Please see the first paragraph under the code sample in the documentation.
Finally I found the way to do that thanks to Uru's comments.
This code works now as I wanted; it was simpler than I thought.
Models:
class Model_Comment extends \Orm\Model
{
protected static $_properties = array(
'id',
'post_id',
'text',
);
protected static $_belongs_to = array('post');
}
class Model_Post extends \Orm\Model
{
protected static $_properties = array(
'id',
'title',
'text',
'updated_at'
);
protected static $_has_many = array('comments');
protected static $_observers = array('Orm\Observer_UpdatedAt');
}
And in the controller:
$comment = Model_Comment::forge();
$comment->text = Input::post('text');
$parent_post = Model_Message::find(Input::post('post_id'));
$parent_post->comments[] = $comment;
$parent_post->save();
This is my many to many relation
class Post extends ActiveRecord\Model {
static $table_name = 'app_post';
static $has_many = array(
array('postcategory'),
array('category', 'through' => 'postcategory')
);
}
class Category extends ActiveRecord\Model {
static $table_name = 'app_post_category';
static $has_many = array(
array('post', 'through' => 'postcategory'),
array('postcategory')
);
}
class PostCategory extends ActiveRecord\Model {
static $table_name = 'app_post_category_relation';
static $belongs_to = array(
array('post'),
array('category')
);
}
To create new record in post i use
$post = Post::create(
array(
'title' => 'Title',
'description' => 'Description',
'keyword' => 'key,word'
)
);
$post->create_postcategory(array('category_id' => '1'));
$post->create_postcategory(array('category_id' => '3'));
But i dont know how to update this record ?
$post = Post::find(1);
$post->title = 'Some title';
$post->save();
It's just update post table how about relation table ?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Updated Question
I am trying to Join Multiple tables in CakePHP and retrieve their data.
I have created my Model but not getting relevant result.
Below is my Table Structure.
Fields needed :
Equipment Name
Equipment Description
Equipment Type name according to Equipment id
Equipment Type Sizes names according to Type id
Sizes Stock.
Model:Equipment.php
class Equipment extends AppModel {
public $useTable = 'equipments';
var $name = 'Equipment';
public $cacheQueries = false;
public $hasMany = array(
'Sizes' => array(
'className' => 'EquipmentSize',
'foreignKey' => 'equipment_id'
)
);
}
Model:EquipmentSizes .php
class EquipmentSizes extends AppModel {
public $useTable = 'equipment_sizes';
var $name = 'EquipmentSizes';
public $cacheQueries = false;
public $belongsTo = array(
'Equipment' => array(
'className' => 'Equipment',
'foreignKey' => 'equipment_id',
'fields' => array('id', 'sizes')
)
);
}
Model:EquipmentType.php
class EquipmentType extends AppModel {
public $useTable = 'equipment_types';
var $name = 'EquipmentType';
public $cacheQueries = false;
public $hasMany = array(
'Sizes' => array(
'className' => 'EquipmentTypesSize',
'foreignKey' => 'equipment_type_id'
)
);
}
Model:EquipmentTypesSizes.php
class EquipmentTypesSizes extends AppModel {
public $useTable = 'equipment_types_sizes';
var $name = 'EquipmentTypesSizes';
public $cacheQueries = false;
public $belongsTo = array(
'EquipmentType' => array(
'className' => 'EquipmentType',
'foreignKey' => 'equipment_type_id',
'fields' => array('id', 'sizes')
)
);
}
You have forgotten the foreign keys on some of your models (Equipment.php, EquipmentType.php) that have hasToMany relationship. Correct your models first then try to query an equipment and you can see there the associated models of Equipment. You can then base your conditions to that.
Updated - Equipment.php
class Equipment extends AppModel {
public $useTable = 'equipments';
var $name = 'Equipment';
public $cacheQueries = false;
public $hasMany = array(
'Sizes' => array(
'className' => 'EquipmentSize',
'foreignKey' => 'equipment_id'
),
'EquipmentType' => array(
'className' => 'EquipmentType',
'foreignKey' => 'equipment_id'
)
);
}
EquipmentSizes.php is correct.
Updated - EquipmentType.php
class EquipmentType extends AppModel {
public $useTable = 'equipment_types';
var $name = 'EquipmentType';
public $cacheQueries = false;
public $hasMany = array(
'Sizes' => array(
'className' => 'EquipmentTypesSize',
'foreignKey' => 'equipment_type_id'
)
);
public $belongsTo = array(
'Equipment' => array(
'className' => 'Equipment',
'foreignKey' => 'equipment_id'
)
);
}
EquipmentTypesSizes.php is correct.
I have a weird problem with the Kohana (3.2) ORM query builder and i can't figure out what is wrong. I get "Incorrect table name" exception:
Database_Exception [ 1103 ]: Incorrect table name '' [ SELECT ``.* FROM `` JOIN `user_plugins` ON (`user_plugins`.`plugin_id` = ``.`id`) WHERE `user_plugins`.`user_id` = '9' ]
As you can see the table is empty in the query.
Controller:
$user = ORM::factory('user', Auth::instance()->get_user()->id);
if ($user->loaded() )
{
$result = $user->plugin->find_all();
}
User model:
class Model_User extends Useradmin_Model_User
{
protected $_has_many = array(
'plugin' => array( 'through' => 'user_plugins'),
);
...
user_plugin Model
class Model_user_plugin extends ORM
{
protected $_belongs_to = array(
'plugin' => array(),
'user' => array()
);
...
plugin Model
class Model_Plugin extends ORM
{
protected $_has_many = array(
'user' => array('through' => 'user_plugins')
);
...
Anyone got any idea what could be wrong here?
Any help is very appreciated!
This is how User Model should be
class Model_User extends Useradmin_Model_User
{
protected $_has_many = array(
'plugin' => array('model' => 'plugin', 'through' => 'user_plugins'),
);
...
This is how Plugin Model should be
class Model_Plugin extends ORM
{
protected $_has_many = array(
'user' => array('model' => 'user', 'through' => 'user_plugins')
);
You don't need user_plugin Model at all, the "user_plugins" in both models refers to the table name, not the model name. Just make sure you have the table with user_plugins that have following fields,
id, user_id, plugin_id
I hope this helps.
The $_has_many, by convention, must always use plural names, unless you specify the name in $_object_name in the target model. So it should be:
class Model_Plugin extends ORM
{
protected $_has_many = array(
'users' => array('through' => 'users_plugins')
);
//...
class Model_User extends ORM
{
protected $_has_many = array(
'plugins' => array('through' => 'users_plugins')
);
//...
class Model_user_plugin extends ORM
{
protected $_belongs_to = array(
'plugin' => array(),
'user' => array()
);
//...
How can I load the children entities of a parent in the kohana ORM?
Models:
class Model_User extends ORM
{
protected $_primary_key = 'UserId';
protected $_has_many = array(
'rides' => array(
'model' => 'ride',
'foreign_key'=> 'RideId'
)
);
}
class Model_Ride extends ORM
{
protected $_primary_key = 'RideId';
protected $_belongs_to = array(
'user' => array(
'model' => 'user',
'foreign_key' => 'UserId',
),
);
}
How would I write the query to get a user and all their Ride?
This is what I have so far:
$members = ORM::factory('user');
$members->where('FirstName', '=', 'Peter')->find_all();
How can I do a FirstOrDefault on all those peters and then list all the Rides of that user?
Something like this:
$members = ORM::factory('user');
$members_list = $members->where('FirstName', '=', 'Peter')->find_all();
foreach($members_list as $member) {
$rides = $member->rides->find_all();
foreach($rides as $ride) {
// Work with ride model
}
}