Saving single data into a database - CakePHP - cakephp

I tried to do on all things I think and I dont know how to do it. I have read the book of Cake...
I dont know how to add this value in 1 column in my database.
When I'm adding 'Task' I want to add my 'name' in column 'created_by'.
Code from Add Task:
public function add()
{
$task = $this->Tasks->newEntity();
if ($this->request->is('post')) {
$task = $this->Tasks->patchEntity($task, $this->request->data);
if ($this->Tasks->save($task)) {
$this->Flash->success(__('The task has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The task could not be saved. Please, try again.'));
}
}
$users = $this->Tasks->Users->find('list', ['limit' => 200]);
$this->set(compact('task', 'users'));
$this->set('_serialize', ['task']);
}
When I will write
echo $this->Auth->user('name');
die();
I have got my name which is 'Mariusz'.
Now I want to add it into column 'created_by'. I think I need to change this line:
$task = $this->Tasks->patchEntity($task, $this->request->data);
But I dont know how. In book of Cake there is information
$articles->patchEntity($article, $this->request->data(), [
'validate' => 'custom',
'associated' => ['Tags', 'Comments.Users' => ['validate' => 'signup']]
]);
But I dont think its good.
I have created the relation
User -> has_many -> Task
Task -> belongs_To -> User

Please can you try following code :
$data['name']=$this->Auth->user('name');
$task = $this->Tasks->patchEntity($task, $data);
if ($this->Tasks->save($task)) {

Related

Create new hasMany children from parent controller

I have two controllers "Events" and "Activities" and both have many "Attendees".
$this->hasMany('Attendees')
->setClassName('Attendees')
->setForeignKey('foreign_id')
->setConditions(array('Attendees.class' => 'Activity'))
->setDependent(true);
I am using a class and a foreign_id in my Attendees table to link them. I would like to create addAttendee() function in my ActivitiesController for example to add a new attendee, but I am not sure how to proceed.
public function addAttendee($id = null)
{
$activity = $this->Activities->get($id, ['contain' => ['Venues', 'Contacts']]);
if ($this->request->is('post'))
{
??
}
$this->set(compact('activity'));
}
I found some documentation on saving with association but not on creating new association.
You can create a new Attendee entity then link it to your $activity.
$data = ['first_name' => 'blah', 'last_name' => ... fields]);
$attendee = $this->Attendee->newEntity($data);
$this->Attendee->link($activity, [$attendee]);
source: https://api.cakephp.org/4.2/class-Cake.ORM.Association.HasMany.html#link()
I proceed this way. It's working but not sure if it's the right way to proceed ??
public function addAttendee($id)
{
$activity = $this->Activities->get($id, ['contain' => ['Venues', 'Contacts']]);
$attendee = $this->Activities->Attendees->newEmptyEntity();
if ($this->request->is('post'))
{
$attendee = $this->Activities->Attendees->patchEntity($attendee, $this->request->getData() + ['class' => 'retreat', 'foreign_id' => $id]);
if ($this->Activities->Attendees->save($attendee))
{
$this->Flash->success(__('The attendee has been saved.'));
return $this->redirect(['action' => 'view', $id]);
}
$this->Flash->error(__('The attendee could not be saved. Please, try again.'));
}
$this->set(compact('activity', 'attendee'));
}

Saving data using where clause

I would like to be able to save data while providing a where clause.
I have the following code:
$game = $this->Games->newEntity();
if ($this->request->is('post')) {
$game = $this->Games->patchEntity($game, $this->request->data);
if ($this->Games->save($game)) {
$this->Flash->success(__('The game has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The game could not be saved. Please, try again.'));
}
}
I tried this, but it didn't work:
$this->Games->save($game)->innerJoinWith('Leagues', function ($q) use($s) {
return $q->where(['Leagues.user_id' => $s]);
}
)
I suspect having to do a find with a where clause and patch the request data to it?
$game = $this->Games->find()->innerJoinWith('Leagues', function ($q) {
return $q->where(['Leagues.user_id' => $this->Auth->user('id')]);
})
->where(['Games.id' => $id])
->first();
if(! count($game)){
$this->Flash->error(__('The game could not be found.'));
return $this->redirect(['action' => 'index']);
}
if ($this->request->is('post')) {
$game = $this->Games->patchEntity($game, $this->request->data);
if ($this->Games->save($game)) {
$this->Flash->success(__('The game has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The game could not be saved. Please, try again.'));
}
}
Anything simpler?
There is no such saving syntax, retrieving the proper entity in beforehand is the correct way to go, and there isn't really a "simpler" way - however there surely is room for optimization.
Personally I'd use finders to DRY things up, ie create a finder on the GamesTable that restricts things to specific league users:
public function findForLeagueUser(\Cake\ORM\Query $query, array $options)
{
if (!isset($options['id'])) {
throw new \InvalidArgumentException('The `id` option is invalid or missing.');
}
return $query
->innerJoinWith('Leagues', function (\Cake\ORM\Query $query) use ($options) {
return $query->where([
$this->Leagues->aliasField('user_id') => $options['id']
]);
});
}
and combine things in the controller action:
$game = $this->Games
->find('forLeagueUser', ['id' => $this->Auth->user('id')])
->where(['Games.id' => $id])
->first();
You could also use firstOrFail() instead, which throws an exception if the record cannot be found, this is what Table::get() does internally too.
And you could reduce things even further by using a dynamic finder for the games id:
$game = $this->Games
->findById($id)
->find('forLeagueUser', ['id' => $this->Auth->user('id')])
->first();
See also
Cookbook > Database Access & ORM > Retrieving Data & ... > Using Finders to Load Data
Cookbook > Database Access & ORM > Retrieving Data & ... > Custom Finder Methods
Cookbook > Database Access & ORM > Retrieving Data & Results Sets > Dynamic Finders
API > \Cake\Datasource\QueryTrait::firstOrFail()

