Basic CakePHP: Edit Post Method become Add Post Method - cakephp

Currently following the blog tutorial however my database and their variable are different.
I was looking through the "Edit Post" method and follow the step they given however they turn into "Add Post" method.
What is the reason that cause it ?
(I have set the hidden field at view pass to controller however they will show the error Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '45' for key 'PRIMARY' because they doing insert statement instead of update).
DateOfEventController.php
public function edit($id = null) {
//Retrieve from database
$post = $this->dateofevent->findByeventdateId($id);
debug($post);
//Without Id
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
//If Not Exist the id
if (!$post) {
throw new NotFoundException(__('Invalid post'));
}
//After press the submit
if ($this->request->is(array('post','put'))) {
echo "yo";
$this->dateofevent->eventDate_id = $id;
if ($this->dateofevent->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been updated.'));
// return $this->redirect(array('action' => 'index'));
}
else{$this->Session->setFlash(__('Unable to update your post.'));}
}
//Set the data same as retrieved
if (!$this->request->data) { $this->request->data = $post;}
}
edit.ctp
<?php
echo $this->Form->create('dateofevent');
//echo $this->Form->input('eventDate_id', array('type' => 'hidden'));
echo $this->Form->hidden('eventDate_id');
echo $this->Form->input('event_date',array(
'label' => 'Event Date',
'type' => 'text',
'id' => 'datepicker'));
echo $this->Form->end('Save Post');
?>
Sql Query
SQL Query: INSERT INTO fyp_seatmanagment.dateofevent
(eventDate_id, event_date, modified) VALUES (45, '2015-06-10',
'2015-06-17 10:19:45')

You're not using Cake's standard naming conventions so you need to make sure you override model attributes that Cake would normally auto-generate. Cake expects the primaryKey to be id which it uses to determine whether to insert or update a record. As you're using eventDate_id you need to tell Cake this in your model:-
class DateOfEvent extends AppModel {
public $primaryKey = 'eventDate_id';
}
Unless there is a specific reason why you can't use Cake's naming convention you should do. Using your own naming convention will create considerable more work for you and problems.
I've also noticed you're incorrectly camel casing methods and variable names in your controller that may cause problems. For example $post = $this->dateofevent->findByeventdateId($id) should be:-
$post = $this->DateOfEvent->findByEventdateId($id);

Related

Creating a Dropdown Menu from Database

