CakePHP HABTM JoinTable w/Extra Field - cakephp

So I have a customers table, a contacts table, and a contacts_customers join table, which also has contact_type_id field which maps to a contact_type table. I have used the information linked to from CakePHP update extra field on HABTM join table in an attempt to come up with a solution, but it's only partly working. I changed the add() method in the ContactCustomersController to
$this->ContactsCustomer->Contact->save($this->data);
$this->ContactsCustomer->create();
if ($this->ContactsCustomer->save($this->data,
array('validate' => 'first'))) {
$this->Session->setFlash(__('The contacts customer has been saved', true));
$this->redirect(array('controller' => 'contacts_customers', 'action' => 'index'));
} else {
$this->Session->setFlash(__('The contacts customer could not be saved. Please, try again.', true));
}
Note the two-part save; this is because using the saveAll() method of the ContactsCustomer model was just out and out failing with no indication of the problem (all that showed up in the SQL log on the resulting page was a BEGIN immediately followed by a ROLLBACK). My assumption here was that this was due to the foreign key constraint between the contacts table and the contacts_customers table, so I opted for the two-part save.
In any event, there are no errors reported in the current code, but the end result is that the appropriate information is saved in the contacts table, but nothing is saved in the contacts_customers join table. The data posted appears to be appropriate according to the FireBug log data:
_method POST
data[Contact][address_1] asdsad
data[Contact][address_2]
data[Contact][city] asdasd
data[Contact][email] jb#sc.net
data[Contact][fax]
data[Contact][first_name] Joe
data[Contact][last_name] Blow
data[Contact][mobile_phon...
data[Contact][office_phon... sdfsdfdf
data[Contact][postal_code... 121212
data[Contact][state] asdas
data[Contact][title]
data[ContactsCustomer][ContactType]
data[ContactsCustomer][ContactType][] 1
data[ContactsCustomer][ContactType][] 2
data[ContactsCustomer][ContactType][] 3
data[ContactsCustomer][Customer] 1
What have I done incorrectly here? Many thanks to any assistance offered!
Relevant model data:
contact.php
var $hasMany = array(
'ContactsCustomer'
);
contact_types.php
var $hasMany = array(
'ContactsCustomer'
);
customer.php
var $hasMany = array(
'ContactsCustomer'
);
contacts_customer.php
var $belongsTo = array(
'Contact', 'ContactType', 'Customer'
);

haven't tested that yet, but I believe $this->data might have been modified by the first save. Just use an extra variable to hold that data.

Related

CakePHP 3 Find All Contain NULL data, displays nothing?

UPDATE
This is the join from the SQL after all the selects,
FROM users Users
LEFT JOIN userinfos Userinfos ON Userinfos.id = (Users.userinfo_id)
INNER JOIN offices Offices ON Offices.id = (Userinfos.office_id)
ok, I have a database (MySQL) setup with CakePHP 3 the users table has extended information held within another table.
This other table is also extended with an office / address information however this is set to NULL by default, so I want to include it in a 'contain' call but dose not return the user data when its empty?
So this is what I use currently,
$UsersTable->find('all')
->contain(['Userinfos','Userinfos.Offices'])
->toArray();
But, Offices (office_id field in table Usersinfos) is not always set, however I still want it to return all the users even if they don't have an office set.
So I have tried,
$UsersTable->find('all')
->contain([
'Userinfos',
'Userinfos.Offices'
])
->where(['Userinfos.office_id IS' => NULL])
->toArray();
Also,
$UsersTable->find('all')
->contain([
'Userinfos',
'Userinfos.Offices' =>
function($q) {
return $q->where(['Userinfos.office_id IS' => NULL]);
}
])
->toArray();
The $UsersTable var is set to
$UsersTable = TableRegistry::get('Users');
If I remove the Userinfos.Offices from the contain condition, then it returns all my current users. However, how can I call in this extra data/information so I have access to the Office information, e.g location name if that is set?
*I may not have explain myself clearly, please let me know if there is anything I can explain better, thanks.
In cakePhp3.x in default when you bake a Model the join table is set to INNER JOIN. You would need to modify the model associations. You need to set the association to LEFT JOIN.
In your case if you look at 'UserinfosTable' in src/model/UserinfosTable make sure you are 'LEFT JOIN' ing the 'User' table or you can completely remove the 'joinType' because in default cakephp sets the Contain to 'LEFT JOIN'
class UserinfosTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Userinfos', [
'foreignKey' => 'office_id',
'joinType' => 'LEFT'
]);
}
}
Try adding the IS NULL clause as a value instead of a key/value pair :
ex:
$UsersTable->find('all')->where(['Userinfos.office_id IS NULL'])
This is the correct way to do NOT NULL (null is just isNull(
->where(function ($exp, $q) {
return $exp->isNotNull('office_id');
});

CakePHP: Save data in two models

In CakePHP I have two models: Clients & Tickets. A client can have many tickets and a ticket can only have 1 client.
When adding a new ticket I want to automatically create a new client by only entering a name. So the form would be:
Name = "Name client" >> Name should be save in Client table en new client_ID in Ticket table
Info = Ticket information >> Save in Ticket table.
"Save"
I'm not sure how this works. I have associations in the model and tried to saveAll but there is no data stored in the Client table. And how do I get the ID in the Ticket table?
Hope someone can point me in the right direction. I've searched for other answers but cant seem to find a solution. Is saveAll the right way to do this?
You should set a php condition before insert values into the table, the sql request 4 exemple return the numbers of repetition of the same ticket_id so if the returned value is greater than 1 the request can't execute else the request insert the values
The function to count number of rows : mysql_num_rows('request');
You can use the callback methods.
If you have defined your relation in the Ticket model with belongsTo Client, it will be accessible from that model.
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id',
),
);
So, if you want to make a new client before saving the ticket, you can do:
public function beforeSave ($options = array()) {
$this->data['Client']['name'] = $someVar;
$this->Client->save($this->data);
$this->data[$this->alias]['client_id'] = $this->Client->getInsertID();
return true;
}

