Monday, March 5, 2012

Re: Saving simple associations

There are some non standard aspects to your code that might contribute to your problem. My advice would be to make some small changes and stick to conventions, if that's possible.

Your field on the people table should be country_id, not countries_id. It's always the singular table name plus '_id' (i.e. country_id) not the name of the table, which is always plural (i.e. countries_id).

Then your data array becomes:

$people = array
(
'Person' => array(
0 => array(
'age' => 23,
'country_id' => 1 // assuming the id of Belgium = 1
),
1 => array(
'age' => 12,
'country_id' => 2 // assuming the id of Austria = 2
),
2 => array(
'age' => 55,
'country_id' => 1
)
)
);


...and your save command is:

$this->Person->saveAll($people['Person']);

Note that you haven't had to create the Person.id field values - Cake will always take care of that for you.

If you want to collect the country_id value as well, do this:

$countries = $this->Country->find(
'list',
array(
'conditions' => array(
'Country.name' => array(
'Austria', 'Belgium'
),
'fields' => array(
'Country.name', 'Country.id'
)
)
)
);

This will return you an array of countries similar to this:

Array
(
['Austria'] => 1
['Belgium'] => 2
)

So you could modify the $people array to:

$people = array
(
'Person' => array(
0 => array(
'age' => 23,
'country_id' => $countries['Belgium']
),
1 => array(
'age' => 12,
'country_id' => $countries['Austria']
),
2 => array(
'age' => 55,
'country_id' => $countries['Belgium']
)
)
);

...and it will insert the correct country_id for you.

Jeremy Burns
Class Outfit

http://www.classoutfit.com

On 5 Mar 2012, at 10:21, FirstTimeBaker wrote:

> Jeremy thanks, but the problem remains.
>
> When I rerun the code, SQL log looks like this:
> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
> `Country`.`name` = 'Belgium'
> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
> `Country`.`name` = 'Austria'
> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
> `Country`.`name` = 'Belgium'
>
> So Cake just looks if countries already exist and it does not perform
> any insert.
>
> Could it be possible that I _must_ manually set the persons.person_id
> when I insert people? However, it puzzles me that the code works when
> a new person's country does not exist in the table, and not
> otherwise.
>
> Also, is there a better place to ask this kind of question?
>
> Thanks.
>
> On Mar 5, 8:10 am, Jeremy Burns | Class Outfit
> <jeremybu...@classoutfit.com> wrote:
>> Try adding $this->Person->create(); before $this->Person->saveAll($data);
>>
>> Jeremy Burns
>> Class Outfit
>>
>> http://www.classoutfit.com
>>
>> On 4 Mar 2012, at 12:15:03, FirstTimeBaker wrote:
>>
>>
>>
>>
>>
>>
>>
>>> Tilen hvala but that's not it. the problem is that if a country
>>> already exists in the table, the code does not insert anything. So if
>>> I rerun the code above, not a single person is added.
>>
>>> On Mar 3, 11:43 pm, Tilen Majerle <tilen.maje...@gmail.com> wrote:
>>>> In ur for statement use $i++ instead of ++$i :)
>>
>>>> Dne sobota, 03. marec 2012 je poĊĦiljatelj FirstTimeBaker <
>>>> thinkgrea...@gmail.com> napisal:
>>
>>>>> Hi all.
>>
>>>>> I am new with CakePHP and I have the following problem with testing
>>>>> associations.
>>
>>>>> I have two objects: a country and a person. One person can live in one
>>>>> country and a country can have many people. I have two test tables as
>>>>> follows:
>>
>>>>> Table countries:
>>
>>>>> CREATE TABLE IF NOT EXISTS `countries` (
>>>>> `id` int(11) NOT NULL AUTO_INCREMENT,
>>>>> `name` varchar(20) NOT NULL,
>>>>> PRIMARY KEY (`id`),
>>>>> UNIQUE KEY `a` (`name`)
>>>>> ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
>>
>>>>> Note, that the field name in countries has to be unique.
>>
>>>>> Table people:
>>
>>>>> CCREATE TABLE IF NOT EXISTS `people` (
>>>>> `id` int(11) NOT NULL AUTO_INCREMENT,
>>>>> `age` int(11) NOT NULL,
>>>>> `countries_id` int(11) NOT NULL,
>>>>> PRIMARY KEY (`id`,`countries_id`),
>>>>> UNIQUE KEY `name_UNIQUE` (`age`),
>>>>> KEY `fk_persons_countries` (`countries_id`)
>>>>> ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
>>
>>>>> As you can notice, both tables are associated through the foreign key
>>>>> 'countries_id' in people.
>>
>>>>> I have the corresponding models:
>>
>>>>> Model Country:
>>
>>>>> <?php
>>>>> class Country extends AppModel {
>>>>> public $name = 'Country';
>>
>>>>> var $useDbConfig = 'test'; // We use the test database.
>>
>>>>> public $validate = array ('name' => 'isUnique');
>>
>>>>> public $hasMany = array(
>>>>> 'Person' => array(
>>>>> 'className' => 'Person',
>>>>> 'foreignKey' => 'countries_id'
>>>>> ));
>>>>> }
>>>>> ?>
>>
>>>>> Model Person:
>>
>>>>> <?php
>>>>> class Person extends AppModel {
>>>>> public $name = 'Person';
>>
>>>>> var $useDbConfig = 'test'; // We use the test database.
>>
>>>>> public $belongsTo = array('Country' => array(
>>>>> 'className' => 'Country',
>>>>> 'foreignKey' => 'countries_id'
>>>>> ),);
>>>>> }
>>>>> ?>
>>
>>>>> In people controller I wish to add the following three people:
>>
>>>>> $people = array
>>>>> (
>>>>> array('id' => 1, 'age' => 23, 'country' => 'Belgium'),
>>>>> array('id' => 2, 'age' => 12, 'country' => 'Austria'),
>>>>> array('id' => 3, 'age' => 55, 'country' => 'Belgium')
>>>>> );
>>
>>>>> with the following code:
>>>>> for ($i = 0; $i < 3; ++$i)
>>>>> {
>>>>> $data['Person'] = array('id' => $people[$i]['id'], 'age' =>
>>>>> $people[$i]['age']);
>>>>> $data['Country'] = array('name' => $people[$i]['country']);
>>
>>>>> $this->Person->saveAll($data);
>>>>> }
>>
>>>>> However, the third person is not saved and no error is reported. I
>>>>> would expect for CakePHP to get the id of Belgium and save the third
>>>>> person with this id in the countries_id field. Obviously I do not
>>>>> understand the associations completely yet. Please help.
>>
>>>>> Thanks!
>>
>>>>> Here is My SQL log if you need it:
>>
>>>>> Query Affected Num. rows Took (ms) Actions
>>>>> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
>>>>> `Country`.`name` = 'Belgium' 1 1 1
>>
>>>>> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
>>>>> `Country`.`name` = 'Belgium' 1 1 1
>>
>>>>> INSERT INTO `countries` (`name`) VALUES ('Belgium') 1 1 1
>>>>> SELECT COUNT(*) AS `count` FROM `people` AS `Person` WHERE
>>>>> `Person`.`id` = 1 1 1 2 maybe slow
>>
>>>>> INSERT INTO `people` (`id`, `age`, `countries_id`) VALUES (1, 23, 1) 1
>>>>> 1 1
>>>>> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
>>>>> `Country`.`name` = 'Austria' 1 1 1
>>
>>>>> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
>>>>> `Country`.`name` = 'Austria' 1 1 1
>>
>>>>> INSERT INTO `countries` (`name`) VALUES ('Austria') 1 1 1
>>>>> SELECT COUNT(*) AS `count` FROM `people` AS `Person` WHERE
>>>>> `Person`.`id` = 2 1 1 1
>>
>>>>> INSERT INTO `people` (`id`, `age`, `countries_id`) VALUES (2, 12, 2) 1
>>>>> 1 1
>>>>> SELECT COUNT(*) AS `count` FROM `countries` AS `Country` WHERE
>>>>> `Country`.`name` = 'Belgium' 1 1 1
>>
>>>>> --
>>>>> Our newest site for the community: CakePHP Video Tutorials
>>
>>>> http://tv.cakephp.org> Check out the new CakePHP Questions sitehttp://ask.cakephp.organdhelp
>>
>>>> others with their CakePHP related questions.
>>
>>>>> To unsubscribe from this group, send email to
>>>>> cake-php+unsubscribe@googlegroups.com For more options, visit this group
>>
>>>> athttp://groups.google.com/group/cake-php
>>
>>>> --
>>>> --
>>>> Lep pozdrav, Tilen Majerlehttp://majerle.eu
>>
>>> --
>>> Our newest site for the community: CakePHP Video Tutorialshttp://tv.cakephp.org
>>> Check out the new CakePHP Questions sitehttp://ask.cakephp.organd help others with their CakePHP related questions.
>>
>>> To unsubscribe from this group, send email to
>>> cake-php+unsubscribe@googlegroups.com For more options, visit this group athttp://groups.google.com/group/cake-php
>
> --
> Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
> Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.
>
>
> To unsubscribe from this group, send email to
> cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

--
Our newest site for the community: CakePHP Video Tutorials http://tv.cakephp.org
Check out the new CakePHP Questions site http://ask.cakephp.org and help others with their CakePHP related questions.


To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php

No comments: