Cakephp HABTM join table empty - cakephp

I'm following a tutorial for an application where users may upload files and files belong to a particular user. There's a HABTM relationship between Users and Uploads as follows:
Upload.php:
var $hasAndBelongsToMany = array(
'SharedUser' => array(
'className' => 'User',
'joinTable' => 'uploads_users',
'foreignKey' => 'upload_id',
'associationForeignKey' => 'user_id',
'unique' => 'keepExisting'
)
);
User.php:
var $hasMany = array(
'Upload' => array(
'className' => 'Upload',
'foreignKey' => 'user_id',
'dependent' => false
)
);
var $hasAndBelongsToMany = array(
'SharedUpload' => array(
'className' => 'Upload',
'joinTable' => 'uploads_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'upload_id',
'unique' => true
)
);
All seems to work as it should with one exception, which is that on creating a new Upload the uploads_users table is not updated. If I insert data into it manually then the views which are meant to find and display data using it function. Can anyone suggest what is wrong?
Here's the uploads_users table:
+-----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| upload_id | char(36) | NO | | NULL | |
| user_id | char(36) | NO | | NULL | |
+-----------+----------+------+-----+---------+----------------+
I've altered the add Upload method a little from the tutorial (so it deletes an uploaded file if the database save fails), so here's that as well:
function add() {
if (!empty($this->data)) {
$this->Upload->create();
if ($this->uploadFile()) {
try {
if (!$this->Upload->saveAll($this->request->data)) {
throw new Exception('Couldn't save to database.');
}
$this->Session->setFlash(__('The upload has been saved', true));
$this->redirect(array('action' => 'index'));
}
catch (Exception $e) {
unlink(APP . 'tmp/uploads/' . $this->request->data['Upload']['id']);
$this->Session->setFlash(__('The upload could not be saved: ' . $e->getMessage(), true));
}
} else {
$this->Session->setFlash(__('The upload could not be saved.', true));
}
}
$users = $this->Upload->User->find('list');
$this->set(compact('users', 'users'));
}
function uploadFile() {
$file = $this->data['Upload']['file'];
if ($file['error'] === UPLOAD_ERR_OK) {
$id = String::uuid();
if (move_uploaded_file($file['tmp_name'], APP.'tmp/uploads'.DS.$id)) {
$this->request->data['Upload']['id'] = $id;
$this->request->data['Upload']['user_id'] = $this->Auth->user('id');
$this->request->data['Upload']['filename'] = $file['name'];
$this->request->data['Upload']['filesize'] = $file['size'];
$this->request->data['Upload']['filemime'] = $file['type'];
return true;
}
}
return false;
}

It would be usefull to see what else is in your request->data.
As written in cookbook you should use the related model structure.
It should look the following:
$this->request->data['Upload']['id'] = $id;
$this->request->data['Upload']['user_id'] = $this->Auth->user('id');
...
$this->request->data['SharedUser']['id'] = $this->Auth->user('id');
Also I could not see your belongsTo relation shown in your method "uploadFile". Maybe you don't need it in the "Upload" model.

Related

how to use countercache for different alias in cakephp model?

I have the following models: Attachment and PurchaseOrder hence the datatables attachments and purchase_orders.
In PurchaseOrder, I have
class PurchaseOrder extends AppModel {
public $hasMany = array(
'Pdf' => array(
'className' => 'Attachment',
'foreignKey' => 'foreign_key',
'conditions' => array(
'Pdf.model' => 'PurchaseOrder'
)
),
'Zip' => array(
'className' => 'Attachment',
'foreignKey' => 'foreign_key',
'conditions' => array(
'Zip.model' => 'PurchaseOrder'
)
),
In Attachment, I have the following:
public $belongsTo = array(
'PurchaseOrder' => array(
'className' => 'PurchaseOrder',
'foreignKey' => 'foreign_key',
'counterCache' => array(
'attachment_count' => array('Pdf.model' => 'PurchaseOrder'),
)
),
My problem is when I try to use $this->PurchaseOrder->Zip->save($data); I run into problem because the alias Pdf is not found.
How do I overcome this while maintaining the countercache behavior of updating the attachment_count inside purchase_orders?
Note that if a PurchaseOrder is associated with 3 Pdf Attachments and 2 Zip Attachments, the attachment_count should read 3.
I am using cakephp 2.4.2
I stopped using counterCache and used afterSave instead.
/**
* Called after each successful save operation.
*
* #param boolean $created True if this save created a new record
* #param array $options Options passed from Model::save().
* #return void
* #link http://book.cakephp.org/2.0/en/models/callback-methods.html#aftersave
* #see Model::save()
*/
public function afterSave($created, $options = array()) {
// update the PurchaseOrder based on pdf
if (isset($this->data['Pdf'])) {
$this->updatePurchaseOrderAttachmentCount($this->data);
}
}
/**
*
* #param Array $data where we expect key Pdf
*/
public function updatePurchaseOrderAttachmentCount($data) {
// check for Pdf
$pdfSet = isset($data['Pdf']);
if (!$pdfSet) {
throw new Exception('we expect Pdf as a key in your $data');
}
// check for foreign_key and model
$pdfFKSet = isset($data['Pdf']['foreign_key']);
$pdfModelSet = isset($data['Pdf']['model']);
if (!$pdfFKSet || !$pdfModelSet) {
throw new Exception('we expect foreign_key and model as keys in your $data["Pdf"]');
}
$count = $this->find('count', array(
'conditions' => array(
'model' => 'PurchaseOrder',
'type' => 'application/pdf',
'foreign_key' => $data['Pdf']['foreign_key'],
)
));
if (!is_numeric($count)) {
throw new Exception('we expect numeric in the $count');
}
$poData = array(
'PurchaseOrder' => array(
'id' => $data['Pdf']['foreign_key'],
'attachment_count' => $count,
)
);
return $this->PurchaseOrder->save($poData);
}
I know this post is very old, but I recently faced a similar issue and found another way to handle the same problem. You can continue using the counterCache approach with multiple counterCache, the only difference would be, you need to add you association on the fly, in the __construct method of your model.
public function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
/**
* When using Aliases, associations need to be added on the fly, otherwise, the CounterScope conditions would result in an SQL Error, during counterCache updates
*/
$this->bindModel(
array('belongsTo' => array(
'PurchaseOrder' => array(
'className' => 'PurchaseOrder',
'foreignKey' => 'foreign_key',
'counterCache' => array(
'attachment_count' => array($this->alias . '.model' => 'PurchaseOrder'),
'attachment_count' => array($this->alias . '.model' => 'PurchaseOrder')
)
)
)
)
);
}

Retrieving related model's data CakePHP

Here is the database tables in question:
Companies:
____________________
| id | name |
____________________
| 1| Unimex|
| 2| Solomex|
Users:
________________________
| id | name | company_id
_________________________
| 1| John | 1
| 2| Ricky| 2
Events:
_____________________________________
| id | user_id | details | date|
_____________________________________
| 1| 1| null | 2014-04-01
| 2| 1| null | 2014-04-15
| 3| 2| null | 2013-04-01
| 4| 1| null | 2014-04-02
What I would like to do is to retrieve a list of users(based on company's id) and their related events for a range of dates. What I have tried to do is the following:
$users = $this->User->find('all',
array(
'conditions' => array(
'company_id' => CakeSession::read("Auth.User.company_id")
),
'contain' => array(
'Event' => array(
'conditions' => array(
'Event.date >=' => $from,
'Event.date <=' => $to
)
)
)
)
);
This way I get the list of Users with their related events, but the $from and $to dates are not taken into consideration, meaning all of the events for a particular user are returned.
The relations are like following:
Event:
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
));
User:
var $hasMany = array(
'Event' => array(
'className' => 'Event',
'foreignKey' => 'user_id',
'dependent' => false,
)
);
var $belongsTo = array(
'Company' => array(
'className' => 'Company',
'foreignKey' => 'company_id',
'dependent' => false,
),
);
Company:
var $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'company_id',
'dependent' => false
));
Any help or guidance is much appreciated.
Following are the two queries that are executed by cakePHP:
SELECT `User`.`id`, `User`.`company_id`, `User`.`name`, `User`.`surname`, `User`.`email`, `User`.`phone`, `Company`.`id`, `Company`.`name`, `Company`.`address` FROM `database`.`users` AS `User` LEFT JOIN `database`.`companies` AS `Company` ON (`User`.`company_id` = `Company`.`id`) WHERE `company_id` = 54
SELECT `Event`.`id`, `Event`.`customer_id`, `Event`.`user_id`,`Event`.`details`, `Event`.`hours`, `Event`.`minutes`, `Event`.`xhours`, `Event`.`xminutes`, `Event`.`assignment`, `Event`.`start_time` FROM `database`.`events` AS `Event` WHERE `Event`.`user_id` IN (124, 125, 126, 141, 143, 144, 147, 156)
So as you can see the date in the Event field conditions is not taken into consideration. If there is any other important information that I can provide, please, just let me know.
Moreover, I have just tried to retrieve only specific fields of the Event model, and that did not work as well. So basically the model is just contained as is, an no other parameter is applied.
Or maybe the model is not contained at all and the result I get is only because of the recursive being set to 1?
I don't see the error only as a suggestion
$users = $this->User->find('all',
array(
'contain' => array(
'Event' => array(
'conditions' => array(
'and' => array(
array(
'Event.date >=' => $from,
'Event.date <=' => $to
),
'company_id' => CakeSession::read("Auth.User.company_id")
)
)
)
)
)
);
The problem is that there was a typo. I always thought it has to be:
var $actAs = array('Containable');
But it actually had to be $actsAs.

