Cakephp profile view looking for the wrong controller - php

I have a function that is used to edit a previously existing userprofile here is the controller
class PeoplesController extends AppController
{
public $name = "peoples";
public $helpers = array('Html', 'form', 'Js');
public $components = array('RequestHandler');
public function viewPerson($id = NULL) {
$this->set('person', $this->people->read(NULL, $id));
}
public function editPerson($id = NULL)
{
if(empty($this->data)) {
$this->data = $this->people->read(NULL, $id);
}
else {
if($this->people->save($this->data)) {
$this->Session-setFlash('The profile has been updated');
$this->redirect(array('action'=>'viewPerson', $id));
}
}
}
}
the view outputs a form prepopulated with the previous data
<h2>Edit Profile</h2>
<?php
echo $this->Form->create('people', array('action'=>'edit'));
echo $this->Form->input('firstName');
echo $this->Form->input('secondName');
echo $this->Form->input('addressOne');
echo $this->Form->input('addressTwo');
echo $this->Form->input('city');
echo $this->Form->input('county');
echo $this->Form->input('country');
echo $this->Form->input('postCode', array(
'label' => 'Zip Code',
));
echo $this->Form->input('dob', array(
'label' => 'Date of birth',
'dateFormat' => 'DMY',
'minYear' => date('Y') - 70,
'maxYear' => date('Y') - 18,
));
echo $this->Form->input('homePhone');
echo $this->Form->input('mobilePhone');
echo $this->Form->input('email', array(
'type' => 'email'
));
$goptions = array(1 => 'Male', 2 => 'Female');
$gattributes = array('legend' => false);
echo $this->Form->radio('gender',
$goptions, $gattributes
);
echo $this->Form->input('weight');
echo $this->Form->input('height');
echo $this->Form->input('referedBy');
echo $this->Form->input('id', array('type'=>'hidden'));
echo $this->Form->end('Edit Profile');
?>
the view seems to work fine #
http://localhost/Cake/peoples/editPerson/2
but when I hit submit the url changes to
http://localhost/Cake/people/edit/2
So I changed
echo $this->Form->create('people', array('action'=>'edit'));
to
echo $this->Form->create('people', array('action'=>'editPerson'));
and I tried changing the first parameter of the create function to peoples but as this refers to the model and not the controller it should be people so i changed it back
the error i get is
Error: PeopleController could not be found.
so it is looking for the wrong controller but I am not sure where that seeking for the controller takes place.
I did use to have the controller class name uncapitalised but I follwed some advice on the conventions and capitalised it but the other previous functions I had still work fine so I dont think that is the problem
any ideas why it is changing the url and looking for the wrong controller?

The form action is being set to the edit action
Irrespective of the current url - the form action is overridden to be an explicit action:
echo $this->Form->create(
'people',
array('action'=>'edit') // <-
);
This will force the url to point at the action edit, or /people/edit/<current id>.
To prevent that, just don't specify the action, and the form will submit to the current url:
echo $this->Form->create(
'people'
);
To specify the form action url
Use the url key, not the action key which only changes the action:
echo $this->Form->create(
'people',
array(
'url'=>'/submit/here/please/' // <- or specify as an array
)
);
Avoid/correct confusing names
The convention regarding model and controller names is that models are singular, and controllers are plural:
Model |  Controller
Singular Plural
Person People
In the question this isn't the case, The model is a plural, and the controller is a confusing plural-plural (Peoples can actually be used, but it means many groups of people)
Don't define properties needlessly
In the question, there's also this:
class PeoplesController extends AppController
{
public $name = "peoples";
At best that doesn't do anything, but since the name property is defined as lower case and cake expects it to be CamelCased - that's likely to cause inconsistent behavior.
Best to follow conventions and name the controller People, the model Person and don't specify a name at all.
Don't repeat yourself
And follow conventions for a much easier ride.
The function naming is duplicates the word "person"
instead of:
public function viewPerson($id = NULL) {
(so.. the code uses person, people and peoples ?)
it's advisable to use:
public function view($id = NULL) {
After all, in the people controller - what other kind of thing is there to view (if the answer is many things, that's another thing to address)?
This makes urls simple (/peoples/view/1, instead of /peoples/viewPeople/1) as well as making the code itself easier to read (PeoplesController::view instead of PeoplesController::viewPerson).
If you don't want to change the names of the action methods, making them lower cased and underscored will at least mean the urls are consistently cased, instead of /lower_case_controller/camelCasedAction/args.

Related

how to validate form field in cakephp using model and controller

I have created a form which I need to validate using model and controller .Here is my form
index.ctp
<?php echo $this->Form->create('Contact',array('url'=>array('controller'=>'contacts','action'=>'add')));
echo $this->Form->text('name');
Model : Contact.php
class Contact extends AppModel
{
var $name = 'Contact';
var $useTable = false;
public $validate = array(
'name' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => false,
'message' => 'Letters and numbers only'
),
'between' => array(
'rule' => array('between', 5, 15),
'message' => 'Between 5 to 15 characters'
)
)
);
}
Controller : ContactsController.php
public function add()
{
$this->Contact->validates();
$this->request->data['Country']['country_name']=$this->request->data['Contact']['country'];
$this->Country->saveall($this->request->data);
$this->redirect('/Contacts/index/');
}
I am trying to do the validation by googling but it seems difficult to me so if anyone could describe the process it would be a great help .My cakephp version is 2.3.8. I just need to validate this name field , as when I click in submit it will show this message in the form.
Your controller code should be like this
The process of validation in CakePHP is like
1) as you have defined validation rules in CakePHP model public `$validates = array();`
2) when ever you do a save on particular model directly or through any association
a callback method beforeValidate for that model gets called to validate the data which is being saved.
3) once the data is validated then beforeSave callback is called after this save method is called.
4) we can also validate the form input fields in controller using $this->Model->validates() but then while saving we have to disable the beforeValidate callback by doing
$this->Model->save($data,array('validate'=>false));
Otherwise you will end validating the same data twice
your controller code should be somewhat like this.
public function add() {
// here we are checking that the request is post method
if ($this->request->is('post')) {
$this->request->data['Country']['country_name']
= $this->request->data['Contact']['country'];
// here we are saving data
if ($this->Contact->saveAll($this->request->data)) {
//here we are setting a flash message for user
$this->Session->setFlash('your record has been added','success');
$this->redirect(array('controller'=>'contacts','action' => 'index'));
} else {
//here we are setting a flash message for user for error if input are not
//validated as expected
$this->Session->setFlash('sorry we could add your record','error');
}
}
}
For more information you can always refer to http://book.cakephp.org/2.0/en/models/callback-methods.html

