I am building a CakePHP 2.3 application, and can't for the life of me figure out why saveAll keeps failing.
I have the following models:
Artist hasMany ArtistPreview
ArtistPreview belongsTo Artist
I have no problem saving my Artist model with the save() function, however as soon as I try to use the saveAll method, Cake seems to fail validation - which is crazy because I have even totally removed all my validation rules from my models.
Here's my view, nothing crazy:
<?php
echo $this->Form->create('Artist', array('inputDefaults' => array('class' => 'input-block-level')));
echo $this->Form->input('Artist.name', array('label' => __('Name')));
echo $this->Form->input('Artist.artist_section_id', array('label' => __('Section'), 'empty' => true));
?>
<label>Tags</label>
<div class="checkboxes">
<?php echo $this->Form->input('Tag', array('label' => false, 'multiple' => 'checkbox', 'class' => false));; ?>
</div>
<?php
echo $this->Form->input('Artist.website', array('label' => __('Website')));
echo $this->Form->input('ArtistPreview.0.url', array('label' => __('Artist Preview')));
echo $this->Form->input('Artist.description', array('label' => __('Description')));
?>
<?php
echo $this->Form->submit(__('Add'), array('class' => 'btn btn-primary btn-large', 'div' => false)) . ' ';
echo $this->Form->button(__('Cancel'), array('type' => 'button', 'class' => 'btn btn-large', 'div' => false, 'onclick' => 'closeDialog()'));
echo $this->Form->end();
?>
And here's my add controller method:
public function add() {
$this->layout = 'form';
if (!$this->request->is('ajax')) {
throw new ForbiddenException();
}
if ($this->request->is('post')) {
$this->setData($this->request->data['Artist'], array(
'user_id' => AuthComponent::user('id'),
'date' => $this->Date->gmt()
));
if ($this->Artist->saveAll($this->request->data)) {
$this->redirectAjax('/artists/view/' . $this->Artist->id);
}
}
$this->set(array(
'title_for_layout' => 'Add Artist',
'artistSections' => $this->Artist->ArtistSection->find('list', array('order' => 'name')),
'tags' => $this->Artist->Tag->find('list', array('order' => 'name'))
));
}
As I mentioned above, the saveAll method fails everytime. I have inspected what is getting output and Cake is outputting a bunch of blank <div>s with the error-message class, but there is no message. Every field on the form gets one of these divs.
Now, when I change my code to use the save function instead of saveAll, everything gets saved properly except the ArtistPreview data, which is to be expected. Even my HABTM Tags are being saved properly, and nothing fails validation.
I have been using Cake since the 1.3 days so I'm quite familiar with it, and have even done exactly what I'm asking in previous projects. I'm leaning towards this being a bug, unless I'm missing something here. Any ideas?
EDIT
I have also tried the saveAssociated method, along with setting the deep key to true when trying to save. This will let me save the artist, but it will not save the related data (ArtistPreview).
EDIT 2
As requested, here are the two tables:
-- -----------------------------------------------------
-- Table `artists`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `artists` ;
CREATE TABLE IF NOT EXISTS `artists` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`user_id` INT UNSIGNED NULL ,
`artist_section_id` INT UNSIGNED NULL ,
`artist_status_id` INT UNSIGNED NULL ,
`name` VARCHAR(200) NULL ,
`website` VARCHAR(500) NULL ,
`description` TEXT NULL ,
`date` DATETIME NULL ,
`comment_count` INT UNSIGNED NOT NULL DEFAULT 0 ,
PRIMARY KEY (`id`) ,
INDEX `FK_artists_users_idx` (`user_id` ASC) ,
INDEX `FK_artists__artist_sections_idx` (`artist_section_id` ASC) ,
INDEX `FK_artists__artist_statuses_idx` (`artist_status_id` ASC) ,
CONSTRAINT `FK_artists__users`
FOREIGN KEY (`user_id` )
REFERENCES `users` (`id` )
ON DELETE SET NULL
ON UPDATE CASCADE,
CONSTRAINT `FK_artists__artist_sections`
FOREIGN KEY (`artist_section_id` )
REFERENCES `artist_sections` (`id` )
ON DELETE SET NULL
ON UPDATE CASCADE,
CONSTRAINT `FK_artists__artist_statuses`
FOREIGN KEY (`artist_status_id` )
REFERENCES `artist_statuses` (`id` )
ON DELETE SET NULL
ON UPDATE CASCADE)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `artist_previews`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `artist_previews` ;
CREATE TABLE IF NOT EXISTS `artist_previews` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`artist_id` INT UNSIGNED NULL ,
`url` VARCHAR(500) NULL ,
`date` DATETIME NULL ,
PRIMARY KEY (`id`) ,
INDEX `FK_artist_previews__artists_idx` (`artist_id` ASC) ,
CONSTRAINT `FK_artist_previews__artists`
FOREIGN KEY (`artist_id` )
REFERENCES `artists` (`id` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
Here is my setData function, which just merges two arrays. Instead of using hidden fields, I set fields in the controller which aren't populated by user input:
public function setData(&$original, $new) {
$original = array_merge($original, $new);
}
So I finally figured this out, and wow was it a rookie mistake. I think I must've been half asleep yesterday when I was coding. The problem was in my model:
class Artist extends AppModel {
public $belongsTo = array(
'User',
'ArtistSection',
'ArtistStatus'
);
public $hasMany = array(
'ArtistPicture',
'Artist' // <--- problem was here, had 'Artist' instead of 'ArtistPreview'
);
public $hasAndBelongsToMany = array(
'Tag'
);
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->validate = array(
'name' => array(
'rule' => 'notEmpty',
'message' => __('Artist name cannot be blank.')
),
'website' => array(
'rule' => 'url',
'message' => __('Must be a valid URL.'),
'allowEmpty' => true
),
'artist_section_id' => array(
'rule' => 'notEmpty',
'message' => __('Section is required.')
)
);
}
}
Thank you to those of you who took the time to look at this question, even though I posted the wrong information.
Related
I set up more than one models, which i want to associate with a master-model like this:
class CommonType extends AppModel {
public $useDbConfig = 'common';
public $hasOne = array(
'CommonTypeDescription' => array(
'className' => 'CommonTypeDescription',
'foreignKey' => 'type_description_id',
'dependent' => true
),
'CommonTypeExperience' => array(
'className' => 'CommonTypeExperience',
'foreignKey' => 'type_expirience_id',
'dependent' => true
),
'CommonTypeProperty' => array(
'className' => 'CommonTypeProperty',
'foreignKey' => 'type_property_id',
'dependent' => true
),
);
public $belongsTo = array(
'CommonTypeCategory' => array(
'className' => 'CommonTypeCategory',
'foreignKey' => 'common_type_id',
));
}
In Heidi SQL (for example) i set the foreignkeys for the tables type_experiences, type_properties and type_descriptions as above, so that foreignkeys in my code and in my tables have the same name.
But now, i don't want to name the primary key as the foreign key, the primary key of the (e.g.) type_descriptions table should named "id". This is the model of type_description:
class CommonTypeDescription extends AppModel {
public $name = 'CommonTypeDescription';
public $useDbConfig = 'common';
public $useTable = 'type_descriptions';
public $primaryKey = 'id';
}
and here is the database creation code:
CREATE TABLE `type_descriptions` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`common_type_id` INT(11) NULL DEFAULT NULL,
`short_description` VARCHAR(50) NULL DEFAULT NULL,
`long_description` VARCHAR(50) NULL DEFAULT NULL,
`notes` VARCHAR(50) NULL DEFAULT NULL,
`modified` DATETIME NULL DEFAULT NULL,
`created` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `type_description_id` FOREIGN KEY (`common_type_id`) REFERENCES `common_types` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION) ...
But when i try to get the data from my model CommonType ($this->find('all')) i get an error like "Unknown column 'CommonTypeDescription.type_description_id' in 'on clause'"
First, i thought that i have to declare the primary key of the description model as "id", but it seams, that the foreign key definition overwrites the naming convention from cake of the primary key from the associated model.
Many thanks for your help & Greetings,
Guido
ps. i've changed the Model-Names of this post (if there is a type-mistake). So when i rename the primary keys of the associated tables, it all works fine, but i want them to name only to "id".
How about update your CommonType Model to this:
'CommonTypeDescription' => array(
'className' => 'CommonTypeDescription',
'foreignKey' => 'common_type_id', //or try type_description_id if there's an error
'dependent' => true
)
Then on your CommonTypeDescription model add this relationship, I think you forgot adding belongs to relationship to CommonType Model:
public $belongsTo = array(
'CommonType' => array(
'className' => 'CommonType ',
'foreignKey' => 'common_type_id',
));
I have the following tables: causes, users, transactions
Cause hasMany Transaction and User hasMany Transaction
Transaction belongsTo Cause and Transaction belongsTo User
Both my causes and users tables have transaction_count fields and my belongsTo has counterCache => true on both associations.
Both of my hasMany clauses have dependent => true and my foreignKeys are set up correctly in that if I delete a Cause, all of it's associated Transactions are deleted as well.
It is also working, in that when I create a Transaction, the transaction_count field in both my users and causes tables updates correctly. Here is the breakdown:
1.) Create a cause
2.) Create a transaction
RESULT: causes[ 15 ][ 'transaction_count' ] increases by 1 correctly
RESULT: users[ 1 ][ 'transaction_count' ] increases by 1 correctly
3.) Manually delete a transaction ( $transaction->delete( $id ) )
RESULT: causes[ 15 ][ 'transaction_count' ] decreases by 1 correctly
RESULT: users[ 1 ][ 'transaction_count' ] decreases by 1 correctly
4.) FAILURE:
If I create the Cause and Transaction and then delete the Cause using $this->Cause->delete( $id ), even though all of the transactions are deleted in the database (along with the Cause), the transaction_count in my users table is not updated to reflect the decrease.
I imagine this is because $this->Transaction->delete() is not getting called explicitly, but it is instead getting deleted due to its association with Cause?
Is there a workaround for this?
Tables
CREATE TABLE `causes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`transaction_count` int(10) unsigned NOT NULL DEFAULT '0'
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `transactions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cause_id` int(10) unsigned NOT NULL DEFAULT '0',
`user_id` int(10) unsigned NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`transaction_count` int(10) unsigned NOT NULL DEFAULT '0'
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
User.php
App::uses('AppModel', 'Model');
class User extends AppModel {
public $hasMany = array(
'Transaction' => array(
'dependent' => true
)
);
}
Cause.php
App::uses('AppModel', 'Model');
class Cause extends AppModel {
public $hasMany = array(
'Transaction' => array(
'dependent' => true
)
);
}
Transaction.php
App::uses('AppModel', 'Model');
class Transaction extends AppModel {
public $belongsTo = array(
'User' => array(
'counterCache' => true
),
'Cause' => array(
'counterCache' => true
)
);
}
Controller
$this->Cause->query('TRUNCATE TABLE users');
$user['User'] = array(
'name' => 'aaa'
);
$this->Cause->Transaction->User->create($user);
$this->Cause->Transaction->User->save(null, false);
$userId = $this->Cause->Transaction->User->getLastInsertID();
$this->Cause->query('TRUNCATE TABLE causes');
$cause['Cause'] = array(
'name' => 'aaa'
);
$this->Cause->create($cause);
$this->Cause->save(null, false);
$causeId = $this->Cause->getLastInsertID();
$this->Cause->query('TRUNCATE TABLE transactions');
$transaction['Transaction'] = array(
'name' => 'aaa',
'user_id' => $userId,
'cause_id' => $causeId
);
$this->Cause->Transaction->create($transaction);
$this->Cause->Transaction->save(null, false);
$this->Cause->Transaction->create($transaction);
$this->Cause->Transaction->save(null, false);
$transaction['Transaction'] = array(
'name' => 'aaa',
'user_id' => $userId,
'cause_id' => 99
);
$this->Cause->Transaction->create($transaction);
$this->Cause->Transaction->save(null, false);
$this->Cause->delete($causeId);
$cause = $this->Cause->find('first', array(
'conditions' => array(
'Cause.id' => $causeId
)
));
$transactions = $this->Cause->Transaction->find('all', array(
'conditions' => array(
'Transaction.cause_id' => $causeId
)
));
$user = $this->Cause->Transaction->User->find('first', array(
'conditions' => array(
'User.id' => $userId
)
));
pr($cause);
pr($transactions);
pr($user);
if (is_a($this->Cause, 'Cause')) {
echo 'Cause';
}
if (is_a($this->Cause->Transaction, 'Transaction')) {
echo 'Transaction';
}
if (is_a($this->Cause->Transaction->User, 'User')) {
echo 'User';
}
Result
Array
(
)
Array
(
)
Array
(
[User] => Array
(
[id] => 1
[name] => aaa
[transaction_count] => 1
)
)
CauseTransactionUser
It works ok.
Double check for typos in models and check if cake is using your models and not the ones that are created on the fly if some model is missing.
I read the CakePHP book but couldn't make it.
I have a table named frendslists. Every user (owner_user_id) has too many friends and I add the friends to friend_id column. (Model name is Friendslist)
CREATE TABLE IF NOT EXISTS `friendslists` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`owner_user_id` int(20) unsigned NOT NULL,
`friend_id` int(20) NOT NULL COMMENT 'id of the friend',
PRIMARY KEY (`id`),
KEY `friend_id` (`friend_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--id-------owner_user_id-----friend_id
--------------------------------------
--1--------1234--------------9200-----
--2--------1234--------------3210-----
--3--------1234--------------7600-----
I also have a profiles table. Every unique person have a profile there. One person can have only one profile. (Model name is Profile)
CREATE TABLE IF NOT EXISTS `profiles` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`profile_user_id` int(20) NOT NULL,
`name` varchar(50) NOT NULL,
`location` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
KEY `profile_user_id` (`profile_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--id------profile_user_id---name------location-
-----------------------------------------------
--1-------9200--------------michael----usa-----
--2-------3210--------------john-------uk------
--3-------7600--------------danny------denmark-
I want to link friendslists table to profiles table. Is this one to one (hasOne) or many to one (belongsTo) type relationship ?
When I query friendslists table I want to get profiles data of the friends. What should I do inside CakePHP models and tables?
I created a foreign key like this:
ALTER TABLE `friendslists`
ADD CONSTRAINT `friendslists_ibfk_1`
FOREIGN KEY (`friend_id`)
REFERENCES `profiles` (`profile_user_id`)
ON DELETE CASCADE ON UPDATE CASCADE;
I changed model file to this:
class Friendslist extends AppModel {
var $name = 'Friendslist';
var $useTable = 'friendslists';
public $belongsTo = array(
'Profile' => array(
'className' => 'Profile',
'foreignKey' => 'friend_id'
)
)
function getAll(){
return $this->find('all');
}
}
At last when I do this:
$records=$this->Friendslist->find('all', array('conditions' => array(
'Friendslist.owner_user_id' => 1234)
));
I get these result:
[Friendslist] => Array
(
[id] => 1
[owner_user_id] => 1234
[friend_id] => 9200
)
[Profile] => Array
(
[id] =>
[profile_user_id] =>
[name] =>
[location] =>
)
)
I'm sure that profiles table has a record with profile_user_id=9200. But Profile records comes empty.
I'm a little confused why you're linking friendslists to profiles. Wouldn't it make more sense to link people with people and then get the profile therefrom?
In any case, what you're describing is a HasAndBelongsToMany(HABTM)
So in your Person model you want to specify that they have many other people (or in your case Profiles) that they're associated with and specify the lookup table.
Something like...
public $hasAndBelongsToMany = array(
'Person' => array(
'className' => 'Profile',
'joinTable' => 'friendslists',
'foreignKey' => 'owner_id',
'associationForeignKey' => 'friend_id'
)
);
And then within the friendslists model I'd describe it as a belongsTo listing both the owner and the profile.
Something like:
public $belongsTo = array(
'Person' => array(
'className' => 'Person'
,'foreignKey' => 'owner_user_id'
),
'Profile' => array(
'className' => 'Profile'
,'foreignKey' => 'friend_id'
)
);
You may need to tweak the names as I had a hard time digesting exactly what entities are at play, but that should give you an idea at least.
New to Cake, and trying to set up model associations. I'm creating an execution planner, to be used by multiple teams, aka 'groups' where the base unit of a plan is an 'event'. Each event is owned by one team, but it can have many supporting teams.
When I use $scaffold in the controllers, the model associations work as expected and when adding a new event I get a select box with all the groups to select who owns an event. However, when I bake the controller using console, the select box for group_id is blank. I've included the baked add() code from the controller, and from the baked add view. I also tried debug($this) in add.ctp, and found that the list of groups is indeed being passed to the view. I'm thus mostly confused about why it works with $scaffold, but not otherwise.
Any advice or pointers in the right direction would be greatly appreciated.
Tables:
CREATE TABLE IF NOT EXISTS `events` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`group_id` int(5) NOT NULL COMMENT 'Group that owns event',
`version` int(5) NOT NULL,
`type` varchar(5) NOT NULL,
`stime` time NOT NULL,
`etime` time NOT NULL,
`description` text NOT NULL,
`comment` text NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `events_groups` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`event_id` int(5) NOT NULL,
`group_id` int(5) NOT NULL,
PRIMARY KEY (`id`)
) ;
CREATE TABLE IF NOT EXISTS `groups` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`code` varchar(4) NOT NULL,
`name` varchar(25) NOT NULL,
`liveversion` int(4) NOT NULL,
`lastupdated` date NOT NULL,
PRIMARY KEY (`id`)
);
Models:
Event:
public $belongsTo = array(
'Prigroup' => array(
'className' => 'Group',
'foreignKey' => 'group_id',
)
);
public $hasAndBelongsToMany = array(
'Secgroup' => array(
'className' => 'Group',
'joinTable' => 'events_groups',
'foreignKey' => 'event_id',
'associationForeignKey' => 'group_id',
)
);
Group:
public $hasMany = array(
'Prievent' => array(
'className' => 'Event',
'foreignKey' => 'group_id',
)
);
public $hasAndBelongsToMany = array(
'Secevent' => array(
'className' => 'Event',
'joinTable' => 'events_groups',
'foreignKey' => 'group_id',
'associationForeignKey' => 'event_id',
)
);
EventsController Snippet:
public function add() {
if ($this->request->is('post')) {
$this->Event->create();
if ($this->Event->save($this->request->data)) {
$this->Session->setFlash(__('The event has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The event could not be saved. Please, try again.'));
}
}
$prigroups = $this->Event->Prigroup->find('list');
$secgroups = $this->Event->Secgroup->find('list');
$this->set(compact('prigroups', 'secgroups'));
}
Add view:
<?php echo $this->Form->create('Event'); ?>
<fieldset>
<legend><?php echo __('Add Event'); ?></legend>
<?php
echo $this->Form->input('group_id');
echo $this->Form->input('version');
echo $this->Form->input('type');
echo $this->Form->input('stime');
echo $this->Form->input('etime');
echo $this->Form->input('description');
echo $this->Form->input('comment');
echo $this->Form->input('Secgroup');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
Add HTML Output
<div class="input select"><label for="EventGroupId">Group</label><select name="data[Event][group_id]" id="EventGroupId">
</select></div>
Can u try something for me please? Rename the $prigroups variable to "groups" and pass it to the view. See if this is working. Otherwise use this one with your old code:
echo $this->Form->input(
'group_id',
array(
'options' => $prigroups
)
);
I also recommend you to use camel case for all those PriGroups and SecGroups. Those are two words in english so camel case advisable.
Greetings
func0der
I have 3 models, Page , Course and Content
Page and Course contain meta data and Content contains HTML content.
Page and Course both hasMany Content
Content belongsTo Page and Course
To avoid having page_id and course_id fields in Content (because I want this to scale to more than just 2 models) I am looking at using Polymorphic Associations. I started by using the Polymorphic Behavior in the Bakery but it is generating waaay too many SQL queries for my liking and it's also throwing an "Illegal Offset" error which I don't know how to fix (it was written in 2008 and nobody seems to have referred to it recently so perhaps the error is due to it not having been designed for Cake 2?)
Anyway, I've found that I can almost do everything I need by hardcoding the associations in the models as such:
Page Model
CREATE TABLE `pages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`)
)
<?php
class Page extends AppModel {
var $name = 'Page';
var $hasMany = array(
'Content' => array(
'className' => 'Content',
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Page'),
)
);
}
?>
Course Model
CREATE TABLE `courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`)
)
<?php
class Course extends AppModel {
var $name = 'Course';
var $hasMany = array(
'Content' => array(
'className' => 'Content',
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Course'),
)
);
}
?>
Content model
CREATE TABLE IF NOT EXISTS `contents` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`class` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`foreign_id` int(11) unsigned NOT NULL,
`title` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`content` text COLLATE utf8_unicode_ci NOT NULL,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
)
<?php
class Content extends AppModel {
var $name = 'Content';
var $belongsTo = array(
'Page' => array(
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Page')
),
'Course' => array(
'foreignKey' => 'foreign_id',
'conditions' => array('Content.class' => 'Course')
)
);
}
?>
The good thing is that $this->Content->find('first') only generates a single SQL query instead of 3 (as was the case with the Polymorphic Behavior) but the problem is that the dataset returned includes both of the belongsTo models, whereas it should only really return the one that exists. Here's how the returned data looks:
array(
'Content' => array(
'id' => '1',
'class' => 'Course',
'foreign_id' => '1',
'title' => 'something about this course',
'content' => 'The content here',
'created' => null,
'modified' => null
),
'Page' => array(
'id' => null,
'title' => null,
'slug' => null,
'created' => null,
'updated' => null
),
'Course' => array(
'id' => '1',
'title' => 'Course name',
'slug' => 'name-of-the-course',
'created' => '2012-10-11 00:00:00',
'updated' => '2012-10-11 00:00:00'
)
)
I only want it to return one of either Page or Course depending on which one is specified in Content.class
UPDATE: Combining the Page and Course models would seem like the obvious solution to this problem but the schemas I have shown above are just shown for the purpose of this question. The actual schemas are actually very different in terms of their fields and the each have a different number of associations with other models too.
UPDATE 2
Here is the query that results from running $this->Content->find('first'); :
SELECT `Content`.`id`, `Content`.`class`, `Content`.`foreign_id`, `Content`.`title`,
`Content`.`slug`, `Content`.`content`, `Content`.`created`, `Content`.`modified`,
`Page`.`id`, `Page`.`title`, `Page`.`slug`, `Page`.`created`, `Page`.`updated`,
`Course`.`id`, `Course`.`title`, `Course`.`slug`, `Course`.`created`,
`Course`.`updated` FROM `cakedb`.`contents` AS `Content`
LEFT JOIN `cakedb`.`pages` AS `Page` ON
(`Content`.`foreign_id` = `Page`.`id` AND `Content`.`class` = 'Page')
LEFT JOIN `cakedb`.`courses` AS `Course` ON (`Content`.`foreign_id` = `Course`.`id`
AND `Content`.`class` = 'Course') WHERE 1 = 1 LIMIT 1
Your query is okay. Just filter empty values after find:
public function afterFind($results, $primary = false) {
return Set::filter($results, true);
}
Take a look at this question.
You can also try to provide conditions to you find query that Page.id in not null or Course.id is not null.