CakePHP - saving HABTM fails - php

I have tables that looks like this. Basically WarehousePlace can have many ItemType in it and ItemType can be used by many WarehousePlace. But when I try to save I get an database error:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'WarehousePlacesItemType.item_type_id' in 'field list'
SQL Query: SELECT `WarehousePlacesItemType`.`item_type_id` FROM `modules`.`warehouse_places_item_types` AS `WarehousePlacesItemType` WHERE `WarehousePlacesItemType`.`warehouse_place_id` = '22'
But everything is done by conventions and also debugged data is like it should be and I do not see what is wrong.
WarehousesController
public function add() {
$this->load();
if ($this->request->is('post')) {
$data = array(
'WarehousePlace' => array(
'name' => $this->request->data['WarehousePlace']['name'],
),
'ItemType' => array(
'ItemType' => $this->request->data['ItemType']['ItemType']
)
);
$this->WarehousePlace->create();
if ($this->WarehousePlace->saveAll($data, array('validate' => 'first', 'deep' => true))) {
//success
}
if ($this->WarehousePlace->validationErrors) {
//validation
} else {
//error
}
}
}
tables:
warehouse_places_item_types(warehouse_places_id,item_types_id) -> no primary key since CakePHP 2,
warehouse_places(id, name),
item_types(id, name)
Models:
ItemType
public $hasAndBelongsToMany = array(
'WarehousePlace' => array(
'className' => 'WarehousePlace',
'joinTable' => 'warehouse_places_item_types',
'foreignKey' => 'item_type_id',
'associationForeignKey' => 'warehouse_place_id',
'unique' => 'keepExisting',
)
);
WarehousePlace
public $hasAndBelongsToMany = array(
'ItemType' => array(
'className' => 'ItemType',
'joinTable' => 'warehouse_places_item_types',
'foreignKey' => 'warehouse_place_id',
'associationForeignKey' => 'item_type_id',
'unique' => 'keepExisting',
)
);

Related

Cakephp. SQLSTATE[42S22]: Column not found: 1054 Unknown column 'CalendarsClassification.id' in 'field list'

