So I am using cakephp and I am a little new to this and I am facing certain issues.
1) I have two tables, report and issues.
cakephp:
report{id, type, details}
issue{id,report_id, details}
So now I am trying to get the report id in issues table. I have defined my hasmany and belongsto relationships as follows:
class Report extends AppModel {
var $name = 'Report';
var $hasMany = array(
'AtneIssue' => array(
'className' => 'Issue',
'foreignKey' => 'report_id',
'dependent' => true,
)
);
}
class Issue extends AppModel {
var $name = 'Issue';
var $belongsTo = array(
'Report' => array(
'className' => 'Report',
'foreignKey' => 'report_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
But this results in a sql error and the data not being saved to the table. I have set index to report_id to get id from Report.
Data is getting saved to reports but not to issues table.
Can someone tell me how to go about this?
Thanks in advance.
The first letter is replace by number here. dunno why... I figured how to post data But now I am not able to get the ID of the report and the data is getting corrupted like below:
Query: INSERT INTO `atne_issues` (`status`, `issue_owner`, `issue_reason`, `problem`) VALUES ('2nhold', '2ricsson', '2IQ - IP address incorrect', '2sdfasdf')
Related
I need to join a model to itself... but I get the error "Not unique table/alias: 'Image'"
Image Schema:
id: int
thumbnail_image_id: int null
key: varchar... filename
location: varchar... s3 or local
created: datetime
modified: datetime
Image Model:
<?php
App::uses('AppModel', 'Model');
class Image extends AppModel {
public $belongsTo = array(
'Thumbnail' => array(
'className' => 'Image',
'foreignKey' => 'thumbnail_image_id'
)
);
public $hasOne = array(
'Thumbnail' => array(
'className' => 'Image',
'foreignKey' => 'thumbnail_image_id'
)
);
public function exampleFunction() {
return $this->find('all', array(
'contain' => array('Thumbnail')
));
}
Running exampleFunction it gives me the error "Not unique table/alias: 'Image'". CakePHP builds the SQL like this:
SELECT `Image`.`id`, `Thumbnail`.`id` FROM `images` AS `Image` LEFT JOIN `images` AS `Image`.`thumbnail_image_id` = `Thumbnail`.`id`;
but it should be something like this... right? (notice the inverted ON):
SELECT `Image`.`id`, `Thumbnail`.`id` FROM `images` AS `Image` LEFT JOIN `images` AS `Thumbnail`.`id` = `Image`.`thumbnail_image_id`;
If I run both SQL queries above in mysql console the second works.
Suggestions?
The problem is that you have used Thumbnail in both $belongsTo and $hasOne.
The Model will have no idea which association to use for the 'contain'.
Rename or remove one of your associations so they are unique.
I'm working on a small app to help learn cakephp 2.0. Its a simple task manager app.
Tables
users
tasks
tasktypes
I've a set up a foreign key in the tasks table called 'user_id'
As a task belongs to a user.
Now all I'm trying to do is display the tasks of a certain user and it wont work at all despite the sql query getting correct results when I tested it any help would be great.
In my taskscontroller I've the method;
//show the tasks of the current user
public function mytasks(){
$this->set('title_for_layout', 'Gerrys TaskManager: Display Tasks');
$this->Task->recursive = 0;
$tasks=$this->Task->find('all', array('conditions'=>array('username'=>'admin')));
$this->set('tasks', $this->paginate());
}
I'm trying to find the tasks of the user 'admin' or the "realted tasks" what am I doing wrong?
I suspect the problem maybe to with my models;
usermodel
/**
* hasMany associations
*
* #var array
*/
public $hasMany = array(
'Task' => array(
'className' => 'Task',
'foreignKey' => 'user_id'
)
);
task model;
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Tasktype' => array(
'className' => 'Tasktype',
'foreignKey' => 'tasktype_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
To get the tasks that belong to a user, it's much simpler to do that in the UsersController. Of course you have to set User hasMany Task in your UserModel.
Now you can create a function, for example to view the User and it's Tasks by id:
public function view($id = null) {
$this->User->id = $id;
$this->set('user', $this->User->read(null, $id));
}
The Tasks should now be available in your view by $user['tasks']. You have to pass the id in the url like: /path_to_your_app/users/view/1
You can always use debug() to see contents of an array or variable. To see what you've got add <?php debug($user);?> to your view.
You most likely want to list any tasks with a foreach in your view, very simple example::
foreach($user['Task'] as $task) {
echo $task['field1'] . ": " . $task['fied2'];
echo "<br />";
}
of course you might want to display the tasks in tables or something.
A good starting point for learning cakePHP is the Blog-Tutorial:
http://book.cakephp.org/2.0/en/getting-started.html#blog-tutorial
I have SubjectGroup, which hasMany Subject.
class SubjectGroup extends AppModel {
public $hasMany = array(
'Subject' => array('order' => 'Subject.name')
);
}
class Subject extends AppModel {
public $belongsTo = array('SubjectGroup');
}
I want to get all SubjectGroups, and recursively retrieve their Subjects, but only the Subjects that have a status of 2. I can't figure out how to do this.
$subjectGroups = $this->SubjectGroup->find('all', array(
'conditions' => array('Subject.status !=' => 2),
'order' => 'SubjectGroup.name'
));
Warning (512): SQL Error: 1054: Unknown column 'Subject.status' in 'where clause'
Note: I have read that I can add a conditions array to the model relationship definition, but I don't want the relationship to always use the condition. Sometimes I will want to just retrieve the SubjectGroups and Subjects with status 2, and sometimes the SubjectGroups with all Subjects, regardless of their status.
PROGRESS
With some help from Ross, I now am trying to use the Containable behaviour. I have this so far:
$this->SubjectGroup->find('all', array(
'contain' => 'Subject.status != 2',
'order' => 'SubjectGroup.name'
));
There are no errors, but it returns all Subjects, even the ones with status = 2.
What you're doing is asking Cake to look for the field status in the SubjectGroup table. It doesn't exist.
What you really want to do is use containable behaviour, and access the status field this way.
Try this:
$this->SubjectGroup->Behaviors->attach('Containable');
$subjectGroups = $this->SubjectGroup->find('all', array(
'contain'=>array('Subject'=>array(
'conditions' => array('Subject.status !=' => 2))
),
'order' => 'SubjectGroup.name'
));
I want the join table to be updated/deleted automatically. I'm doing a deleteAll() prior to saveAll() as a workaround to do this.
When I submit the form, the Layout and Component models updates correctly but the Layout Component model (which is the join table) inserts new data (which is what I want) but does not delete the referenced data.
Layout Model:
class Layout extends AppModel {
var $name = 'Layout';
var $hasMany = array(
'LayoutComponentOrder' => array(
'className' => 'LayoutComponentOrder',
'foreignKey' => 'layout_id',
'dependent' => false,
'order' => 'LayoutComponentOrder.sort_id ASC',
),
'ComponentVideo' => array(
'className' => 'ComponentVideo',
'foreignKey' => 'layout_id',
'dependent' => false,
),
);}
Component Model:
class ComponentVideo extends AppModel {
var $name = 'ComponentVideo';
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $hasMany = array(
'LayoutComponentOrder' => array(
'className' => 'LayoutComponentOrder',
'foreignKey' => 'layout_component_id',
'dependent' => false,
),
);
var $belongsTo = array(
'Layout' => array(
'className' => 'Layout',
'foreignKey' => 'layout_id'
),
);
};
Layout Component Model (join table):
class LayoutComponentOrder extends AppModel {
var $name = 'LayoutComponentOrder';
var $uses = 'layout_component_orders';
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Layout' => array(
'className' => 'Layout',
'foreignKey' => 'layout_id'
),
'ComponentVideo' => array(
'className' => 'ComponentVideo',
'foreignKey' => 'layout_component_id'
)
);
}
Layout Controller:
// deleting the data manually
$this->LayoutComponentOrder->deleteAll(array('LayoutComponentOrder.layout_id' => $layout_id));
// this one inserts into the tables including the join table
$this->Layout->id = $layout_id;
if ($this->Layout->saveAll($this->data)) {
$this->Session->setFlash(__('The layout has been saved', true));
}
How can I have the join be deleted automatically? Is this possible with CakePHP?
Unfortunately, this is not built into CakePHP's saveAll for hasMany relationships. I wish it was, as I found this page searching for a solution to the same thing.
It does seem to be built in with HABTM relationships, though.
See Is there a way to make saveAll() remove extraneous objects? and Shouldn't saveAll remove associated records as well?).
You'll have to implement your own solution (My quick solution running a deleteAll before the saveAll if the form validates. This is not ideal though, because if there is an error not-related to form validation you lose the existing associated items).
Maybe I don't understand the question, but are we talking about removing joins when a parent record is removed from Cake? It does do that, if configured in the model relationships using the 'dependent' parameter:
dependent: When the dependent key is set to true, and the model’s
delete() method is called with the cascade parameter set to true,
associated model records are also deleted. In this case, we set it
true so that deleting a User will also delete her associated Profile.
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
Is that what you're looking for?
please help me, i'm really struggling with this...
Authors can write post, and authors can love other authors' posts...
So posts belong to author (when authors write them), but posts habtm
authors (when authors love them).
For example i'd like to get posts ordered by number of postlovers and
created in the last 24 hours. Here's my models and join table:
TABLE: lovedposts_postlovers
id: INT
lovedpost_id: INT
postlover_id: INT
POST MODEL
<?php
class Post extends AppModel {
var $name = 'Post';
var $belongsTo = 'Author';
var $hasAndBelongsToMany = array(
'Postlover' =>
array(
'className' => 'Author',
'joinTable' => 'lovedposts_postlovers',
'foreignKey' => 'lovedpost_id',
'associationForeignKey' => 'postlover_id',
'unique' => true
)
);
var $displayField = 'title';
}
?>
AUTHOR MODEL
<?php
class Author extends AppModel {
var $name = 'Author';
var $hasMany = 'Post';
var $hasAndBelongsToMany = array(
'Lovedpost' =>
array(
'className' => 'Post',
'joinTable' => 'lovedposts_postlovers',
'foreignKey' => 'postlover_id',
'associationForeignKey' => 'lovedpost_id',
'unique' => true
)
);
var $displayField = 'username';
}
?>
Your best option is to query on the joinModel. Usually that would be:
$this->Author->AuthorsLovedpost->find(...);
But since you're not sticking to the Cake naming conventions for the table that may or may not be different. The joinModel is automatically created BTW, but you can also explicitly specify it in the HABTM declaration.
var $hasAndBelongsToMany = array(
'Postlover' => array(
...,
'with' => 'joinModelName'
)
);
For the find options you can do whatever you need, 'group' => 'post_id' and 'order' => 'COUNT(post_id)' or something to that extend. What you're looking for is getting the right set of 'post_ids' back.
Since from the point of view of the joinModel the Author and Post models are both belongsTo relationships, Cake will find related results accordingly and you can use the usual 'contain' options etc to filter results.
Hope that helps.
I think you should take a step back and try to read the documentation (book.cakephp.org). Try to make a demo using their examples.
lovedposts_postlovers table is very confusing and maybe should be called something else, maybe authors_posts or even favorites. well, it can be anything as long as you specify it in 'joinTable'.
lovedposts_postlovers should have the fields author_id, post_id
//POST MODEL
var $hasAndBelongsToMany = array(
'Author' =>
array(
'className' => 'Author',
'joinTable' => 'lovedposts_postlovers',
'foreignKey' => 'author_id',
'associationForeignKey' => 'post_id',
'unique' => true
)
);
For example i'd like to get posts ordered by number of postlovers and created in the last 24 hours. Here's my models and join table:
$this->Post->LovedPosts->find('all', array('fields'=>array('Post.title', 'count(LovedPosts.*) as favorited'), 'group'=>'LovedPosts.post_id');
Basically you want to do a select count query and group by the post_id and this code should get you on the right track. Note: I didn't test this code. You also need an order clause in that find operation but I will leave that to you.