How to use model attribute value in behavior config Yii

I want create ImageBehavior for uploading and saving images. My behavior have two fields: imagePath and imageField. In my model i'm wrote:
public function behaviors(){
return array(
'imageBehavior' => array(
'class' => 'ImageBehavior',
'imagePath' => 'images/avatar-pics/'.$this->user->username,
'imageField' => 'avatar',
),
);
}
but this doesn't worked - i receive path -
images/avatar-pics//image.png
What a solution? Create in behavior field imageFolder and add to config 'imageFolder' => 'user->username'? Thanks.
As a suggestion:
Change the way you use your behavior and add some codes to your models. Take a look at the following example:
For example, your behavior:
class ImageBehavior extends CBehavior {
public $imagePath;
public $imageField;
public function getImagePath() {
return $this->imagePath;
}
}
Your model:
class TestModel extends CFormModel {
private $imagePath = '/home/x/y';
public function setImagePath($imagePath) {
$this->imagePath = $imagePath;
$this->attachBehaviors(array(
array(
'class' => 'ImageBehavior',
'imagePath' => $this->imagePath
)
));
}
public function init() {
$this->setImagePath($this->imagePath);
parent::init();
}
}
Now, take a look at tests and results:
$model=new TestModel();
CVarDumper::dump($model->getImagePath()); //output: /home/x/y
$model->setImagePath('/home/x/path2');
CVarDumper::dump($model->getImagePath()); //output: /home/x/path2
$model->setImagePath('/home/x/path3');
CVarDumper::dump($model->getImagePath()); //output: /home/x/path3
By this way, if you do not set any imagePath it uses model's default value. In front, each time you change the imagePath your path will change in your behavior.
Note: This is just a suggestion. By this, you can customize your setImagePath method to get the value from everywhere you want(another model, session and so on...).
Sorry for answering own question, but almost two years later build correct vision to this issue:
1) don't use line
'images/avatar-pics/'.$this->user->username
in your behavoir - it throws a notice "Trying to get property of non-object" - good application doesn't thows notices and warnings.
2) all you need is use
'images/avatar-pics/' . CHtml::value($this, 'user.username')
instead. If $this->user is null, value method returns null, so be sure that you have related user to your model.
//inside the behavior:
$this->owner->user->username;
$this->owner - it's your model. Behavior is initialized before filling attributes, and the attribute value can be get only after the initialization.

cakephp validation view issue?