CakePHP, find() with table alias

I want to copy 4 tables, deep associated:
Test->Scale->Question->Option
into
TestResult->ScaleResult->QuestionResult->OptionResult
In TestResult and OptionResult I want to add some new columns and also I need to have id of each 'has many' table to put it into each of 'belongs to' table.
So when I use find() I want to add aliases to result returned by Cake.
Yes, that is possible. You can provide the alias in the $hasMany, $belongsTo, etc.
public $hasMany = array(
'ImagesAlias' => array(
'className' => 'Image',
'foreignKey' => 'car_id'
)
);
You can read everything about it in the documentation

CakePHP 2.0 pagination and sum on hasMany-associated model

Project hasMany Comments
Payment (id, project_id, value, date)
I want to include in my index view a column equal to the sum of payments per project. I want to be able to sort by this field.
I've found some similiar problems here but neither of them concerns pagination.
My current (wrong) solution:
$this->paginate = array('Project' => array(
'conditions' => array('Project.archived =' => $archive),
'order' => 'Project.start_date DESC',
'contain' => array(
'Payment' => array(
'fields' => array('SUM(Payment.value) as Project__value_sum'),
'group' => array('Payment.project_id'),
)
)
));
$data = $this->paginate('Project');
$this->set('projects', $data);
$this->set('archive', $archive);
Seems like you'll probably want to do an afterSave on the Payment model.
Within the afterSave function, you run some MySQL that totals the payments (using MySQL SUM()) for the related Project, and store it in Project.payment_total.
Then, you can easily sort by that field, and it keeps you from having to run complex MySQL on every page, since it will only run when necessary (ie when there's a new or changed payment)

CakePHP - Retrieving and working with data from different tables

I'm sorry, I am a newbie in CakePHP and I am a little bit confused in this subject, let me explain:
I have a relationship between two tables. One of the table is Dose and the other is tank. So, one Tank belongs to a Dose. A Dose has many Tanks. The table schema is:
CREATE TABLE `doses` (
`id` INT(10) NOT NULL AUTO_INCREMENT,
`dose` INT(5) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
In my Tank view I have the following code:
<?php echo $form->input('dose_id', array('class'=>'input', 'label' => ''));?>
Each 'dose' (field) from Dose table correspond to a value, such as 200, 300, and so forth. I need to use these numbers to calculate others numbers before to insert into my database (table tank). For instance, my code in tanks_controllers:
$t_u = $this->data['Tank']['tipo_uso_id'];
if( $t_u == '1'){
$this->data['Tank']['producao_adubo_diaria'] = $this->data['Tank']['dose_id'] * 0.10;
.
.
.
However, it is bringing to me the ID of the Dose and not the value (dose field). Where can I set up this to bring me the correct data (dose)? I tried to set up this way in my model:
'Dose' => array(
'className' => 'Dose',
'foreignKey' => 'dose_id',
'conditions' => '',
'fields' => 'dose',
'order' => ''
)
It did not work.
I appreciate your time helping me.
Thanks in advance.
it is bringing to me the ID of the Dose and not the value (dose field). Where can I set up this to bring me the correct data (dose)?
You need to get it from the db (model), not from the view. So you need to do a find(). If you are new to Cake, you should read the cookbook first to see how it works.
What does $form->input('dose_id') produce? A dropdown? If so; by default cake will produce a dropdown with the value containing (dose_)id, and the text you see as the value of $displayField(usually name/title).
To do this; if I understand you, you would need to first query doses for all the values and store the result in an array using the dose value as the key AND the value, rather than the id as you normally would. You would then be able to access the actual dose value from $this->data.
$doseArray=array();
$doses = $this->Dose->find('all');
foreach($doses['Dose'] as $k => $v) {
$doseArray[$v] = $v;
}
perhaps. Seems a bit redundant so I might be off.

Resources