I'm trying to create a Dropdown menu from the table Holidays for the column name. But I'm too dumb to make it work.
I already tried some of the things people wrote but most of them have a second database. But I only have one.
My goal is to show all the names from the Holiday name column so, if I create a new holiday, I just get the name of the date from the Dropdown menu and don't need to write it down every time.
HolidaysController.php
public function index()
{
$holidays = $this->paginate($this->Holidays);
$this->set(compact('holidays'));
$name =$this->name->find('list');
$this->set(compact('name'));
}
Holidays add.ctp
<?php
echo $this->Form->control('date', array('label' => __('Datum', true)));
echo $this->Form->control('name', ['options' => $name, 'empty' => true]);
?>
I thought he would show me now a dropdown list from the names of the holidays but i just have a normal field and get the error:
Notice (8): Undefined variable: name [APP/Template\Holidays\add.ctp, line 19]
I'm probably missing something really basic here, I'm still learning coding so if I missed any information, you need, just let me know.
EDIT:
My add function after the edit
HolidaysController
public function add()
{
$name =$this->name->find('list');
$this->set(compact('name'));
$holiday = $this->Holidays->newEntity();
if ($this->request->is('post')) {
$holiday = $this->Holidays->patchEntity($holiday, $this->request->getData());
if ($this->Holidays->save($holiday)) {
$this->Flash->success(__('Der Feiertag wurde gespeichert.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Der Feiertag wurde nicht gespeichert. Bitte, versuchen sie es erneut.'));
}
$this->set(compact('holiday'));
}
You must find and set list in your add() method, like :
public function add()
{
// your add code here .. then:
$name =$this->Holidays->find('list');
$this->set(compact('name'));
}
By default every controller method has own view template:
index() >> index.ctp
add() >> add.ctp
edit() >> edit.ctp
myCustomMethod() >> my_custom_method.ctp
// ...
EDIT:
If I add your code to function add() i get an Error: Call to a member
function find() on string.
I copy code from your question. But you must update:
from: $this->name->find('list'); to
$this->Holidays->find('list', [
'keyField' => 'name',
]);

select list association in cakephp

i am new to cake and using version 2.
i have models
hgcylinder.php
class HgCylinder extends AppModel {
//put your code here
var $name= "HgCylinder";
var $belongsTo = array('HgKeyGase');
}
hgkeygase.php
class HgKeyGase extends AppModel {
//put your code here
var $name= "HgKeyGase";
public $belongsTo = array(
'HgKeyColor' => array(
'className' => 'HgKeyColor',
'foreignKey' => 'hg_key_color_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
Controller HgCylindersController.php
<?php
class HgCylindersController extends AppController
{
var $name = "HgCylinders";
// var $scaffold;
function index()
{
$this->set('hey',$this->HgCylinder->find('all'));
}
public function edit($id = null) {
$this->HgCylinder->id = $id;
if ($this->request->is('post')) {
var_dump($this->request->data);
exit;
if ($this->HgCylinder->save($this->request->data)) {
$this->Session->setFlash(__('Cylinder has been updated successfull'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The cylinder could not be saved. Please, try again.'));
}
} else {
$this->request->data = $this->HgCylinder->read(null, $id);
}
$hg_key_gase_id = $this->HgCylinder->HgKeyGase->find('list');
$this->set(compact('hg_key_gase_id'));
}
}
?>
View : edit.ctp
<?php
echo $this->form->create('HgCylinder',array('action'=>'edit'));
echo $this->form->input('hg_key_gase_id',);
echo $this->form->input("capacityM3");
echo $this->form->input("weightEmpty");
echo $this->form->input("weightFilled");
echo $this->form->input("isFilled");
echo $this->form->end('Add');
?>
my problem is hg_key_gase_id is become select list with no options. if i changed the name to "hgKeyGas" in view and controller it shows the options from the hg_key_gases table. but on saving does not saving the value of hg_key_gase_id field in hg_cylinders table instead it stores null in this field.
second i want to know that it is necessary to have variable name passing to view from controller exactly same for as field in table.
try to stick to conventions.
so its
$hgKeyGases = $this->HgCylinder->HgKeyGase->find('list');
$this->set(compact('hgKeyGases'));
the pluralized form will be able to populate your select box (as documented in the cook book)
also use $this->Form->input() (note the capital F). $name is not necessary.
dont use read(), use find(first) instead. dont set the action (the form will post to itself by default).
and most importantly. ALWAYS respect the casing of files in your filesystem. especially if you plan on deploying on NIX systems (which are case sensitive).
so it would be HgCylinder.php and HgKeyGase.php as Model class files.
last tip: use baking (cake bake via shell console) to bake your crud files. this way you learn how its done the right way. it would have also answered your question itself by the way.
the documentation can be found here: http://book.cakephp.org/2.0/en/index.html
maybe you found an old outdated version, the 2.x one is the one you should have used.

CakePHP HABTM Form Submission

I have two tables, questions and tags, that have a HABTM relationship. When adding a question, I want to be able to specify a tag for the question (this would just be the first tag, with ability to add more tags later). The tags are pulled from their table. How can I configure my application so that when a question is added and a tag is specified, the join is reflected in the join table (questions_tags)?
Here is my question add action code :
function add() {
$tags = $this->Question->Tag->find('all');
$this->set('tags',$tags);
if (!empty($this->data)) {
$this->Question->create();
if ($this->Question->save($this->data)) {
$this->Session->setFlash(__('The question has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The question could not be saved. Please, try again.', true));
}
}
$users = $this->Question->User->find('list');
$tags = $this->Question->Tag->find('list');
$this->set(compact('users', 'tags'));
}
and here is my question add view code:
<?php
echo $this->Form->create('Question');
echo $this->Form->input('user_id',array('type' => 'hidden', 'value' => $this->Session->read('Auth.User.id')));
echo $this->Form->input('title');
echo $this->Form->input('details',array('type' => 'textarea'));
echo $this->Form->input('tag_id');
echo $this->Form->end(__('Submit', true));
?>
First make sure that your models are set up the right way. The fact that a user initially just adds one tag to your question does not change the fact that you should have a HABTM relation between the Question model and the Tag model (because you want the possibility add more tags later).
If your $this->data array is build according to the following schema:
$this->data = array(
'Question' => array(
'name' => 'Trick question'
),
'Tag' => array(
'Tag' => array(1,2,3)
)
);
Then a $this->Question->save() will save the Question data as well as the related Tag data (in this case Question 'Trick Question' with Tags with the id 1, 2 and 3).
Maybe take one step back and bake your Models, Views and Controllers for these two models (again) and see what Cake makes out of it. If I'm correct you'll just need a $this->Form->input('Tag') somewhere in your form (and if that not fills in the right data automatically you want to fill the options parameter with the result of $this->Question->Tag->find('list')).
if you have a single tag for a question, it's not HABTM. it has to be one to one or one to many relation.
in your questions model you can define property belongsTo:
class Question extends AppModel {
var $name = 'Question';
var $belongsTo = array(
'Tag' => array(
'className' => 'Tag',
'foreignKey' => 'tag_id'
)
);
}
Something like this.
here is a link describing how to set HABTM
HABTM

How to create a ground of checkbox in Cakephp? and how to store it?

I have a field called Hobbies, I wish to store all the hobbies selected by the user to be stored in the database as CSV. How can I do this in Cakephp?
Paste into view (ie, views/users/add.ctp)
<?php echo $form->create('User', array('action' => 'add')) ?>
<?php echo $form->input('User.hobbies', array('type' => 'select',
'multiple' => 'checkbox',
'options' => array('sports' => 'sports',
'movies' => 'movies',
'games' => 'games'))) ?>
<?php echo $form->end('Save') ?>
Paste into Users controller (just a standard save method, nothing special here)
function add() {
if(!empty($this->data)) {
if($this->User->saveAll($this->data, array('validate' => 'first'))) {
$this->Session->setFlash('User saved successfully');
} else {
$this->Session->setFlash('User failed to save');
}
}
}
Paste into User model
function beforeValidate() {
// join hobbies into csv
if(!empty($this->data['User']['hobbies'])) {
$this->data['User']['hobbies'] = join(',', $this->data['User']['hobbies']);
}
return true;
}
Notes:
If you need to separate the hobbies back out when reading the User model, you could use the "afterFind" callback or check out the Serializable Behaviour http://blog.matsimitsu.nl/code/206/serializeable-behavior-for-cakephp that automatically serializes and deserializes whenever you try to add or pull out an array to/from the db.
You could add the beforeValidate code to the beforeSave callback instead, just depends what kind of validation you want to perform. having the code in beforeValidate will let you do a basic notEmpty check, however in beforeSave will mean you can check individual items are present in the array.
References:
http://book.cakephp.org/view/76/Callback-Methods
http://book.cakephp.org/view/189/Automagic-Form-Elements

Display custom validation messages using CakePHP $validate array

I'm trying to display custom messages like, 'this field should not be empty' or 'name not null' using the $validate array in the model. I have two controllers, main and users.
The index file of the main controller has the login and registration views. The action part of the login and register functions are in the user_controller. If the login and register function validate, they are redirected to the home page of the main controller,else they remain in the index page itself.
I want the validation messages to be displayed in the index page itself. But those messages appear only if there is a separate view file for login and register,i.e, /views/forms/register.ctp and /views/forms/login.ctp exist.
Is there a way to display those validation messages without having a separate view file for those functions? I have given my code below.Someone guide me please.
Model Class:
<?php
class User extends AppModel {
var $name = 'User';
var $components=array('Auth');
var $validate = array(
'name' => array(
'rule' => 'notEmpty',
'message' =>'Name cannot be null.'
),
'password' => array(
'rule' => 'notEmpty'
),
'email_id' => array(
'rule' => 'notEmpty'
)
);
function registerUser($data)
{
if (!empty($data))
{
$this->data['User']['name']=$data['User']['name'];
$this->data['User']['email_id']=$data['User']['email_id'];
$this->data['User']['password']=$data['User']['password'];
$existingUsers= $this->find('all');
foreach($existingUsers as $existingUser):
if($this->data['User']['email_id']==$existingUser['User']['email_id']){
return 0;
}
else{
$this->save($this->data);
$this->data['User']['id']= $this->find('all',array('fields' => array('User.id'),
'order' => 'User.id DESC'
));
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
endforeach;
}
}
function loginUser($data)
{
$this->data['User']['email_id']=$data['User']['email_id'];
$this->data['User']['password']=$data['User']['password'];
$login=$this->find('all');
foreach($login as $form):
if($this->data['User']['email_id']==$form['User']['email_id'] && $this->data['User']['password']==$form['User']['password'])
{
$this->data['User']['id']= $this->find('all',array('fields' => array('User.id'),
'conditions'=>array('User.email_id'=> $this->data['User']['email_id'],'User.password'=>$this->data['User']['password'])
));
$userId=$this->data['User']['id'][0]['User']['id'];
return $userId;
}
endforeach;
}
}
?>
Controller Class:
<?php
class UsersController extends AppController
{
var $name = 'Users';
var $uses=array('Form','User','Attribute','Result');
var $helpers=array('Html','Ajax','Javascript','Form');
function register()
{
$this->Session->write('userId',$this->User->registerUser($this->data));
$this->User->data=$this->data;
if (!$this->User->validates())
{
$this->Session->setFlash('Please enter valid inputs');
$this->redirect('/main' );
return;
}
if($this->Session->read('userId')==0){
$this->Session->setFlash('You are already a registerd member.Log in your account');
$this->redirect('/main');
}
else{
$this->Session->setFlash('User account created');
$this->redirect('/main/home');
}
}
function login()
{
//$userId=$this->User->loginUser($this->data);
$this->Session->write('userId',$this->User->loginUser($this->data));
$this->User->data=$this->data;
if (!$this->User->validates())
{
$this->Session->setFlash('Please enter valid inputs');
$this->redirect('/main' );
return;
}
if($this->Session->read('userId')>0){
$this->Session->setFlash('Login Successful');
$this->redirect('/main/home');
break;
}
else{
$this->Session->setFlash('Username and password do not match.');
$this->redirect('/main');
}
}
}
?>
View Template:
<!-- File: /views/main/index.ctp-->
<div id="register">
<h3>Register</h3>
<?php
echo $form->create('User',array('action'=>'register'));
echo $form->input('name');
echo $form->input('email_id');
echo $form->input('password');
echo $form->end('Register');
?>
</div>
<div id="login">
<h3>Login</h3>
<?php
echo $form->create('User',array('action'=>'login'));
echo $form->input('email_id');
echo $form->input('password');
echo $form->end('Login');
?>
</div>
I think you're going about it the wrong way. You're doing way too much in the model, and you're also doing almost the same thing in the controller again after the fact. That's not good. Overall, honestly, the code is quite a mess for something so simple.
A huge WTF flag pops up here:
$existingUsers= $this->find('all');
foreach($existingUsers as $existingUser):
if($this->data['User']['email_id']==$existingUser['User']['email_id']){
You're seriously retrieving all users from the database (potentially a hugely expensive task) and then go through them one by one to compare a single field?!
You can simply define a validation rule that says 'email_id' should be unique, and Cake will automatically ask the database if the 'email_id' already exists. http://book.cakephp.org/view/472/isUnique
About your specific problem: You have the same form field twice on the same page, password and email_id fields for the same User model. There's no way for Cake to know which instance of the two fields is supposed to get the error message, they both have the same name. Also, I don't think you want to use validation error messages for the login form, you just want to see if the login was successful or not. Use Session::flash() instead to display an error message for a failed login, it's not field specific.
Take the login and register methods out of your model, they don't belong there. Only specify proper validation rules for the email, name and password fields in the model, they will automatically be checked upon calling $this->User->save() in the controller.
Don't hand-validate anything, unless there's really no way to do it with Cake validation rules (not the case here). If the built-in validation rules don't satisfy what you need to do, you can even make custom rules. http://book.cakephp.org/view/150/Custom-Validation-Rules
PS: Components are not for models. I think you need to learn more about the basics of Cake before continuing: http://book.cakephp.org/view/218/Tutorials-Examples
But, if you want to see your error messages that comes from the validate array you should access the $this->modelName->invalidFields() which will return you the fields that didn't pass the validation and the message that you have setted for them...

Resources