First post here on stack overflow so I hope I do it right, I have searched but cannot find what I am looking for.
i am new to cakephp and fairly new to php. I was able to get up and running yesterday no problem and can send data to my database. to day I wanted to work on validation with ajax but I think I am going to leave the ajax out of it for a little while as I have a problem with the validation errors displaying.
The validation is set up for the first two form fields like this;
<?php
class people extends AppModel
{
public $name = 'people';
public $useTable = 'people';
public $validate = array(
'firstName'=>array(
'rule'=>'notEmpty',
'message'=>'Enter You First Name'
),
'secondName'=>array(
'rule'=>'notEmpty',
'message'=>'Enter Your Second/Family Name'
),
);
}?>
and it works fine if those fields are empty it wont write to the database so far so good. However, when I hit submit on the form the page refreshes, the error messages appear under the form fields but it also adds a completely new form under the previous one. here is the controller. Note: the validate_form function is from an cakephp with ajax tutorial i was following and is commented out
<?php
class peoplesController extends AppController
{
public $name = "peoples";
public $helpers = array('Html', 'form', 'Js');
public $components = array('RequestHandler');
public function index() {
if( $this->request->is('post'))
{
$data = $this->request->data;
$this->people->save($data);
}
}
/*public function validate_form() {
if ($this->RequestHandler->isAjax()) {
$this->data['people'][$this->params['form']['field']] = $this->params['form']['value'];
$this->people->set($this->data);
if ($this->people->validates()) {
$this->autoRender = FALSE;
}
else {
$error = $this->validateErrors($this->people);
$this->set('error', $error[$this->params['form']['field']]);
}
}
}*/
}
?>
and the view. note: the divs with id sending and success are also from the tutorial I was following but I dont think would have an effect on this particular issue.
<div id="success"></div>
<h2> Fill in your profile details </h2>
<?php
echo $this->Form->create('people');
echo $this->Form->input('firstName');
echo $this->Form->input('secondName');
echo $this->Form->input('addressOne');
echo $this->Form->input('addressTwo');
echo $this->Form->input('city');
echo $this->Form->input('county');
echo $this->Form->input('country');
echo $this->Form->input('postCode', array(
'label' => 'Zip Code',
));
echo $this->Form->input('dob', array(
'label' => 'Date of birth',
'dateFormat' => 'DMY',
'minYear' => date('Y') - 70,
'maxYear' => date('Y') - 18,
));
echo $this->Form->input('homePhone');
echo $this->Form->input('mobilePhone');
echo $this->Form->input('email', array(
'type' => 'email'
));
$goptions = array(1 => 'Male', 2 => 'Female');
$gattributes = array('legend' => false);
echo $this->Form->radio('gender',
$goptions, $gattributes
);
echo $this->Form->input('weight');
echo $this->Form->input('height');
$toptions = array(1 => 'Tandem', 2 => 'Solo');
$tattributes = array('legend' => false);
echo $this->Form->radio('trained',
$toptions, $tattributes
);
echo $this->Form->input('referedBy');
/*echo $this->Form->submit('submit');*/
echo $this->Js->submit('Send', array(
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->get('#sending')->effect('fadeOut'),
'update'=>'#success'
));
echo $this->Form->end();
?>
<div id="sending" style="display: none; background-color: lightgreen">Sending.... </div>
<?php
echo $this->Html->script(
'validation', FALSE);
?>
so the creation of the second identical form on the same page is my primary problem, I think it has something to do with the controller taking the first form and sending it back to the same view but I dont know how to trouble shoot this.
a second problem is that for some reason if I use
echo $this->Form->submit('submit');
instead of
echo $this->Js->submit('send', array(
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->get('sending')->effect('fadeOut'),
'update'=>'#success'));
Then I dont get my error messages anymore I instead just get a bubble that appears and says 'please fill in this field' I am sure this is a jquery issue but again I dont know how to trouble shoot it so that that bullbe does not appear and it instead shows the error messages I want
Thanks in advance
Couple things:
1) Use Caps for your classnames. So People, PeoplesController, etc
2) Don't mess with Ajax until you get the standard flow working. So go back to $this->Form->submit('submit');.
3) That "required" tooltip is HTML5. Since you set the validation to notEmpty, Cake adds HTML5 markup to make the field required. Modify your Form->create call to bypass that for now (if you need to, but it provides client-side validation which is more efficient):
$this->Form->create('People', array('novalidate' => true));
See the FormHelper docs for more info on HTML5 validations

CakePHP : Validation message not displaying