Can't pass an entity as an parameter to another action in the same controller in CakePHP 3.2

While adding a new book into the DB I want to have separate actions for patching the request in a new entity and for saving that entity. The action for patching request into new entity returns this entity to another method.
The code is like this:
public function bookAdder($book = [])
{
if ($this->Books->save($book)) {
$this->Flash->success(__('The book has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The book could not be saved. Please, try again.'));
return $this->redirect(['action' => 'add']);
}
}
public function add()
{
$user_id = $this->request->session()->read('Auth.User.id');
$book = $this->Books->newEntity();
if ($this->request->is('post')) {
$book = $this->Books->patchEntity($book, $this->request->data);
$book->set(array('user_id' => "$user_id"));
return $this->redirect(['action' => 'bookAdder', $book]);
}
$users = $this->Books->Users->find('list', ['limit' => 200]);
$this->set(compact('book', 'users'));
$this->set('_serialize', ['book']);
}
While saving a test record, I am getting this error:
Error: A route matching "/books/book-adder/{ "title": "cc", "writer":
"cc", "edition": "cc", "course": "cc", "description": "cc", "price":
2, "user_id": "1"}" could not be found.
Error screenshot Here
I also tried public function bookAdder($book){ }
but still no success.
Is there any way to solve this issue? Thanks in advance!
Multiple Functions !
Are you doing some practice for making multiple functions ? That's
great if you make your function reusable and more readable.
But what you are doing here is adding some complexity for nothing. When you redirect to bookAdder function you would generate url something like this:
book-adder/%7B%0A%20%20%20%20"name"%3A%20"abc"%2C%0A%20%20%20%20"user_id"%3A%20"1"%0A%7D
And you are passing entity as function parameter. And obviously that routing error occur.
So you really don't need multiple function here at least for things you are doing.
Make it simple:
public function add()
{
$user_id = $this->request->session()->read('Auth.User.id');
$book = $this->Books->newEntity();
if ($this->request->is('post')) {
$book = $this->Books->patchEntity($book, $this->request->data);
$book->set(array('user_id' => "$user_id"));
if ($this->Books->save($book)) {
$this->Flash->success(__('The book has been saved.'));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__('The book could not be saved. Please, try again.'));
return $this->redirect(['action' => 'add']);
}
}
$users = $this->Books->Users->find('list', ['limit' => 200]);
$this->set(compact('book', 'users'));
$this->set('_serialize', ['book']);
}
If you really need entity from another function program flow should be something like this:
makeEntity function:
public function makeEntity($book = null,$requestData = []) {
$book = $this->Books->patchEntity($book, $requestData);
return $book;
}
Add function:
public function add()
{
$user_id = $this->request->session()->read('Auth.User.id');
$book = $this->Books->newEntity();
if ($this->request->is('post')) {
$book = $this->makeEntity($book, $this->request->data);
$book->set(array('user_id' => "$user_id"));
return $this->redirect(['action' => 'bookAdder', $book]);
}
$users = $this->Books->Users->find('list', ['limit' => 200]);
$this->set(compact('book', 'users'));
$this->set('_serialize', ['book']);
}
And which doesn't make much differences.

on editing inserting a new row instead of updating the current row in cakephp 2x

