Cakephp Relationships - cakephp

I have a few models which are not in the default cakephp format
user(id, name....)
1 Harsha ...
2 John ....
dishes(id, name, price ...)
1 "Cheese Pizza" 6
2 "Zinger Burger" 3
restaurants (id, name, .....)
1 "KFC" ...
2 "Pizza Hut" ...
module(id, name) values (User, Dishes, Restaurants)
1 "Users"
2 "Dishes"
3 "Restaurant"
items (id, module_id, item_id)
1 1 1 (refers to User Harsha)
2 3 2 (refers to Pizza hut)
3 2 2 (refers to Zinger Burger)
4 1 2 (refers to User John)
where item_id refers to the Id of Users, Dishes or Rests Depending on the module_id
reviews (id, parent_id, review, time, item_id, commenter_id)
1 0 "Best Burger in the world" "time" 3 1 (refers to Harsha reviewing Zinger Burger)
2 1 "Yes i love Zingers tooo" time 3 2 ( refers to John replying to Harsha's Review)
I am a little messged up on how to draw up the relationships in cakephp

In the book at this page: http://book.cakephp.org/view/1039/Associations-Linking-Models-Together you'll find a guide to the possible keys you can set on the relationship, e.g.
foreignKey: the name of the foreign
key found in the other model. This is
especially handy if you need to define
multiple hasOne relationships. The
default value for this key is the
underscored, singular name of the
current model, suffixed with ‘_id’. In
the example above it would default to
'user_id'.
Assuming reviews and items are children in their associations, for both ends of the relationships, you'd set the foreignKey as 'item_id'.
Something like:
dishes:
class Dish extends AppModel {
var $name = 'Dish';
var $hasMany = array(
'Item' => array(
'className' => 'Item',
'foreignKey' => 'item_id',
...
items:
class Item extends AppModel {
var $name = 'Item';
var $belongsTo = array(
'Dish' => array(
'className' => 'Dish',
'foreignKey' => 'item_id',
...
),
'Restaurant' => array(
'className' => 'Restaurant',
'foreignKey' => 'item_id',
...
It's difficult to be more precise, but you haven't provided any datamodel. To handle the selection of Model via the Module, you'll need to write some code on a model somewhere, which one(s) depends on how you access the data.
However, it looks to me like a good time to restructure the database!

Related

CakePHP 2.4 saveAssociated not saving all children elements

Problem Synopsis:
(CakePHP v2.4.2) When I use saveAssociated (or saveAll, same result) for input for a new record with a hasMany/belongsTo relationship with multiple child elements, only the last child element gets saved because it INSERTs the first element, but then executes UPDATES for subsequent elements.
I've used saveAssociated for very similar purposes in this same application and had no problem with it, so I'm baffled.
Queries on all these work just fine, i.e., I get the multiple children associated with each parent.
Models synopsis:
class Site extends AppModel {
// sites columns: id (primary key), bunch of others
public $hasMany = array(
'SiteUser' => array(
'className' => 'SiteUser',
'foreignKey' => 'id', // Yes, I would have preferred 'site_id', lost battle
'dependent' => true
)
);
}
class SiteUser extends AppModel {
// site_users columns: rowid(PK), id (FK to sites), name
public $belongsTo = array(
'className' => 'Site',
'foreignKey' => 'id'
);
}
Equivalent request data (processed from form):
$site_data = array(
'Site' => array('field1' => 'value1', 'field2' => 'value2' ),
'SiteUser' => array(
array('name' => 'Jane Doe'),
array('name' => 'John Doe'),
array('name' => 'Moe Money')
)
);
In the controller:
unset($this->Site->SiteUser->validate['id']);
$saved_site = $this->Site->saveAssociated($site_data);
Results:
All of the Site data gets saved as expected. Only the last SiteUser element (Moe Money in the example) is saved. This is the same regardless of the number of elements in SiteUser, i.e., only the last element gets saved.
SQL Log:
It performs an
INSERT INTO site_users (`name`, `id`) VALUES ('Jane Doe', 1)
but then executes
UPDATE site_users SET 'name' = 'John Doe', 'id' = 1 WHERE site_users = 1
UPDATE site_users SET 'name' = 'Moe Money', 'id' = 1 WHERE site_users = 1
This obviously leaves the very last element as the one to get saved, the others are over-written by updates.
Thanks for any pointers in advance.
You better stick to the conventions, id as the foreign key? No, really, don't do that!
In any case you must tell your SiteUser model about the primary key column name in case it doesn't follow the conventions. See Cookbook > Models > Model Attributes > primaryKey
class SiteUser extends AppModel {
public $primarykey = 'rowid';
// ...
}
And while setting this to rowid will most likely fix the problem, I'd again advise to stick to the naming conventions instead!

ID fields not auto filled for table with multiple associations (CakePHP)

I'm working on a customer database. For larger business customers the relationships get a little complicated. It's almost working but one ID field is not being automatically filled.
I have 3 models, Customer, CustomerAddress and CustomerContact. A customer can have many addresses, and many contacts, but the contacts are also based at one address so an address has many contacts.
Database:
customer has id
customer_addresses has customer_id
customer_contacts has customer_id, customer_address_id
Models:
class Customer extends AppModel {
public $hasMany = array(
'CustomerContact',
'CustomerAddress',
);
....
}
class CustomerAddress extends AppModel {
public $belongsTo = array(
'Customer',
);
public $hasMany = array(
'CustomerContact',
);
....
}
class CustomerContact extends AppModel {
public $belongsTo = array(
'Customer',
'CustomerAddress',
);
....
}
I have one form that adds fields for all 3 models, and I'm calling '$this->Customer-saveAll' in the controller. It saves everything just fine, but doesn't fill in the 'customer_address_id' field in the 'customer_contacts' table.
I've tried changing the relationship in contacts to belongs to address, I've tried renaming the field to customer_addresses_id (made it pleural) just incase it was a quirk with Cake's internal naming, but it still doesn't fill the address ID field.
My workaround is to update the contact after the saveAll command in the controller, since the address has it's id set at this point:
$this->CustomerContact->saveField( 'customer_address_id', $this->CustomerAddress->id);
This is my first project with Cake and it seems really good at doing this stuff by itself, so I'm wondering if I've got something wrong somewhere.
TIA!
EDIT:
After going through the associations again, I changed the association on CustomerContact from hasOne to belongsTo CustomerAddress because I realised I got it wrong.
I tried 2 different ways of submitting the data:
'Customer' => .... data ....
'CustomerAddress' => array(
(int) 0 => array(
'CustomerContact' => array(
(int) 0 => array(
.... data ....
)
),
.... data ....
)
)
This sets the customer_address_id field on the contact, but not customer_id.
'Customer' => .... data ....
'CustomerAddress' => array(
(int) 0 => array(
.... data ....
)
),
'CustomerContact' => array(
(int) 0 => array(
.... data ....
)
)
This sets the customer_id but not the customer_address_id.

CakePHP - Saving an hasMany through association

I'm currently trying to figure out how to save a hasMany through relationship.
My tables are:
cards:
id,
name
colors:
id,
name,
color
card_colors (associated with the model CardColor):
id,
card_id,
color_id,
cost
hasMany through Association:
Card hasMany CardColor
Color hasMany CardColor
CardColor belongsTo Card
CardColor belongsTo Color
In Card::beforeSave(), I'm going to reconstruct my $data variable so that it has this structure:
array(
'Card' => array(
'name' => 'theCard',
'CardColor' => array(
array(
'card_id' => 4,
'color_id' => 5,
'cost' => 2
),
array(
'card_id' => 5,
'color_id' => 2,
'cost' => 3
)
)
)
)
However, I don't know how to get the card_id for the card that I am currently inserting. Is there a more Cake-y way of saving a hasMany through association (such as getting the card id automatically in some way while saving)?
Try this:
Use $this->Card-create() // or just $this->create() in the model
In Card::beforeSave(), don't set the index CardColor[i][card_id]
Do the save this way: $this->saveAssociated($data)

Associations not working properly in CakePHP

I have the following Models
Shop
_____________________________________
Id Name address city postalcode ...
Category
_______________________________________
Id Name Description shop_id ...
Product
______________________________________
Id Name Description category_id ...
And my Product Model I have defined $belongsTo relation like
public $belongsTo = array(
'Category' => array(
'className' => 'Category',
'conditions' => array('Category.shop_id' => 5)
)
);
What I need is that when I want to add New Product, in the Categories SelectBox should appear only Categories belonging to shop_id = 5 but I am getting all Categories.
Or i have to change the find method?
Yes, you need to add the conditions in the find query as you require it for add product
form.

Cakephp: HasOne Relationship

I'm trying to model the following:
A journey has an id, a fromCity and a toCity.
My DB looks like this:
Table journey:
id | fromCity | toCity
1 2 4
2 4 2
Table fromCity:
id | name
2 paris
4 london
I have models defined for the city and for the journey.
In my model file for the journey I want to declare a $hasOne filed in order resolve the fromCity id to the city's name.
I tried to follow the CakePHP tutorial on hasOne (http://book.cakephp.org/view/80/hasOne) but I can't wrap my head around how to resolve two foreign keys.
Can someone please explain to me how a var $hasone = ... has to look for this case?
Edit: The models:
<?php class City extends AppModel { var $name='City';} ?>
<?php class Journey extends AppModel { var $name='Journey'; /*var $hasOne=array(...)*/} ?>
Edit 2:
var $hasOne = array(
'CityFrom' => array(
'className' => 'City',
'conditions' => 'Journey.fromAirport = CityFrom.id',
'dependent' => true,
'foreignKey' => 'id = Journey.fromCity' ),
'CityTo' => array (
'className' => 'City',
'conditions' => 'Journey.toCity = CityTo.id',
'dependent' => true,
'foreignKey' => 'id = Journey.toCity'
)
);
Seems to work for the first entry of the journey table. All other's values are null. I think the problem occours from having two columns with the same name in this query.
As Rin mentioned,you need to use beLongsTo instead of hasOne.Here's a example about Multiple relations to the same model from Cookbook.Hope it helps.
First of all your link leads to 1.2 docs, you probably downloaded 1.3.
In 1.3, you should probably also use belongsTo on FromCity and ToCity Models (but I could be wrong, long time ago I used it :)

Resources