I'm new to CakePHP. Now I'm struggeling with a problem I can't find an answer for on the internet for the past hour. I'm trying to save the following array to my database:
array(
'Product' => array(
'product_id' => '77adfe7754esda71r1999431',
'supplier_id' => 'zalando_it',
'product_name' => 'Sweater',
'price_new' => '68.97',
'affiliate_url' => 'http://example.com'
),
'Image' => array(
'image' => '99988_DP.jpg'
)
)
Now this is an example of my ERD: https://www.dropbox.com/s/1zvfqfxes53gibb/example.png
I connected the tables correctly in the Models (by using belongsTo and hasMany variables), but still I think I'm doing something wrong.... Cause when I use the function $this->Supplier->saveAssociated($data) in the Model "Feed" it doesn't save anything.
And when I use $this->Supplier->Product->saveAssociated($data) it saves the Product and it creates records in the Image table with the product_id but leaves the "image" field empty.
Only if I use $this->Supplier->Product->Image->saveAssociated($data) it saves everything correctly. But isn't that wrong? Cause to my opinion it doesn't seem right to go through each model ($this->Supplier->Product->Image...) to save all tables.... Or am I wrong?
Assuming Product hasMany Image, your data needs to be like this (notice "Image" is numbered, so there can be more than one):
array(
'Product' => array(
'product_id' => '77adfe7754esda71r1999431',
'supplier_id' => 'zalando_it',
'product_name' => 'Sweater',
'price_new' => '68.97',
'affiliate_url' => 'http://example.com'
),
'Image' => array(
0 => array(
'image' => '99988_DP.jpg'
)
)
)
Related
I have two Models, namely Product and ProductSpecification which have the following relations in place:
(Product Model)
public $hasMany = array(
'ProductSpecification' => array(
'className' => 'ProductSpecification',
'foreignKey' => 'product_id',
'dependent' => true
)
);
and
(ProductSpecification Model)
public $belongsTo = array(
'Product' => array(
'className' => 'Product',
'foreignKey' => 'product_id'
)
);
Using the CakePHP Form helper I post ProductSpecification data and then I use the saveAll method (or saveAssociated, I've tried both) to save the data. debug($this->request->data) gives me the following output after POSTing:
array(
'Product' => array(
'id' => '2'
),
'ProductSpecification' => array(
'title' => 'test',
'step' => '1',
'position' => '1'
)
)
This is great, right..? Now, the line after the debug I use the following code to save (I've also tried saveAssociated):
if($this->Product->saveAll($this->request->data))
For some odd reason this saves three(!) empty rows in my ProductSpecification table, with only the product_id field (and id) set; the fields title, step and position are empty. Exactly the same behavior happens when I run saveAssociated. What am I doing wrong?
I'm running CakePHP 2.x.
Your save data should look more like this:-
array(
'Product' => array(
'id' => '2'
),
'ProductSpecification' => array(
array(
'title' => 'test',
'step' => '1',
'position' => '1'
)
)
);
The values for ProductSpecification need to be passed as a numerically indexed array for the hasMany relationship.
Also, make sure you use saveAssociated() rather than saveAll() as you are passing associated data so there is no need to use the wrapper method (which should be avoided wherever possible).
Right, so my data returns in the following way,
(int) 0 => array(
'MODEL-XX' => array(
//DATA HERE
'xxs_id' => '11',
'aas_id' => '44',
'vvs_id' => '2'
),
'xxs' => array(
'id' => '11',
'customername' => 'XX name here'
),
'aas' => array(
'id' => '44',
'clientname' => 'aa name here',
'xxs_id' => '11'
),
'vvs' => array(
'id' => '2',
'start' => '1405296000',
'end' => '1405814400',
'users_id' => '1'
)
This works fine, but I want to know how to link my users table to this model. So the details of each user for my VV model would become apart of the data. My MODEL-XX does not have any links with my users table so the place I need to call in the users details are held with my VV model.
I have been looking into this but have not been able to find a simple easy method for doing this?
I was thinking that this would be doable with my model, so I opened my my XX model and added the following within my '$belongsTo' section,
'Users' => array(
'className' => 'Users',
'foreignKey' => 'vvs.users_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
So is there a easy method for linking data like this?
Please give me time, if I have not explained myself right or not enough data, please tell me and let me fix or explain better.
Thanks,
Either set your recusive higher:
$this->MODEL-XX->recursive = 1; //or 2
Or and this should be your prefered way to go, start using the containable behaviour:
http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html
In your appModel:
public $actsAs = array('Containable');
Then try this find:
$this->MODEL-XX->recursive = -1;
$data = $this-MODEL-XX>find(
'all', array(
'conditions' => $conditions,
'contain' => array('xxs', 'aas', 'vvs', 'user')
)
);
I might be 'vvs.user' but I forgot what is used for deeper models
I have a database:
Companies | Users | Files
- ID - ID - ID
- company_id - user_id
So for my models:
Company hasmany User
User belongsto Company & hasmany File
File belongsto User
How can I list al the files belonging to a company? Without the user and company data? So a single array listing files.
I could fetch all the user IDs followed by a query in File searching with these IDs. But I was wondering, is there a best practice cakePHP way?
I'm fairly new to cake.
Thanks
As far as I know it's not possible to get company files without any user or company data, but you can limit the data by using the Containable behaviour. For example, if you want to get files that belong to a company in the company controller you could use this:
$users = $this->Company->User->find('all', array(
'conditions' => array('User.company_id' => $id),
'fields' => array('id', 'company_id'),
'contain' => array('File'),
));
The result ($users) would look something like this:
array(
0 => array(
'User' => array(
'company_id' => '75',
'id' => '51'
),
'File' => array(
0 => array(
'id' => '399',
'user_id' => '51',
...
),
1 => array(
'id' => '337',
'user_id' => '51',
...
)
...
)
)
1 => array(
'User' => array(
'company_id' => '75',
'id' => '65'
),
'File' => array(
0 => array(
'id' => '450',
'user_id' => '65',
...
),
...
)
)
)
You can then get an array of files using the Hash utility.
$files = Hash::extract($users, '{n}.File.{n}');
Which will give you something like this:
array(
0 => array(
'id' => '399',
'user_id' => '51',
...
),
1 => array(
'id' => '337',
'user_id' => '51',
...
),
3 => array(
'id' => '450',
'user_id' => '65',
...
),
...
)
Don't forget to enable the behaviour. I suggest you do it in your app model by adding the following line:
public $actsAs = array('Containable');
CakePHP will not help you on this and even if want to write mysql query you cant do this by using files table only until and unless you will add company_id in files table.
I am using Cakephp 2.2.4 and I need to retrive a list of Lead that belongs to the user (id = 106).
The result of the query is:
array(
(int) 0 => array(
'Lead' => array(
'id' => '6',
'user_id' => '106',
'date' => '2012-12-31 22:15:23',
'ip' => '127.0.0.1',
'service_id' => '1',
'location' => 'Rome',
'message' => 'Message Message',
'telephone' => null,
'active' => null
),
'User' => array(
'id' => '106',
'email' => 'daje#daje.it',
'pwd' => '0433c024cb08be13000d59a347e640482843f46f177e95749dc6599c259617fd3491dcb940b47693cbbc7f65a2cc5ef62deca2e600c1be133ad54170f7d1fbd1',
'role_id' => '3',
'active' => '1'
),
'Service' => array(
'id' => '1',
'name' => 'Primo servizio'
),
'Estimate' => array(
(int) 0 => array(
'id' => '1',
'lead_id' => '6',
'user_id' => '106'
)
)
)
)
It looks good but I need to count the Estimates (Estimate array), I would like to retrive the number of the estimates, and not the array with all the fields (of estimates table).
How can i do it?
I need :
Lead array as it shown
User array as it shown
Service array as it shown
Estimate (only the total number of the estimates... in this case 1)
The find is very simple:
$options = array('conditions' => array('User.id' => 106));
debug($this->Lead->find('all', $options));
Try something like this, not 100% sure it'll work but worth a go if not I'd advise trawling the cakephp docs for retrieving your data:
$options = array(
'fields' => array('Lead.*', 'User.*', 'Service.*', 'count(Estimate.id)'),
'conditions' => array('User.id' => 106)
);
Without diving too far into the internals of the Cake ORM, assuming you don't need to do this immediately at query time, couldn't you just get the count of the estimate array programmatically after the fetch?
http://php.net/manual/en/function.count.php
$leads = $this->Lead->find('all',$options);
foreach($leads as $lead){
//get the number of estimates for every lead result
$lead_num = count($lead['Estimate']);
}
Alternatively, you could manually write a join query for this one fetch and execute it using the Cake Model class's query method. Without knowing the specifics of your table schema and model relations its hard to give specifics about how to structure the query, but this shouldn't be too difficult by just look at your table spec and extracting a sql COUNT statement for every Estimate with given id.
I created an install script to add two fields to customer using the script below.
But I get this error.
Source model "" not found for attribute "dob_month"
Am I not defining the model in the first line? What does that actually do? What is the best way to fix this?
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttribute('customer', 'dob_month', array(
'label' => 'Month',
'type' => 'varchar',
'input' => 'dropdown',
'visible' => true,
'required' => true,
'position' => 1,
'option' => array (
'value' => array (
'optionone' => array('January'),
'optiontwo' => array('February'),
'optionthree' => array('March'),
'optionfour' => array('April'),
'optionfive' => array('May'),
'optionsix' => array('June'),
'optionseven' => array('July'),
'optioneight' => array('August'),
'optionnine' => array('September'),
'optionten' => array('October'),
'optioneleven' => array('November'),
'optiontwelve' => array('December')
)
)
));
$setup->addAttribute('customer', 'dob_year', array (
'label' => 'Year',
'type' => 'varchar',
'input' => 'text',
'visible' => true,
'required' => true,
'position' => 1
));
If you've already added the attribute, you'll want to use updateAttribute to set the source model value in the eav_attribute table.
<?php
$installer = Mage::getResourceModel('customer/setup','default_setup');
/***
* When working with EAV entities it's important to use their module's setup class.
* See Mage_Customer_Model_Resource_Setup::_prepareValues() to understand why.
*/
$installer->startSetup();
$installer->updateAttribute(
'customer',
'dob_month',
'source_model', //a.o.t. 'source'
'whatever/source_model',
)
$installer->endSetup();
If not, then you can use addAttribute(), which - due to the Mage_Eav setup class' _prepareValues() method - requires an alias for the source_model column as indicated in Alexei's answer ('source' as opposed to 'source_model').
Source model is used when Magento needs to know possible values of your attribute. For example, when rendering dropdown for your attribute. So no, you're not defining it. If my memory doesn't fail me, you can do that by adding 'source' to attribute definition array. Something like:
...
'source' => 'eav/entity_attribute_source_table'
...
That will mean that all your possible options are stored in tables eav_attribute_option and eav_attribute_option. So if your options from install script are successfully added to these tables, that should work. Or you can write your own source model, which I prefer more.