Cakephp Helpers in Views and $this - cakephp

I'm trying to determine what the best standard is for using helpers in views whether is should be
echo $form->input();
or
echo $this->Form->input();
In the CakePHP manual ver 1.2 the Helper class is accessed by the helper object directly, whereas in the 1.3 book the helper object is accessed through the View.
Does this matter?
Leo

It really only matters because of the possibility of having a collision that will "wipe out" your access to the helper. Say I had a model named Form and decided to do something like this in my view after getting many records.
foreach ($forms as $form) {
echo $form['Form']['name'] . '<br/>';
}
See what happened there? I accidentally just overwrote the $form variable, basically losing my FormHelper.
The standard is to now access all helpers via $this in the view.

Related

Cakephp View Helper

Whenever I'm displaying a user's name in my view file, I use:
echo $user['User']['name'];
The users table also has a 'company_name' field. If the user has a company name listed (in most cases, but not all), I would like to display their company name (and if they do not, I want to use the 'name' field). The code would look something like:
if(isset($user['User']['company_name']) && $user['User']['company_name'] != '') {
echo $user['User']['company_name'];
} else {
echo $user['User']['name'];
}
What is the proper way to handle this throughout multiple view files? Should I create a helper for it?
Being that this particular use case is such a small bit of presentation logic it would make more sense to me to build this within the scope of an Element rather than a Helper.
Now if at some point down the road (or now even) you decide that there is more functionality that you would like to extend similar to this presentation logic, perhaps in the form of a UsersHelper that would define various pieces of display logic relevant to the current user, then it would be wise to encapsulate that functionality within a Helper.
Here's a good example to get you started with Elements:
// In src/Template/Element/name_display.ctp
if(isset($user['User']['company_name']) && $user['User']['company_name'] != '') {
echo $user['User']['company_name'];
} else {
echo $user['User']['name'];
}
In your view file:
// Echo this wherever you need the name displayed
echo $this->element('name_display', [
'user' => $user // Sets the $user viewVar in the element
]);
And for sake of completeness, in your controller:
$this->set('user', $user);
In your spare time it would be a good idea just to check out the manual on some of the core helpers that are included with Cake to get an idea of how they are constructed to get a better idea of use cases in which you would want to create a Helper.
2.x Elements Documentation
3.x Elements Documentation
2.x Helpers Documentation
3.x Helpers Documentation
Good luck!

CakePHP model named 'Model' not working

I have a model named Model. After some frustration with its responses, I came to the conclusion that the class file is not being used.
To test this, I changed the name of the file from model.php to model_x.php and no errors were encountered.
Can someone verify to me if Model is an invalid name for an appModel class?
I am using CakePHP 2.x
Lee
The class Model is already taken
So what you should do is create another name. It's the same when using a controller and model named layout, because the Layout folder in View is already used for the layouts. So you should either come up with a clever solution with routing, or simply give it a different name.

Autoloading model on demand in codeigniter

Can I somehow omit the first line? i.e. $this->load->model('Model_name'); and autoload it when necessary?
To load a model you will use the following function:
$this->load->model('Model_name');
Once loaded, you will access your model functions using an object with the same name as your class:
$this->Model_name->function();
Lazy loading is not supported in Codeiginiter 2.1
There are a couple of options available to you
Use the 'autoload' in the config. This will always make the model available throughout the application. See here for more info
Load the model in the __construct() of your controller (if it is specific to that controller)
You don't understand the logic .
$this->load->model('Model_name') means you load it when it necessary.
or
If you find that you need a particular model globally throughout your application, you can tell CodeIgniter to auto-load it during system initialization. This is done by opening the application/config/autoload.php file and adding the model to the autoload array.

How do you perform Form validation without a model in Cakephp?

