I'm having problems with a very simple ordering query. I have a Post model and a Tag model with a HABTM relationship and am trying to return a list of all posts with a particular tag assigned to them, ordered by the date the post is created.
$this->set('data', $this->Post->Tag->find('all', array(
'conditions' => array('Tag.id' => 1),
'contain' => array('Post' => array(
'order' => 'Post.created_date desc'
))
)));
While this returns the list of posts, it is not sorted by date.
With debugging on, it looks like the following query is being used:
SELECT `Post`.`id`, `Post`.`title`, `Post`.`created_date`, `PostsTag`.`post_id`, `PostsTag`.`tag_id`
FROM `database`.`posts` AS `Post`
JOIN `database`.`posts_tags` AS `PostsTag` ON (`PotsTag`.`tag_id` = 1 AND `PostsTag`.`post_id` = `Post`.`id`)
Code for posts model:
class Post extends AppModel {
public $name = 'Post';
public $hasAndBelongsToMany = array('Tag');
}
Code for tags model:
class Tag extends AppModel {
public $name = 'Tag';
public $hasAndBelongsToMany = array('Post');
}
Any help on the issue would be much appreciated - I'm using CakePHP 2.1. if it makes any difference.
What about defining the order attribute in your Tag Model?
Like e.g.
var $hasAndBelongsToMany = array(
'Post' => array(
'order' => 'Post.created_date'
)
);
I don't think that the "order" should be inside of "contain".
Try with:
$this->set('data', $this->Post->Tag->find('all', array(
'conditions' => array('Tag.id' => 1),
'contain' => array('Post'),
'order' => 'Post.created_date desc'
)));
or just:
$this->set('data', $this->Post->Tag->find('all', array(
'conditions' => array('Tag.id' => 1),
'order' => 'Post.created_date desc'
)));
Read this:-
http://www.jamesfairhurst.co.uk/posts/view/adding_tags_to_a_cakephp_app_hasAndBelongsToMany/
http://edivad.wordpress.com/2007/04/19/cakephp-hasandbelongstomany-habtm/
//try this
CREATE TABLE `tags` (
`id` int(11) NOT NULL auto_increment,
`tag` varchar(100) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `posts_tags` (
`post_id` int(11) NOT NULL,
`tag_id` int(11) NOT NULL
);
//Creating the Models and Relationships
class Tag extends AppModel {
var $name = 'Tag';
var $hasAndBelongsToMany = array('Post'=>array('className'=>'Post'));
}
class Post extends AppModel {
var $name = 'Post';
var $hasMany = array('Comment'=>array('className'=>'Comment'));
var $hasAndBelongsToMany = array('Tag'=>array('className'=>'Tag'));
}
Related
I have a few Tables/Models and I want to show the content of the models in one view.
My Schema:
My Models:
Adress:
var $name = "Adress";
public $belongsTo = array("Customer", "Country");
public $hasAndBelongsToMany = array(
'Contactperson' => array(
'className' => 'Contactperson'
)
);
ContactPerson:
var $name = "Contactperson";
public $hasAndBelongsToMany = array(
'Adress' => array(
'className' => 'Adress'
)
);
Country:
var $name = "Country";
public $hasMany = "Adress";
Customer:
var $name = "Customer";
public $hasMany = array(
'Adress' => array(
'className' => 'Adress',
'order' => array('Adress.mainadress DESC', 'Adress.created DESC')
)
);
My CustomerController:
$customer = $this->Customer->findByid($customerId);
$this->set('customer', $customer);
The return value is the content of the customer and the adress table but I want to get the content of every table.
I want to get a array with the content from customers, addresses, contactpeople and countries.
Thanks for helping.
Once you setup and linking each table correctly (with foreign key and db design), then you can retrieve all the related field easily with CakePHP.
Read up on CakePHP containable.
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
Recursive will also works, but higher recursive value can hurt your system if its getting too big.
My app works fine on my local server and I had to change the .htaccess files so that the cakephp app website would work on godaddy hosting, but now I found that some of the information is not retrieved from the tables in the live website which is weird because the same information is retrieved in my local app... I've lost hours searching for the cause but haven't found a possible explanation yet...
On this particular view I should get all the product prices doing this (only works locally):
public function index() {
$options = array('contain' => 'ProductPrice');
$this->set('products', $this->Product->find('all', $options));
}
The necessary models are loaded above in the controller with:
public $uses = array('ProductPrice', 'Product', 'MenuSection');
In the view I should get something like: (which happens in my local app)
products(array)
0(array)
Product(array)
ProductPrice(array)
1(array)
Product(array)
ProductPrice(array)
(and so on...)
but what I'm getting is: (which happens in my live app)
products(array)
0(array)
Product(array)
1(array)
Product(array)
(but no ProductPrice arrays...)
These are the table structures:
CREATE TABLE `product_prices` (
`id` tinyint(9) unsigned NOT NULL AUTO_INCREMENT,
`price` float(6,2) DEFAULT NULL,
`product_id` varchar(36) DEFAULT NULL,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=181 DEFAULT CHARSET=utf8;
CREATE TABLE `products` (
`id` int(9) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`description` text,
`menu_nr` int(9) DEFAULT NULL,
`menu_section_id` int(9) DEFAULT NULL,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=96 DEFAULT CHARSET=utf8;
These are the models:
class ProductPrice extends AppModel {
public $name = 'ProductPrice';
public $useTable = 'product_prices';
public $actsAs = array('Containable');
public $belongsTo = array('Product');
public $validate = array(
'product_id' => array(
'rule' => 'notEmpty',
'message' => 'This is a required field and cannot be left empty.'
),
);
}
class Product extends AppModel {
public $name = 'Product';
public $actsAs = array('Containable');
public $hasMany = array(
'ProductPrice'
);
public $belongsTo = array(
'MenuSection',
);
public $validate = array(
'name' => array(
'rule-empty' => array(
'rule' => 'notEmpty',
'message' => 'This is a required field and cannot be left empty.'
),
'rule-unique' => array(
'rule' => 'isUnique',
'message' => 'There is already one product with that name.'
),
),
'menu_nr' => array(
'rule' => 'isUnique',
'message' => 'There is already one product with that Menu Item Nr.'
)
);
}
Could anyone help me find the cause? Where else should I look for? Any hints or best practice suggestions are welcome too, thanks.
I finally figured it out... it was a simple problem after all. My model names were called 'product.php' and 'product_prices.php' because I followed CakePHP blog example, but once I changed them to 'Product.php' and 'ProductPrice.php' (and so on...) they started working! I thought about this before but forgot to actually try it while in the middle of the mess. Cheers for trying to help
So I have a self-referencing model like so.
class Category extends AppModel {
public $order = "Category.name";
public $belongsTo = array(
'ParentCategory' => array(
'className' => 'Category',
'foreignKey' => 'parent_id',
'order' => 'ParentCategory.name'
)
);
}
The sql query it produces is this:
SQL Query: SELECT `ParentCategory`.`id`, `ParentCategory`.`name` FROM `cakephp`.`categories` AS `ParentCategory` WHERE 1 = 1 ORDER BY `Category`.`name` ASC
Which will not work because "Category" is not a table name here.
What am I doing wrong here. Why is it not respecting my "order" rule?
I found the solution to a simliar issue in the CakePHP docs:
http://book.cakephp.org/2.0/en/models/virtual-fields.html#virtual-fields-and-model-aliases
So basically, anytime you want to use Model Aliasing, it is best to define the values in the constructor like this:
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->order = $this->alias.".whatever";
}
I have the table 'posts' and 'users':
CREATE TABLE `posts` (
`id` int(11) unsigned NOT NULL auto_increment,
`name` varchar(255) default NULL,
`date` datetime default NULL,
`content` text,
`user_id` int(11) default NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL auto_increment,
`name` varchar(100) default NULL,
`email` varchar(150) default NULL,
`firstname` varchar(60) default NULL,
`lastname` varchar(60) default NULL,
PRIMARY KEY (`id`)
);
and the model classes:
<?php
class Post extends AppModel {
var $name = 'Post';
var $belongsTo = array(
'User'=>array(
'className'=>'User',
'foreignKey'=>'user_id',
'conditions'=>null,
'fields'=>null)
);
}
?>
<?php
class User extends AppModel {
var $name = 'User';
var $hasMany = array('Post');
}
?>
I am testing using var $scaffold.
However, after I add some users, I can only see an empty select menu in the add post page, which means the association is not working. I don't know what is wrong with my code. Please help me out.
Thank you very much!
See the below url:-
http://book.cakephp.org/1.3/view/1042/belongsTo
http://book.cakephp.org/1.3/view/1043/hasMany
//Try This for belongsTo :--
<?php
class Profile extends AppModel {
var $name = 'Profile';
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
}
?>
Or
<?php
class Profile extends AppModel {
var $name = 'Profile';
var $belongsTo = array('User');
}
?>
//For hasmany
<?php
class User extends AppModel {
var $name = 'User';
var $hasMany = array(
'Post' => array(
'className' => 'Post',
'foreignKey' => 'user_id',
'conditions' => array('Comment.status' => '1'),
'order' => 'Comment.created DESC',
'limit' => '5',
'dependent'=> true
)
);
}
?>
I am starting with cakePHP too and banged my head for some time before I realized that the "conventions" require the Model filename to be CamelCased.
Try using:
Post.php
User.php
otherwise it seems the models are totally ignored.
I have the model AccountLicense, when I execute the method getExpiringLicenes for some reason the association I have with the parent model (AccountUser) the primary key of AccountUser is not being used, it is instead using the default primary key 'id'. I am not sure why this is happening. This is all part of a plugin.
Any help with this is greatly appreciated.
This is the exception I am getting:
Warning (512): SQL Error: 1054: Unknown column 'AccountUser.id' in 'on clause' [CORE/cake/libs/model/datasources/dbo_source.php, line 684]
This is the query that is being executed:
SELECT `AccountLicense`.`license_id`, `AccountLicense`.`user_id`,
`AccountLicense`.`board_id`, `AccountLicense`.`license_number`,
`AccountLicense`.`license_state`, `AccountLicense`.`license_designation_id`,
`AccountLicense`.`active_date`, `AccountLicense`.`expire_date`,
`AccountLicense`.`is_active`, `AccountLicense`.`is_confirmed`,
`AccountLicense`.`is_primary`, `AccountUser`.`user_id`, `AccountUser`.`user_name`,
`AccountUser`.`user_pass`, `AccountUser`.`user_status`, `AccountUser`.`user_group`,
`AccountUser`.`instance_id`, `AccountUser`.`is_logged_in`, `AccountUser`.`is_visible`,
`AccountUser`.`created_by`, `AccountUser`.`last_modified_by`,
`AccountUser`.`created_date`, `AccountUser`.`last_modified_date`
FROM `account_licenses` AS `AccountLicense`
LEFT JOIN `account_users` AS `AccountUser`
ON (`AccountLicense`.`user_id` = `AccountUser`.`id`)
WHERE `AccountLicense`.`expire_date` BETWEEN '2011-10-05' and '2011-11-04'
This is my AccountLicenses model:
<?php
class AccountLicense extends AppModel {
var $name = 'AccountLicense';
var $primaryKey = 'license_id';
var $plugin = 'AccountModule';
var $belongsTo = array(
'AccountUser' => array(
'className' => 'AccountUser',
'foreignKey' => 'user_id'
)
);
public function getExpiringLicenses($date = null)
{
if(is_null($date))
$date = date('Y-m-d',strtotime("+30 days"));
return $this->find(
'all',
array(
'conditions' => array(
$this->name . '.expire_date BETWEEN ? and ?' =>array(date('Y-m-d'),$date)
)
)
);
}
}
?>
This is my AccountUser model:
<?php
class AccountUser extends AppModel {
var $name = 'AccountUser';
var $primaryKey = 'user_id';
var $actsAs = array('Containable');
var $validate = array(
'user_name'=>array(
'rule'=>'isUnique',
'message'=>'This username has already been taken. Please try again'
),
'user_pass' => array(
'rule' => array('between', 8, 16),
'message' => 'Passwords must be between 8 and 16 characters long.')
);
var $hasMany = array(
'AccountLicense' => array(
'className' => 'AccountLicense',
'foreignKey' => 'user_id'
)
);
?>
Since is a plugin your association should have the plugin name
Example:
If your plugin name is AccountModule your association should look like
var $belongsTo = array(
'AccountUser' => array(
'className' => 'AccountModule.AccountUser',
'foreignKey' => 'user_id'
)
);
Also is not wrong, but the correct way to declare a model class inside a plugin is
<?php
class AccountLicense extends AccountModuleAppModel {
If it is in the correct place in your folder structure and correctly declared you won't need this line
var $plugin = 'AccountModule';