I'm new to cakePHP and I've made a simple form following some tutorial. On this html form I've used validation. Now the problem is that the validation is working but the message is not displaying what I want it to display. I tried the code below.
Model
public $validate = array(
'title' => array(
'title_required' => array(
'rule' => 'notEmpty',
'message' => 'This is required field'
),
'title_unique' => array(
'rule' => 'isUnique',
'message' => 'This should be unique title'
)
)
);
Controller
public function add() {
if ($this->request->data) {
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash('Post has been added successfully');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Error occured, Please try agan later!');
}
}
}
View
<h2>Add New Post</h2>
<?php
echo $this->Form->create('Post', array('action'=>'add'));
echo $this->Form->input('title');
echo $this->Form->input('body');
echo $this->Form->end('Create Post');
?>
The validation error which I've seen is not the message I mentioned in my controller.
That's built-in browser validation.
Since 2.3 the HTML5 required attribute will also be added to the input based on validation rules.
Your title has the notEmpty rule, so Cake is outputting
<input type="text" required="required" ..
and your browser is triggering that message.
Edit: to override this behaviour, you can do:
$this->Form->input('title', array('required'=>false));
or
$this->Form->submit('Submit', array('formnovalidate' => true));
When you submit the form, your model validation will fire.
From your code what i can see is that you havent included helpers.
public $helpers = array('Html', 'Form', 'Session');
public $components = array('Session');
Just add to your controllers and try..
Your Form-create() options are invalid, first argument is the model-name, second is for options:
<h2>Add New Post</h2>
<?php
echo $this->Form->create('Post', array('action'=>'add'));
echo $this->Form->input('title');
echo $this->Form->input('body');
echo $this->Form->end('Create Post');
?>
If the form-helper does not know which 'model' it is creating a form for, I won't check for field validation in the right place, hence, it won't output the validation errors for 'title'
[update] solution above didn't solve the problem. OP has modified the question
Some ideas:
Be sure to enable 'debug' (App/Config/core.php set Configure::write('debug', 2); Otherwise CakePHP may be using a 'cached' version of your model.
If you've named your Model incorrectly, Cake may be automatically generating a model for you, in which case your own model is never actually used, try this for debugging to see if we even 'get' to your model:
Add this to your model;
public function beforeValidate($options = array())
{
debug($this->data); exit();
}

what is the best security practice to escape my data before submitting it into my database in CodeIgniter

i have written a function for insertion into my database. i have a small doubt .
Is my below code provides good security to escape my data before submitting it into my database?
Please suggest me some solution for this if the below code does not provide good way of insetion of data into db
views.php
<? echo form_open('Setups/subject'); ?>
<? echo '<div id="level">'. $subjectname.' : '.form_input($fsubjectname); ?>
<? echo form_submit($submitbtn);
echo form_reset($resetbtn);
echo '</fieldset>'; ?>
<? echo form_close(); ?>
controller.php
class Setups extends CI_Controller {
function subject(){
$this->load->helper('form');
$this->load->model('Setupsmodel');
if($this->input->post('subsubmit')){
$this->Setupsmodel->entry_insert();
}
$data=$this->Setupsmodel->subjectsetup();
$this->load->view('admin/setups/subject_setups',$data);
}
}
model.php
class Setupsmodel extends CI_Model {
function __construct()
{
// Call the Model constructor
parent::__construct();
}
function subjectsetup()
{
$data['subjectname']='Enter Subject Name';
$data['fsubjectname']=
array('name'=>'subject_name','class'=>'input','size'=>30,'id'=>'txtsubject');
$data['formtopic']='Subject Details Form';
$data['submitbtn'] = array(
'name' => 'subsubmit',
'class' => 'button',
'value' => 'Submit',
'type' => 'submit',
'content' => 'Submit'
);
$data['resetbtn'] = array(
'name' => 'button',
'class' => 'rsetbutton',
'value' => 'Reset',
'type' => 'reset',
'content' => 'Reset'
);
return $data;
}
//--------------Insertion of new record in the table subjectdetails into the db------------
function entry_insert(){
$this->load->database();
$data=array(
'subject_name'=>$this->input->post('subject_name'));
$this->db->insert('subjectdetails',$data);
}
}
You are not filtering your user input, so it's risky. Anyways, CodeIgniter comes with a Cross Site Scripting Hack prevention filter which can either run automatically to filter all POST and COOKIE data that is encountered, or you can run it on a per item basis. By default it does not run globally since it requires a bit of processing overhead, and since you may not need it in all cases. To filter data through the XSS filter you can use following method from security class
$data = $this->security->xss_clean($data);
If you want the filter to run automatically every time it encounters POST or COOKIE data you can enable it by opening your application/config/config.php file and setting this
$config['global_xss_filtering'] = TRUE;
If you use the form validation class, it gives you the option of XSS filtering as well, using set_rules method of form validation class.
$this->form_validation->set_rules('input_name', 'input label', 'xss_clean');
So in this case, you can use in your controller
$this->form_validation->set_rules('subject_name', 'Subject Name', 'xss_clean|required');
if($this->form_validation->run())
{
$this->Setupsmodel->entry_insert();
}
There xss_clean rule will filter the input and required rule will check whether the input is empty or not, so if validation is successful then your insert method will work.

Categories