I need to perform some validation. I don't have the model in the application.
Does anyone know how to do the validation without a model?
Can you show me using a small sample or statement?
Honestly, I'd create a model just for the validation. You can create a model that doesn't use a table by adding
var $useTable = false;
And then create a validation array with rules for each field you want to validate:
var $validate = array('login' => 'alphaNumeric','email' => 'email','born' => 'date');
Then, in your controller, do something like:
$this->MyModel->set($this->data);
if($this->MyModel->validates()){
// do stuff with valid data
}
If you really, really can't use a model, then you'll have to simply loop over each value in $this->data in your controller action and validate it against a regular expression or use the Validation::[rule]() stuff, like:
if(Validation::email($someThingThatMightBeAnEmailAddress)){
// do stuff with valid email address.
}
You can perform validation of form data in CakePHP without having to create a model.php file. There are many times when I need to do this, and storing model.php files that do nothing more then validation is a poor usage of the model design pattern.
Another problem with CakePHP is that sometimes validation rules are common across multiple models. It would be nice to move validation out of the model, much in the way behaviors are to their own subfolder. That way we can re-use them or use them without a model.
Another problem with validation is that it's dependent upon the model alias. If you have a model called "Email" without a table to perform validation, then the posted form must also use "Email". If the form uses a alias different from the controller, then you have to set the action. A lot of extra steps just to do validation. You can't re-use that model again if your form uses a different model.
So here is my alternative approach.
In your controller's action that receives the posted form data. You can create a default CakePHP model, add some validation rules and then use that model for validation.
An example action might look like this;
function edit()
{
$model = ClassRegistry::init(array('class'=>'Email','table'=>false,'type'=>'Model'));
if(!empty($this->data))
{
$model->validate = array(
'subject'=>array(
'rule'=>'notEmpty',
'required'=>true
),
'message'=>array(
'rule'=>'notEmpty',
'required'=>true
)
);
if($model->save($this->data))
{
// validation was successful, but no data was actually saved
}
}
}
The key here is the creation of an automatic model by CakePHP.
$model = ClassRegistry::init(array('class'=>'Email','table'=>false,'type'=>'Model'));
The above attempts to find a model by Email in the applications model folder. When it is not found CakePHP will auto-create an in memory model for that class. Since we set the value of 'table' to false, then this should tell CakePHP that this model doesn't use a table.
This works as long as there really isn't a email.php file in the applications model folder. Once this model is created in memory. It's accessible from the built in Form help. That means validation errors will be passed correctly to the view.
Here is an example view file.
<?php echo $this->Form->create('Email',array('action'=>array('controller'=>'mycontroller','action'=>'edit'))); ?>
<?php echo $this->Form->input('subject'); ?>
<?php echo $this->Form->input('message',array('type'=>'textarea')); ?>
<?php echo $this->Form->submit(); ?>
The view will now render the validation errors from the Email model using the Form helper. This is because CakePHP class registry has saved a copy of the EMail auto model in memory that the Form helper will access.
If you want to use custom validation rules, then you will have to put the callback methods in the app_model.php file.
These methods tested in CakePHP 1.3
#ThinkingMedia's answer got me going in the right direction, but $model->save($this->data) was returning false for me unfortunately, even when the form was valid. I'm using CakePHP 2.3.9 for reference.
It turned out that even with 'table' => false parameter set, the returned$success of save() was based on a $count > 0 of the rows that were created/updated/modified. In my table-less case, this meant a $count of 0 and $success was false. I ended up blending the referenced answer with this similar question's solution to have validation work properly without a model file:
function edit()
{
$model = ClassRegistry::init(array('class'=>'YourFormName','table'=>false,'type'=>'Model'));
if($this->request-is('post'))
{
$model->validate = array(
'some_field'=>array(
'rule'=>'notEmpty',
'required'=>true
),
'another_field'=>array(
'rule'=>'notEmpty',
'required'=>true
)
);
$model->set($this->request->data)
if($model->validates($this->request->data) && empty($model->validationErrors))
{
// validation was successful, but no data was actually saved
}
}
}
Came across this question since I also had a similar issue. I have a form that needs to collect data and generate a PDF. So there is no data saving involved nor there is a maching model class. The PDF is a user contract and the user will fill the online form and the data filled will be used to generate the PDF which they must print and mail back. But I need to validate whether the fields are not empty, whether email is really an email format, and date inputs are really date inputs.
First I did without a model class then saw this quesion. Now I'm using a dummy model class to have my validations put in there since the code in controller action looks much neat.
Class Validation which is a subclass of Object is used by model class to perform validation against validation rules specified in it.
One can directly instantiate Validation class inside any controller or model and use its methods for performing validation on any data, not only inputs from forms.
I think my first question would be this: if you don't have a model...what are you validating? Typically data collection would be done to populate a model. If you're using an alternative data repository (file, web services, etc.), a model would still be the appropriate way to access and manipulate that data.
In short, in order to better answer this, I think a little more context would be helpful and maybe even necessary.

CakePHP: Passing $this->data to the View from Controller

I'm using CakePHP 1.2 and I'm just wondering if there is any side affect on passing the $this->data to the View from the Controller.
Ex:
// inside PostsController, I have this code:
$this->data['Posts'] = $this->Post->find('all');
instead of :
$posts = $this->Post->find('all');
$this->set(compact('posts'));
// inside the /posts/view, I access it like this:
<?php foreach ($this->data['Posts'] as $post) {....};?>
By doing this, I skipped the $this->set() from the controller all together. Does this violate any MVC pattern or any security issue that I might have overlook? I saw that using the Auth Component, $this->data contains the [_Token] array.
Thanks
You need to be aware of the different places that Cake Helpers automagically look for data, since that is were it makes a real difference. The Form Helper will fill in fields automatically based on the contents of $this->data. That's how form data persists when validation fails. OTOH, a <select> elements options array is automatically taken from the pluralized field name,
e.g. $form->select('Model.foo_id') will take its options from $foos if set.
As such, $this->data has its special place and shouldn't be used lightly, just as named variables have their use and shouldn't be ignored. Use both as appropriate. If you don't want to auto-set Form Helper content, set() your variables. IMHO it's also more readable to assign a variable name that hints at the data it contains. All your views operating on $this->data is less clear than one view operating on $foo and another on $bar.
In CakePHP 2.x you should use $this->request->data instead if plain $this->data, otherwise you might end up getting this error:
Indirect modification of overloaded property View::$data has no effect
$controller->data is meant for data posted to the control from view file.
$view->data is for general data.
I would avoid doing it to keep myself sane. besides you are typing more in view.
There is no good reason for setting $this->data directly except when working with forms.
Why break convention - Controller:set is there for a reason. If you want to pass data to the view for display or display logic purposes you should use the function provided instead of trying to co-opt Controller:data for unintended purposes.
Everything is easier from within CakePHP if you follow the rules and do things the expected, correct way.
In cakephp version 2.*, error occurs when you try to set data on $this->data

Resources