Retrieving related model's data in CakePHP

Here is the database tables in question:
Companies:
____________________
| id | name |
____________________
| 1| Unimex|
| 2| Solomex|
Users:
________________________
| id | name | company_id
_________________________
| 1| John | 1
| 2| Ricky| 2
Events:
_____________________________________
| id | user_id | details | date|
_____________________________________
| 1| 1| null | 2014-04-01
| 2| 1| null | 2014-04-15
| 3| 2| null | 2013-04-01
What I would like to do is to retrieve events for a particular date based on company's id. What I have tried to do is the following:
$this->User->find('all',
array(
'conditions' => array(
'company_id' => CakeSession::read("Auth.User.company_id")
),
'contain' => array(
'Event' => array(
'conditions' => array(
'Event.date' => date("Y-m-d", $tomorrow)
)
)
)
));
but this retrieves all of the events for the company, the date condition is not being applied.
In the best case I would like to retrieve only the events for one company for a particular date. Otherwise I would get by with returning a list of users related to one company and their events for that particular date.
What would be the most efficient way to do this?
Any help or guidance is much appreciated.
Following are the relations between the tables:
Events:
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
));
Users:
var $belongsTo = array(
'Company' => array(
'className' => 'Company',
'foreignKey' => 'company_id',
'dependent' => false,
),
);
Here is the query that I get:
SELECT Event.id, Event.customer_id, Event.user_id, Event.project_id, Event.service_id, Event.date, Event.start_city, Event.material, Service.id, Service.company_id, Service.name, Service.service_nr, User.id, User.company_id, User.employee_nr, User.name, User.surname, User.email, User.password, User.role, Customer.id, Customer.company_id, Project.name, Project.description, Project.link_nr, Project.start_date, Project.finish_date, Project.project_nr FROM schedule.events AS Event LEFT JOIN schedule.services AS Service ON (Event.service_id = Service.id) LEFT JOIN schedule.users AS User ON (Event.user_id = User.id) LEFT JOIN schedule.customers AS Customer ON (Event.customer_id = Customer.id) LEFT JOIN schedule.projects AS Project ON (Event.Project_id = Project.id) WHERE 1 = 1
The problem right now is that the company id is not taken into concideration, and all of the events are being returned no matter what date it is.
I’ve tried this solution and it works for me.
I made all tables with small letters according to cake conventions like companies, events and users.
This is Event Model
class Event extends AppModel {
var $actsAs = array('Containable');
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
This is controller Event class
$tomorrow = '2013-04-01';
$this->Event->find('all',
array(
'conditions' => array(
'date' => date("Y-m-d", strtotime($tomorrow)),
),
'contain' => array(
'User' => array(
'conditions' => array(
'User.company_id' => CakeSession::read ('Auth.User.company_id')
)
)
)
));
This will give you
SELECT `Event`.`id`, `Event`.`user_id`, `Event`.`details`, `Event`.`date`, `User`.`id`, `User`.`name`, `User`.`company_id`
FROM `schedule`.`events` AS `Event`
LEFT JOIN `schedule`.`users` AS `User` ON (`Event`.`user_id` = `User`.`id` AND `User`.`company_id` = 2)
WHERE `date` = '2013-04-01'
I hope this will work for you. Thanks
try this code:
$this->Event->find('all',
array(
'conditions' => array(
'User.company_id' => CakeSession::read("Auth.User.company_id"),
'Event.date' => date("Y-m-d", $tomorrow)
),
'contain' => array('User')
));

Relationships not working correctly - cakePHP

I have relationships set up by the built in CakePHP build function. First, my tables:
assets
id | company_id | group_id | location_id | item_id | invoice_id | item_number | description | purchase_value | purchase_date | barcode | colour | picture | created | modified
repairs
id | company_id | asset_id | invoice_id | created | modified
My relationship in my asset model looks like this:
public $hasMany = array(
'Repair' => array(
'className' => 'Repair',
'foreignKey' => 'asset_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
And in my repair model, like this:
public $belongsTo = array(
'Asset' => array(
'className' => 'Asset',
'foreignKey' => 'asset_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
However, when I try to view an asset, it shows this error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Asset.asset_id' in 'field list'
SQL Query: SELECT `Asset`.`id`, `Asset`.`company_id`, `Asset`.`group_id`, `Asset`.`location_id`, `Asset`.`item_id`, `Asset`.`invoice_id`, `Asset`.`item_number`, `Asset`.`description`, `Asset`.`purchase_value`, `Asset`.`purchase_date`, `Asset`.`barcode`, `Asset`.`colour`, `Asset`.`picture`, `Asset`.`created`, `Asset`.`modified`, `Asset`.`asset_id` FROM `asset_register`.`assets` AS `Asset` WHERE `Asset`.`company_id` = 1 AND `Asset`.`asset_id` = (4)
Anyone know what the issue is?
EDIT TO UPDATE
My find statement is the plain CakePHP find statement.
$options = array('conditions' => array('Asset.' . $this->Asset->primaryKey => $id));
$this->Asset->recursive = 1;
$this->set('asset', $this->Asset->find('first', $options));
EDIT
Add this line to your asset model
public $primaryKey = 'id';
and make sure that $primaryKey is not defined somewhere else in the model.

Cakephp problem with Save belongsTo

I got problem when save belongto
class Script extends AppModel {
var $name = 'Script';
var $belongsTo = array(
'ScriptCatagories' => array(
'className' => 'ScriptCatagories',
'foreignKey' => 'script_catagories_id',
function add_script() {
pr($this->data);
if (!empty($this->data)) {
$this->Script->create();
$this->data['Script']['script_catagories_id'] = $this->Script->scriptCategory->id;
$this->data['Script']['user_id'] = $this->Auth->user('id');
if ($this->Script->save($this->data)) {
$this->Session->setFlash(__('The script has been saved', true));
$this->redirect(array('action' => 'script_index'));
} else {
$this->Session->setFlash(__('The script could not be saved. Please, try again.', true));
}
}
pr($scriptCatagories = $this->Script->ScriptCatagories->find('list'));
$this->set(compact('scriptCatagories'));
}
when click save
Array
(
[Script] => Array
(
[name] => fdfvvds
[description] => dfvdfvdfvdf
[tags] =>
)
)
Array
(
[0] => performance
[1] => cleanup
)
question in
$this->data['Script']['script_catagories_id'] = $this->Script->scriptCategory->id;
I need to save categoryid to script table but I don't know to get it
thank you
var $belongsTo = array(
'ScriptCatagories' => array(
'className' => 'ScriptCatagories',
'foreignKey' => 'script_catagories_id',
first, it doesn't have close parentheses. And it should be singular ScriptCategory, also the foreign key script_category_id (just to follow the convention). And you misspelled category (you have $this->Script->scriptCategory->id; later in the code)

Resources