When I delete a classification, I get this error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'CalendarsClassification.id' in 'field list'
SQL Query: SELECT `CalendarsClassification`.`id` FROM `calendars_classifications` AS `CalendarsClassification` WHERE `CalendarsClassification`.`calendar_id` = 221
CalendarsClassification.id does not exist, but I do not know how to change it.
ClassificationsController
public function delete($id = null) {
if (!$id) {
$this->flash(__('Invalid Classification', true), array('controller'=>'clients','action'=>'index'));
}
$this->request->data = $this->Classification->read(null, $id);
if ($this->Classification->delete($id, true)) {
$this->flash(__('Classificació esborrada.', true), array('controller'=>'blocks','action'=>'view',$this->data['Classification']['block_id']));
}
}
Model Classification
class Classification extends AppModel {
var $name = 'Classification';
var $validate = array(
'long_name' => array(
'rule' => array('minLength', 1)
)
);
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $belongsTo = array(
'Block' => array('className' => 'Block',
'foreignKey' => 'block_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'Line' => array('className' => 'Line',
'foreignKey' => 'classification_id',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'dependent' => true,
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
var $hasAndBelongsToMany = array(
'Calendar' => array('className' => 'Calendar',
'joinTable' => 'calendars_classifications',
'foreignKey' => 'calendar_id',
'associationForeignKey'=> 'classification_id',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'unique' => true,
'finderQuery' => '',
'deleteQuery' => '',
)
);
}
if there is the field 'id' in the table and still you are unable to delete the row then you should clear the cache and then try to delete the row.
here is the path for cache:
\app\tmp\cache\models
and
\app\tmp\cache\persistent
Note: Do not delete the folder.
Hope this helps
i believe it should be "calendar_id" instead of "id".
As per the Query reflects.
SELECT CalendarsClassification.id FROM calendars_classifications AS CalendarsClassification WHERE CalendarsClassification.calendar_id = 221
If you're table doesn't have a column id then you need to define which column is the primary key in the relevant model. For example:-
class CalendarsClassification extends AppModel {
public $primaryKey = 'example_id';
}
The model delete() method uses the primary key as the first parameter to delete with so you must set the primaryKey for the model if it is different from Cake conventions before using this method.
You really should have a primary key for every model and it is advisable to stick with Cake conventions and name it id if possible as this will simplify your code significantly.
If you are not trying to delete a record by the primary key then you want to be using deleteAll() for which you can pass conditions for the deletion as the first parameter. Something like this:-
$this->CalendarsClassification->deleteAll(['example_id' => $id]);

hasAndBelongsToMany in CakePHP 2.x

I need help for the simple relationchip in cakephp 2.x, I believe this right however not working:
Customer.php (Model)
public $hasAndBelongsToMany = array(
'Note' => array(
'className' => 'Note',
'joinTable' => 'customers_notes',
'foreignKey' => 'customer_id',
'associationForeignKey' => 'note_id',
'unique' =>false,
'dependent'=>true,
)
);
Note.php (Model)
public $hasAndBelongsToMany = array(
'Customer' => array(
'className' => 'Customer',
'joinTable' => 'customers_notes',
'foreignKey' => 'note_id',
'associationForeignKey' => 'customer_id',
'unique' =>false,
'dependent'=>true
)
);
CustumersController.php (Controller I make the find)
public function admin_notes($id=null){
$this->layout="Adm.admin";
$all = $this->Customer->Note->find('all', array(
'limit' => 10,
'conditions' => array(
"CustomersNote.customer_id" => $id
),
'order'=>'CustomersNote.id DESC'
));
$this->set('notes', $all);
}
The error
SQL Query: SELECT `Note`.`id`, `Note`.`titulo`, `Note`.`conteudo`, `Note`.`created`, `Note`.`modified`, `Note`.`user_id` FROM `crm_prado`.`notes` AS `Note` WHERE `CustomersNote`.`customer_id` = '1' LIMIT 10
Thanks!
The soluction is really simple.
In find uses
$all = $this->Customer->find('all', array(
'recursive'=>2,
'conditions'=>array(
'Customer.id'=>$id
)
));
Works!, but now the recursive mode don't work...

cant add new record in HABTM table

I want to add a new record in a table called TutorsSubject. This table is created from HABTM relationship of Tutor and Subject. Anyway I load the subject names in a text box and I can select a subject name but I cant add a new record. I need to set the id of the tutor_id.
There are 3 fields in the tutorsSubject table called id,tutor_id and subject_id. I only need to select in 1 field which is the subject_id from a list of names found in the subject table, and then set the tutor_id manually.
Currently I am able to select from a list of subject names but I cant add a new record with the subject name and set tutor_id.
Error: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails
class TutorsSubjectsController extends AppController {
public function tutoradd() {
$this->loadModel('Subject');
$options['recursive']=-1;
$options['fields']=array('Subject.name');
$te2= $this->Subject->find('list',$options);
debug($te2);
$this->set( 'te',$te2);
//put is for edit and post for new record
if ($this->request->is('post')) {
$this->request->data['TutorsSubject']['tutor_id']=2;
debug($this->request->data);
if ($this->TutorsSubject->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been updated.'));
return $this->redirect(array('controller' => 'tutors','action' => 'tutordetails'));
}
$this->Session->setFlash(__('Unable to update your post.'));
}
//View which works fine as it displays the list
echo $this->Form->create('TutorsSubject', array('type' => 'post'));
echo $this->Form->input('tutorsSubject.subject_id', array('options' => $te));
echo $this->Form->end('Save Post');
//model subject
public $hasAndBelongsToMany = array(
'Tutor' => array(
'className' => 'Tutor',
'joinTable' => 'tutors_subjects',
'foreignKey' => 'subject_id',
'associationForeignKey' => 'tutor_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
)
);
//model tutor
public $hasAndBelongsToMany = array(
'Subject' => array(
'className' => 'Subject',
'joinTable' => 'tutors_subjects',
'foreignKey' => 'tutor_id',
'associationForeignKey' => 'subject_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
'deleteQuery' => '',
'insertQuery' => ''
),
);

CakePHP SaveAssociated / SaveAll ignoring fields

I am having an issue where CakePHP is ignoring saving a field I specify and instead creating extra records. I am using CakePHP 2.3.6.
My table looks like this:
CREATE TABLE `events_guests` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`guest_id` int(11) NOT NULL,
`event_id` int(11) NOT NULL,
`promoter_id` int(11) DEFAULT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`attended` varchar(15) NOT NULL DEFAULT 'No',
PRIMARY KEY (`id`)
)
Heres the code
public function addGuest($event_id, $promoter_id = null) {
if ($this->request->is('post')) {
$this->Guest->create();
$event_data = array('event_id' => $event_id);
$data = $this->request->data;
$data['Event'] = $event_data;
if($promoter_id) {
$data['Event']['promoter_id'] = $promoter_id;
}
if ($this->Guest->saveAssociated($data)) {
$this->Session->setFlash(__('The guest has been added to the guestlist'), 'flash/success');
} else {
$this->Session->setFlash(__('The guest could not be saved. Please, try again.'), 'flash/error');
}
Here is my data that I am trying to save:
Array (
[Guest] => Array
(
[first_name] => Joe
[last_name] => Schmoe
)
[Event] => Array
(
[event_id] => 1
[promoter_id] => 2
)
)
My Models follow:
class Guest extends AppModel {
public $hasAndBelongsToMany = array(
'Event' => array(
'className' => 'Event',
'joinTable' => 'events_guests',
'foreignKey' => 'guest_id',
'associationForeignKey' => 'event_id',
'unique' => 'true',
),
'Promoter' => array(
'className' => 'Promoter',
'joinTable' => 'events_guests',
'foreignKey' => 'guest_id',
'associationForeignKey' => 'promoter_id',
'unique' => 'true',
)
);
}
And
class Event extends AppModel {
public $hasAndBelongsToMany = array(
'Guest' => array(
'className' => 'Guest',
'joinTable' => 'events_guests',
'foreignKey' => 'event_id',
'associationForeignKey' => 'guest_id',
'unique' => 'keepExisting',
'order' => 'last_name',
),
'Promoter' => array(
'className' => 'Promoter',
'joinTable' => 'events_promoters',
'foreignKey' => 'event_id',
'associationForeignKey' => 'promoter_id',
'unique' => 'keepExisting',
)
);
}
The results from this are 2 records for EventsGuests, neither with a promoter_id.
One record receives event_id = 1 AS EXPECTED
Other record receives event_id = 2, which is actually the promoter_id
I have tried using a mix of saveAssociated and saveAll
Any help is greatly appreciated! Thank you!
Reference: Cakephp save extra attribute in HABTM relation
For your problem, don't use HABTM, because, HABTM is normally use for connect 2 tables.
So, if you have more than 2 fields, create a model and use it like belongsTo and hasMany relationships.
class Event extends AppModel {
$hasMany = array(
'EventGuest' => array(
'className' => 'EventGuest',
'foreignKey' => 'event_id'
)
);
}
class Guest extends AppModel {
$hasMany = array(
'EventGuest' => array(
'className' => 'EventGuest',
'foreignKey' => 'guest_id'
)
);
}
class Promoter extends AppModel {
$hasMany = array(
'EventGuest' => array(
'className' => 'EventGuest',
'foreignKey' => 'promoter_id'
)
);
}
Now, your relationship model.
class EventGuest extends AppModel {
$belongsTo = array(
'Event' => array(
'className' => 'Event',
'foreignKey' => 'event_id'
),
'Guest' => array(
'className' => 'Guest',
'foreignKey' => 'guest_id'
),
'Promoter' => array(
'className' => 'Promoter',
'foreignKey' => 'promoter_id'
)
);
}
And continue use your code.
public function addGuest($event_id, $promoter_id = null) {
if ($this->request->is('post')) {
$this->Guest->create();
$event_data = array('event_id' => $event_id);
$data = $this->request->data;
$data['Event'] = $event_data;
if($promoter_id) {
// EDITED
$data['Promoter']['promoter_id'] = $promoter_id;
}
if ($this->Guest->saveAssociated($data)) {
$this->Session->setFlash(__('The guest has been added to the guestlist'), 'flash/success');
} else {
$this->Session->setFlash(__('The guest could not be saved. Please, try again.'), 'flash/error');
}
}
}

Chained contain and paginate in Cakephp

Two Languages belongs to Lset, Lset HABTM Translator
It is defined as follows:
Translator:
var $hasAndBelongsToMany = array(
'Lset' => array(
'className' => 'Lset',
'joinTable' => 'lsets_translators',
'foreignKey' => 'translator_id',
'associationForeignKey' => 'lset_id',
)
);
Lset:
var $belongsTo = array(
'langfrom' => array(
'className' => 'Language',
'foreignKey' => 'from_id',
),
'langto' => array(
'className' => 'Language',
'foreignKey' => 'to_id',
)
);
The thing i am doing is :
$this->paginate['Translator']['contain'] = array('Lset' =>array('langfrom', 'langto'));
debug($this->paginate());
In my opinion I should get Translator with Lsets, each of them with associated Language, but i only get an error:
SQL Error: 1054: Unknown column 'Lset.langfrom' in 'field list'
How should I do this ?
okay, found that. assosciants should be named with capital letter.

Categories