I have a hasMany through (the join model) which is not saving, but when reading, it works naturally.
I will try to provide as much detail as possible, so bear with me. Please note I am trying to save a new user paired with quantities of existing products, and I am not wanting to add new products in this save.
Database Tables: users, products, subscribed_users
Table structure of joining table: id, user_id, product_id, quantity, created, modified
User.php
public $hasMany = array(
'SubscribedUser'
);
Product.php
public $hasMany = array(
'SubscribedUser'
);
SubscribedUser.php
class SubscribedUser extends AppModel {
public $belongsTo = array(
'User', 'Product'
);
}
Data array I am trying to save from within the UsersController.php
Array (
[User] => Array (
[username] => asdf
)
[SubscribedUser] => Array (
[0] => Array (
[product_id] => 50f1ef25-6884-44cf-80e4-bd346f01a4c2
[count] => 12
)
[1] => Array (
[product_id] => 50f1f1d6-89b4-4ade-961f-c1a06f01a4c2
[count] => 12
)
)
)
Using $this->User->SubscribedUser->saveAll($data); I have the User properly saved, but my subscribed_users table only has one row (as you can see from my above data, there should be two) and it contains missing data. There is no product_id, and the count number is 0.
I am not sure what I am missing here. Thoughts?
Unless it's a typo the filename Users.php is the most obvious error.
The problem was I was using $this->User->SubscribedUser->saveAll() and not $this->User->saveAll()
My problem is now solved with this resolution.
Related
I have a pretty simple relational model setup. When using $this->model->find('all',$params), the results do not return the complete relational data set. I'm pulling my hair out here.
Here's my table setup:
Table qs_skus:
id (AI, PK)
sku_name
profile
...
Table net_lengths_in_skus:
id (AI,PK)
quick_ship_skus_id
net_lengths_id
Table net_lengths
id (AI,PK)
name
The way the models are configured are:
Model QuickShipSku $hasMany=array('NetLengthsInSku')
Model NetLengthsInSku $hasOne='NetLength'
All models have $actAs = array('Containable')
When doing the following, I get only the first relationship queried, the last relationship is completely ignored:
$model = $this->QuickShipSku->find('all',
array(
'contain' => array(
'NetLengthsInSku' => array('NetLength')
)
);
Output:
Array
(
[0] => Array
(
[QuickShipSku] => Array
(
[id] => 3
[sku_name] => 1112-8
[product_name] => Product A
[sku_specie_id] => 1
[members_ft] => 8
[profile] => Profile Description
)
[NetLengthsInSku] => Array
(
[0] => Array
(
[id] => 10
[quick_ship_skus_id] => 3
[quick_ship_net_length_id] => 1
)
)
)
)
For each NetLengthsInSku there should be a NetLength, but it's not even being queried.
Any ideas?
What you have here is a many to many relationship. That means an association called hasAndBelongsToMany.
If you are using Cake 2.x you should have something like this:
class QsSku extends AppModel {
public $hasAndBelongsToMany = array(
'NetLength' =>
array(
'className' => 'NetLength',
'joinTable' => 'net_lengths_in_skus',
'foreignKey' => 'quick_ship_skus_id',
'associationForeignKey' => 'net_lengths_id',
)
);
}
You should do something similar to your NetLength model as well.
I have two tables
messages
users
users has roles Doctor and user.
messages has doc_id & user_id.
How do I make an association, so that it returns me both data doc_id & user_id from users.
For the Role association on User you will need a join table, thats if i am right in believing a User can have many roles?
You'r Message model should only have a BelongsTo User, then when your doing loop ups you will use deep associations in your find methods to bring back some like...
// Find with deep assosiations
$this->Message->find('all', array());
Array
(
[Message] => Array
(
[id] => 2
[body] => example body...
)
[User] => Array
(
[username] => John
[Role] => Array
(
[0] => 2
[1] => 6
)
)
)
class Message extends AppModel {
public $hasMany=array('MessageDetail');
public $belongsTo = array(
'User'=>array(
'className'=>'User',
'foreignKey'=>'user_id',
),
'Doctor'=>array(
'className'=>'User',
'foreignKey'=>'doc_id'
),
'Petprofiles'=>array(
'className'=>'PetProfiles',
'foreignKey'=>'petprofiles_id'
)
);
}
I need help constructing a CodeIgniter Datamapper ORM query that includes join fields.
I have a table of Merchants and a table of Vendors.
They have a many-to-one relationship, that is, many Merchants are part of a single Vendor.
Thus, my datebase tables, following the Datamapper ORM convention are:
merchants
vendors
merchants_vendors
Furthermore, in the merchants_vendors table, I have join fields 'role' and 'admin'.
Obviously, this data must be placed in the join table, if it were placed in the Merchants table, I wouldn't be able to define roles and administrators per Vendor.
Lastly, Merchants are related to Users by a one-to-one relationship.
Think of Merchants as just an extension of Users.
I'm attempting to create a PHP array from the data that follows this data structure, but I can't seem to get the role and admin fields populating properly. I removed redundant columns for your simplicity:
[vendor] => Array
(
[id] => 1
[name] => Vendor1
[users] => Array
(
[0] => Array
(
[id] => 277
[username] => merchant1
[firstname] => Merchant1
[merchant] => Array
(
[id] => 1
[user_id] => 277
[role] => Sales
[admin] => 0
)
)
[1] => Array
(
[id] => 282
[username] => merchant2
[firstname] => Merchant2
[merchant] => Array
(
[id] => 2
[user_id] => 282
[role] => Software
[admin] => 1
)
)
)
)
Here's the code I'm using - Assuming we know the Vendor ID:
$v = new Vendor($id);
if($v->exists())
{
$d['vendor'] = $v->to_array();
$m = new Merchant();
$m->where_related_vendor('id', $v->id)->get();
if($m->exists())
{
foreach($m as $mK => $mV)
{
$u = new User();
$u->where_related_merchant('id', $mV->id)->get();
$d['vendor']['users'][$mK] = $u->to_array();
$d['vendor']['users'][$mK]['merchant'] = $mV->to_array();
}
}
}
$this->load->view('myview', $d);
This gets me as far as the above PHP data structure without the role and admin.
I am well aware of the include_join_fields() function - but I cannot seem to get it working. Specifically, I tried $m->vendor->include_join_fields(); Then tried to access the role/admin fields by $mV->vendor->join_role and $mV->vendor->join_admin - but that doesn't work.
Your help is much appreciated!
The solution was to use include_join_fields() on the $mV object inside the forloop:
$v = new Vendor($id);
if($v->exists())
{
$d['vendor'] = $v->to_array();
$m = new Merchant();
$m->where_related_vendor('id', $v->id)->get();
if($m->exists())
{
foreach($m as $mK => $mV)
{
$u = new User();
$u->where_related_merchant('id', $mV->id)->get();
$mV->vendor->where('id', $v->id)->include_join_fields();
$d['vendor']['users'][$mK] = $u->to_array();
$d['vendor']['users'][$mK]['merchant'] = $mV->to_array();
$d['vendor']['users'][$mK]['merchant']['role'] = $mV->vendor->join_role;
$d['vendor']['users'][$mK]['merchant']['admin'] = $mV->vendor->join_admin;
}
}
}
$this->load->view('myview', $d);
Ongoing discussion in the CodeIgniter forums.
I will post more information as it arrives.
include_join_fields() doesn't execute anything, it just sets a flag that you want these fields included.
Both examples above miss the get() that actually executes the query...
At first sorry for my English.
I've got a problem in associative models in CakePHP. When I bind more than two models, for example
$this->Album->bindModel(
array(
'hasMany'=>array(
'Photo'=>array(
'className'=>'Photo'
),
'Album'=>array(
'className'=>'Album'
)
)
)
);
I have:
Array
(
[Album] => Array
(
[id] => 22
[f_name] => Some album
[0] => Array
(
[id] => 19
[f_name] => Another album
[id_parent] => 22
[Photo] => Array
(
....
Is it any way to set a key in parent table? I mean I don't want to have "0" as a key, there can be "Album1", "Album2" and so on.
The problem likely stems from binding a model to itself under the same name. Album hasMany Album probably trips up Cake somewhere. Use a unique name for the association, like Album hasMany SubAlbum.
I'm developing a simple application with CakePhp, and need some help on creating a multi-record edit form using some related data.
The application I'm developing is pretty straightforward, its main purpose is managing students records: updating, deleting, changing a student from one group to another, the usual suspects.
The relevant tables of the database are:
group = (id, teacher, classroom, etc)
groups_students=(groupID, studentID, since, until)
students = (id, name, last_name, etc)
assitance = (id, assitance, date)
assistance_students (studentID, assitanceID, meta_information )
As you might have gathered from the tables above, the application is supposed to aid in recording assitance. Which is where I'm having some issues.
What I want to do is this:
Have the user select a group
In de detail group, I'll have an action called "Register Assistance"
Register assitance should redirect to a view in wich for every student belonging to that group, the user can see the student's assitance, edit them, and save. Something like this:
In which A stands for "Absent" and P for "Present" and the user can edit everyone, and the save.
I just don't know how to go about that? How do I manage that? I've managed to create a multi-edit form for the assitance, but adding the related data is a pain, I don't know if I should query the students from the groups controllers and then pass that to the action to register assitance, or manage all the logic inside the assitance controller?
Any help would be great,
thanks!
Edit: Here's the output of $this->Student->find('first');
Array (
[Alumno] => Array (
[id] => 14
[tipo] => dni
[dni] => 2321312312
[apellido] => COQUITO
[nombre] => Pepe
[carrera] => ComposiciĆ³n Musical
[creado] => 2011-01-08 17:59:00
[modificado] => 2011-01-08 17:59:00
)
)
The output is in spanish. Alumno = Student, nombre= first name, apellido= last_name.
Well, I managed to find a solution to this. I was waiting to see if anyone found something better, as I'm pretty sure my solution is far from the best, but here it goes, in case someone finds this question in the future.
My issue was that I needed, for every group I selected to register assitance:
Every student that belonged to that group
All the assitances of the students belonging to that group
Now, in order to make use of the Form helper to edit those assitences (and after, the saveAll() method), I needed $this->data to have ann array like this:
Array
(
[Assitance] => Array
(
[5] => Array
(
[id] => 5
[date] => 2011-01-09
[assitance] => A
[updated] => 2011-01-16 21:32:00
[created] => 2011-01-16 21:32:00
)
[6] => Array
(
[id] => 6
[date] => 2011-03-09
[assitance] => A
[updated] => 2011-01-16 21:32:00
[created] => 2011-01-16 21:32:00
)
)
)
at the same time, though, I needed each student linked to his or her assitances, to be able to loop trough them, and display the edit forms for every assitance in a table like the one in the question:
What I ended up doing is this
First, I query all the students belonging to the selected group.
For each student get all his/her assitances .
so, for each student, I ended up having an array like this:
Array
(
[Student] => Array
(
[id] => 12
[last_name] => LASARTE
[name] => Julia
[created] => 2011-01-08 16:35:00
[updated] => 2011-01-08 16:35:00
[assitance] => Array
(
[0] => Array
(
[Assitance] => Array
(
[id] => 4
[date] => 2011-01-09
[assitance] => z
[updated] => 2011-01-16 20:51:00
[created] => 2011-01-16 20:51:00
)
[assitance_studenty] => Array
(
[id] => 2
[student_id] => 12
[assitance_id] => 4
[comision] => 0
)
)
)
)
)
)
Now, with that, I have the information I need in order to display the table and create the forms, but I still need the assitances data in $this->data, so the form helper can create the from displaying the correct information, and afterwars, saveAll() updates the rows in the database correctly.
What I needed to do was turn the array of $students into an structure like the one at the beginning of the post. Enter the Set Class:
$formated_students = Set::combine($students, '{n}.students.id', '{n}.students');
$assitance = Set::extract('/presentes/Assistance', $formated_students);
$this->data['Assistance'] = Set::combine($assistance, '{n}.Assistance.id', '{n}.Assistance');
I'm pretty sure the first to lines (formating the students array in order to extract the assitance) can be done with just one Set::extract or Set::classicExtract, but this worked and regular expressions are really not my thing, so.
After that, It's just a matter of looping trough the data and making the table:
<?php
echo $form->create('Assistance', array('url' => array('controller' => 'Comisions', 'action' => 'register_assitance')));
foreach ($students as $student) { ?>
<tr><td>><?php echo $student['students']['last_name'].", ".$student['students']['name']; ?></td>
<?php foreach ($student['students']['assitance'] as $asstiance) { ?>
<td><?php echo $form->input('Assistance.'.$assitance['Assistance']['id'].'.id');
echo $form->input('Assistance.'.$assitance['Assistance']['id'].'.assistance', array( 'label' => false, 'size' => 1)) ?></td>
<?php } ?>
</tr>
<?php } ?>