I m having trouble in updating the student profile form,after i gave the user_id to the student profile.Every time when i try to edit the form, on saving it provide new id to the existing user. I don't know where I'm getting wrong. Plz help.Thanks in Advance.
Here is my add and edit function in Student Profiles controller:
public function add() {
if ($this->request->is('post')) {
$this->StudentProfile->create();
$data = $this->request->data;
$data['StudentProfile']['user_id'] = $this->Auth->user('id');
// code implemented below
//$this->loadModel('User');
if ($this->StudentProfile->save($data)) {
//Update user here if Profile saved successfully
//$this->StudentProfile->id = $this->Auth->user('id');
$this->Session->setFlash(__('Your account profile has been created'));
$this->redirect(array('controller' => 'studentprofiles', 'action' => 'index'));
}else{
$this->Session->setFlash(__('Your Profile was saved, but an error has occurred while updating the Users table'));
//Email your self the user ID here or something ??
}
}
$h=array(
'fields' => array('Height.height'),
'recrusive' => 0
);
$this->loadModel('Height');
$height = $this->Height->find('list',$h);
$this->set(compact('height'));
}
public function edit($id = null) {
if (!$this->StudentProfile->exists($id)) {
throw new NotFoundException(__('Invalid student profile'));
}
if ($this->request->is(array('post', 'put'))) {
$this->request->data['StudentProfile']['user_id'] = $this->Auth- >user('id');
// code implemented below
// $this->loadModel('User');
if ($this->StudentProfile->save($this->request->data)) {
//$this->StudentProfile->id = $this->Auth->user('id');
$this->Session->setFlash(__('The student profile has been saved.'), 'default', array('class' => 'alert alert-success'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The student profile could not be saved. Please, try again.'), 'default', array('class' => 'alert alert-danger'));
}
} else {
$options = array('conditions' => array('StudentProfile.' . $this- >StudentProfile->primaryKey => $id));
$this->request->data = $this->StudentProfile->find('first', $options);
}
$h=array(
'fields' => array('Height.height'),
'recrusive' => 0
);
$this->loadModel('Height');
$height = $this->Height->find('list',$h);
$this->set(compact('height'));
}
Can't believe I'm replying to my own question . Well In case anyone have the same above problem,the solution is just add the following code after this-
$this->request->data['StudentProfile']['user_id'] = $this->Auth->user('id');
// add this code to avoiding giving new id to existing user on edit:
$this->request->data['StudentProfile']['id'] = $id;
A better way of saving edited information is to set the ID on the model before the save like so
$this->StudentProfile->id = $this->Auth->user('id');
If you initiate a save after setting the above then the row will be edited and not add a new row.

Failure to Update record CakePHP

I am currently trying to update my user before sending an email which will have a confirm link with a resetkey for the user to reset the password.
The problem is that the user is not updating whilst the key is being generated.
the code can be seen hereunder
public function forgotpassword() {
if ($this->request->is('post')) {
$mail = $this->request->data['ContactDetail']['email'];
$data = $this->User->find('first', array('conditions' => array('ContactDetail.email' => $mail)));
if (!$data) {
$message = __('No Such E-mail address registerd with us ');
$this->Session->setFlash($message);
} else {
$data['User']['resetkey'] = Security::hash(mt_rand(),'md5',true);
debug($data);
if ($this->User->saveAssociated($data)) {
$this->Session->setFlash(__('The user has been saved.'));
}
else {
$this->Session->setFlash(__('The user could not be updated. Please, try again.'));
}
$key = $data['User']['resetkey'];
$id = $data['User']['id'];
$mail = $data['ContactDetail']['email'];
$email = new CakeEmail('default');
$email->to($mail);
$email->from("xxxx#yahoo.com");
$email->emailFormat('html');
$email->subject('Password reset instructions from');
$email->viewVars(array('key' => $key, 'id' => $id, 'rand' => mt_rand()));
$email->template('reset');
if ($email->send('reset')) {
$message = __('Please check your email for reset instructions.');
$this->Session->setFlash($message);
} else {
$message = __('Something went wrong with activation mail. Please try later.');
$this->Session->setFlash($message);
}
}
$this->redirect('/');
}
}
I checked the execution log of MySQL but all I am seeing are selects no updates or even inserts.
This is probably something very dumb but I can't understand why it doesn't say anything.
Why do you use saveAssociated method for update single field?
Something like this would be easier:
$this->User->updateAll(
array( 'User.resetkey' => $hash ),
array( 'User.id' => $userId )
);
try using
$this->User->saveMany($data, array('deep' => true));
When saving. Also
if (empty($data)) {...
Might be a safer way to go
This will work for you-
$this->User->id = $data['User']['id'];
if ($this->User->save($data)) {
$this->Session->setFlash(__('The user has been saved.'));
}else {
$this->Session->setFlash(__('The user could not be updated. Please, try again.'));
}
Try to debug like:
if ($this->User->saveAssociated($data)) {
$this->Session->setFlash(__('The user has been saved.'));
}
else {
$this->Session->setFlash(__('The user could not be updated. Please, try again.'));
}
$log=$this->User->getDataSource()->getLog(false, false);
echo "<pre>";print_r($log);exit;

Resources