I am learning having a problem insert records in Tables with association "hasOne", When I insert into the Table Users it should also insert in Table Customers but is only working with Users. I've looked people had similar problems but i really don't know what I am doing wrong. I appreciate any help
My User Model
class UsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->hasOne('Customers', [
'foreignKey' => 'user_id'
]);
}
My Customer Model
class CustomersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('customers');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id'
]);
}
My request->getData()
[
'Users' => [
'Customers' => [
'first_name' => 'name',
'last_name' => 'test',
'gender' => 'Male',
'postcode' => '1234'
],
'username' => 'user1',
'password' => '12134'
],
'done' => '1'
]
My Action
public function addCustomer()
{
//Configure::write('debug',true);
// debug($this->request->getData());
$usersTable = TableRegistry::get('Users');
$user = $usersTable->newEntity();
if ($this->request->is('post')) {
$user = $usersTable->patchEntity($user,$this->request->getData(),['associated' => ['Customers']]);
if ($usersTable->save($user)) {
$this->Flash->success('The Customer has been saved.');
return $this->redirect(['action' => 'addCustomer']);
}
$this->Flash->error('Unable to add the Customer.');
}
}
I though that your User model can not have user_id as its foreinKey
Related
I am using CakeDC Users and as part of the registration I would like the registrant to choose some checkbox values that correspond to another Model in the application. I am able to get the form to load the choices just fine, but I am unable to get it to save to the join table even though I have added all of the associations and accessibilities where it would seem relevant. The form is displaying in a similar way to other areas where I am saving the same type of association with a different model.
TypesTable.php
{
public function initialize(array $config): void
{
//$this->addBehavior('Timestamp');
$this->setDisplayField('type');
$this->setPrimaryKey('id');
$this->belongsToMany('Words');
$this->belongsToMany('Users');
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
'joinType' => 'INNER',
]);
}```
UsersTable.php (in the plugin folders)
```class UsersTable extends Table
{
...
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('username');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->addBehavior('CakeDC/Users.Register');
$this->addBehavior('CakeDC/Users.Password');
$this->addBehavior('CakeDC/Users.Social');
$this->addBehavior('CakeDC/Users.LinkSocial');
$this->addBehavior('CakeDC/Users.AuthFinder');
$this->hasMany('SocialAccounts', [
'foreignKey' => 'user_id',
'className' => 'CakeDC/Users.SocialAccounts',
]);
$this->hasMany('Types', [
'foreignKey' => 'user_id', 'targetForeignKey' => 'type_id',
'joinTable' => 'types_users']);
}```
In order for a "belongsToMany" association to work in this instance, both *Table.php files must have the relations listed as belongsToMany. Don't forget to make the field accessible in the Entities as well.
One also needs to place the associated array in the patchEntity function in the RegisterBehavior.php file.
UserTable.php (in CakeDC users)
public function initialize(array $config): void
{
...
$this->belongsToMany('Types', [
'foreignKey' => 'user_id', 'targetForeignKey' => 'type_id',
'joinTable' => 'types_users']);
}
TypesTable.php (in app)
class TypesTable extends Table
{
public function initialize(array $config): void
{
....
$this->belongsToMany('Users');
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
'joinType' => 'INNER',
]);
}
RegisterBehavior.php
$user = $this->_table->patchEntity(
$user,
$data,
['validate' => $validator ?: $this->getRegisterValidators($options), 'associated' => ['Types']]
);
I am new to php frameworks and I've started to learn cakephp few days ago, but even after reading cakephp cookbook about saving belongsToMany associations I still don't know how to implement it in my situation.
I have three tables:
clients:
id | firstname | lastname | phone | email
interests:
id | text | comment | status_id | created_at
clients_interests:
client_id | interest_id
Models and entities were baked so I don't think it's something wrong there, but here is the code:
ClientsTable.php
class ClientsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('clients');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsToMany('Interests', [
'foreignKey' => 'client_id',
'targetForeignKey' => 'interest_id',
'joinTable' => 'clients_interests'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmptyString('id', 'create');
$validator
->scalar('firstname')
->maxLength('firstname', 64)
->requirePresence('firstname', 'create')
->allowEmptyString('firstname', false);
$validator
->scalar('middlename')
->maxLength('middlename', 64)
->allowEmptyString('middlename');
$validator
->scalar('lastname')
->maxLength('lastname', 64)
->requirePresence('lastname', 'create')
->allowEmptyString('lastname', false);
$validator
->scalar('phone')
->maxLength('phone', 24)
->requirePresence('phone', 'create')
->allowEmptyString('phone', false)
->add('phone', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']);
$validator
->email('email')
->allowEmptyString('email');
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['email']));
$rules->add($rules->isUnique(['phone']));
return $rules;
}
}
InterestsTable.php
class InterestsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('interests');
$this->setDisplayField('id');
$this->setPrimaryKey('id');
$this->belongsTo('Statuses', [
'foreignKey' => 'status_id',
'joinType' => 'INNER'
]);
$this->belongsToMany('Clients', [
'foreignKey' => 'interest_id',
'targetForeignKey' => 'client_id',
'joinTable' => 'clients_interests'
]);
}
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmptyString('id', 'create');
$validator
->scalar('text')
->maxLength('text', 128)
->requirePresence('text', 'create')
->allowEmptyString('text', false);
$validator
->scalar('comment')
->maxLength('comment', 128)
->allowEmptyString('comment');
$validator
->date('created_at')
->requirePresence('created_at', 'create')
->allowEmptyDate('created_at', false);
return $validator;
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['status_id'], 'Statuses'));
return $rules;
}
public function getAll($id)
{
$connection = ConnectionManager::get('default');
$results = $connection
->execute('SELECT i.*, s.name status_name, s.classname status_classname FROM interests i INNER JOIN clients_interests ci ON ci.interest_id=i.id AND ci.client_id=:client_id INNER JOIN statuses s ON i.status_id=s.id ORDER BY created_at DESC;', ['client_id' => $id])
->fetchAll('assoc');
return $results;
}
}
ClientsInterestsTable.php
class ClientsInterestsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('clients_interests');
$this->setDisplayField('client_id');
$this->setPrimaryKey(['client_id', 'interest_id']);
$this->belongsTo('Clients', [
'foreignKey' => 'client_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Interests', [
'foreignKey' => 'interest_id',
'joinType' => 'INNER'
]);
}
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['client_id'], 'Clients'));
$rules->add($rules->existsIn(['interest_id'], 'Interests'));
return $rules;
}
}
Client entity - Client.php
class Client extends Entity
{
protected $_accessible = [
'firstname' => true,
'middlename' => true,
'lastname' => true,
'phone' => true,
'email' => true
];
}
Interest entity - Interest.php
class Interest extends Entity
{
protected $_accessible = [
'text' => true,
'comment' => true,
'status_id' => true,
'created_at' => true,
'clients_interest' => true,
'status' => true
];
}
ClientsInterests entity - ClientsInterests.php
class ClientsInterest extends Entity
{
protected $_accessible = [
'client' => true,
'interest' => true
];
}
And then in my controller I get all the data from a form. Interest entity after patchEntity() gets all its data besides client data for joinTable. And after save method new interest in interests table is created but there is no new row in clients_interests table. I've tried a lot of things from stackoverflow but it didn't work because I can't understand the mechanism of saving associated data even after reading the manual. Could anyone explain me in simple words how to save belongsToMany associated data?
Here is the code of my save method in InterestsController.php:
public function add()
{
$this->request->allowMethod(['ajax', 'post']);
$this->response->withDisabledCache();
$interest = $this->Interests->newEntity();
$interest = $this->Interests->patchEntity($interest, $this->request->getData(),
['associated'=>['Clients._joinData']]
);
if($this->Interests->save($interest)) {
$result = ['error' => null, 'error_text' => 'SUCCESSFUL'];
} else {
$result = ['error' => null, 'error_text' => 'ERRORS ERRORS ERRORS'];
}
$result = ['error' => null, 'error_text' => 'ERRORS ERRORS ERRORS'];
$this->set('result', $result);
$this->set('_serialize', ['result']);
}
And in my template I use this input for getting client_id:
<?php echo $this->Form->control('clients.0.client_id', ['hidden', 'type'=>'text','id'=>'client-id', 'class'=>'form-control']); ?>
Request data looks like this: request data
And Interest entity after patchEntity() looks like this: Interest entity
If you want to add an 'interest', I think your request data should look differently.
Here is an example, but sorry, I haven't tested it, it's made so you get the idea : you have to tell CakePHP you want to create a Interest entity, and inside add a Client information (just like in the "Converting BelongsToMany Data" in "Saving Data" of book.cakephp.org/3.0/en/orm/saving-data.html).
$data = [
_csrfToken => "...",
'interests' => [
'text' => 'texttext',
'comment' => '',
'created_at' => '2019-01-10',
'status_id' => 2,
'clients' => [
'_ids' => [0],
]
];
Personally, I learnt a lot looking at the requests generated through the Form Helper from the automatically baked templates.
I am creating a tool that allows to generate dynamic forms. There are several tables in question:
Form [the Form master table]
FormField [JoinTable to Field]
Field [the fields available for inclusion in Form]
FieldValidation [The table containing relation data between the FormField and the Validation option]
Validation [The available Validation options]
For the FieldValidation - this could in effect be a hasMany from Field, but I am unsure of whether I need to set up this relation from the Field table, or from the join table FieldValidation. The Validation table literally just includes the definitions for the validation options. This does not actually need to be a belongsToMany relation from the FormField/Field table. A hasMany is fine if that simplifies things.
Is this even possible?
Form -> [FormField] -> Field -> [FieldValidation] -> Validation
I have never done this before - so if there is a better way to approach this, I am all ears. My main concern is being able to select Form, contain Field's, and then contain the Validation for each field selected. Obviously, multiple validation rules can be selected per field.
A little late, but I did resolve this issue.
ERD Diagram of Physical Relationship in DB
Model: UsersTable
class UsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('users');
$this->displayField('username');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Projects', [
'foreignKey' => 'user_id',
'targetForeignKey' => 'project_id',
'through' => 'ProjectsUsers'
]);
$this->hasMany('ProjectsUsers', [
'foreignKey' => 'user_id'
]);
}
}
Model: ProjectsTable
class ProjectsTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('projects');
$this->displayField('name');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsToMany('Users', [
'foreignKey' => 'project_id',
'targetForeignKey' => 'user_id',
'through' => 'ProjectsUsers'
]);
$this->hasMany('ProjectsUsers', [
'foreignKey' => 'project_id'
]);
}
}
Model: ProjectsUsersTable - this is the model for the JOIN table (through)
class ProjectsUsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('projects_users');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Users', [
'foreignKey' => 'user_id'
]);
$this->belongsTo('Projects', [
'foreignKey' => 'project_id'
]);
$this->hasMany('ProjectsUsersPermissions', [
'foreignKey' => 'projects_users_id'
]);
}
}
Model: ProjectsUsersPermissions - this is the relation to the join table
class ProjectsUsersPermissionsTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('projects_users_permissions');
$this->displayField('role');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('ProjectsUsers', [
'foreignKey' => 'projects_users_id'
]);
}
}
Then the controller find action
$this->Projects->find()
->where(
[
'Projects.id' => $projectId
]
)
->contain(
[
'Users', // through belongsToMany
'ProjectsUsers' => [ // through hasMany [joinTableModel]
'ProjectsUsersPermissions' // through hasMany
]
]
)
->first();
This may be overkill for this scenario, and it is not my exact implementation - so don't think I am just doing unnecessary joins/contains. In my real life scenario, this works perfectly.
Hope this helps someone!
I'm trying set association in cakephp
my db
two model:
namespace App\Model\Table;
class UsersTable extends Table {
public function initialize(array $config)
{
$this->hasOne('Scores',[
'className' => 'Scores',
'conditions' => '',
'dependent' => true
]);
}
}
and
class ScoresTable extends Table {
//var $name = 'Scores';
public final $connection = ConnectionManager::get('default');
public function initialize(array $config)
{
$this->belongTo('Users',
'foreignKey' => 'user_code_Student',
'joinType' => 'INNER',
);
}
}
function index in controller:
public function index() {
//$connection = ConnectionManager::get('default');
$modelUser = $this->loadModel('Users');
$dataUser = $modelUser->find('all')->contain(['Score']);
/*$data = array(
/*'listUser' => $modelUser->find('all', array(
'conditions' => array('email LIKE' => '%gmail.com'),
'limit' => 2
)),$connection
->execute('SELECT * FROM users WHERE email like :email limit 3', ['email' => '%gmail.com'])
->fetchAll('assoc')
'listUser' => $this->paginate($modelUser->find('all')),
'title' => 'Demo MVC'
);*/
$data = array(
'listUser' => $dataUser
);
$this->set('data', $data);
}
When I run it, the following error is shown: Users is not associated with Score
Can you help me?
Your relation looks like invalid.Try this:
users table
public function initialize(array $config)
{
$this->hasOne('Scores',[
'foreignKey' => 'user_code_Student'
]);
}
scores table
public function initialize(array $config)
{
$this->belongsTo('Users', // you wrote here belongTo that should be belongsTo instead
'foreignKey' => 'user_code_Student', // is user_code_Student foreignKey ???
'joinType' => 'INNER',
);
}
And also change this:
$dataUser = $modelUser->find('all')->contain(['Scores']); // not Score
I wanna make assoc with Locations via locations_ways join table what contain order and point (start / middle / end) of way.
In end I wanna get assoc
locations - all locations
end_location ONLY end location
start_location ONLY start location
Now for end_location and start_location I have array what containe one record. But I dont want write some like this: $way->end_location[0]->name;
How to process it?
class WaysTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Locations', [
'through' => 'LocationsWays',
'sort' => ['LocationsWays.position ASC'],
]);
$this->belongsToMany('LocationStartPoint', [
'className' => 'Locations',
'foreignKey' => 'way_id',
'targetForeignKey' => 'location_id',
'through' => 'LocationsWays',
'conditions' => ['LocationsWays.point' => 'start'],
]);
$this->belongsToMany('LocationEndPoint', [
'className' => 'Locations',
'foreignKey' => 'way_id',
'targetForeignKey' => 'location_id',
'through' => 'LocationsWays',
'conditions' => ['LocationsWays.point' => 'end'],
]);
}
}
class LocationsTable extends Table
{
public function initialize(array $config)
{
$this->belongsToMany('Ways', [
'through' => 'LocationsWays',
]);
}
}
class LocationsWaysTable extends Table
{
public function initialize(array $config)
{
$this->belongsTo('Ways', [
]);
$this->belongsTo('Locations', [
]);
}
}
Fetching func.
public function getWayById($id, $locale = 'uk')
{
I18n::locale($locale);
$item = $this->find()
->where(['Ways.id' => $id])
->contain(['Locations', 'LocationStartPoint', 'LocationEndPoint'])
->cache(function (Query $q) {
return 'way-' . md5(serialize($q->clause('where')));
}, 'orm')
->first();
return $item;
}