CakePHP: How to disable email online validation? - cakephp

I'm using CakePHP 2.3.8 and the email rule validates that the email has a valid host name or so. This is great, I like this feature, but it does not make things easy when testing on a local server, specially if it's offline.
Is there anyway to disable this very quick? A config variable maybe?
EDIT: Not going model by model changing the rule variable, but a global config variable.

You just need to remove second arguments from rule-- Like you defined as
'rule' => array('email', true)
This should be as-
'rule' => array('email')
after edit on question
You can do this by dynamic validation. But the easy approach will be unset email validation thus you are on development environment..
AppModel.php
public function beforeValidate(){
if$this->validate['email'](){
unset($this->validate['email']);
}
// now, If you really need to check email add dynamic rule for email field here.
}

Related

CakePHP use Library inside Model

Our site is multilanguage (for a client). But instead of translate words like "login" in the PO files, we need to extract them from our translations table in the database. This is a client requirement.
I did research in which way I could make a function that is accessible from anywhere (view, controller, etc.). I concluded that the best way was to make a custom Library, because it said it could be used anywhere.
But I can't use it in my model, it gives me the error that I can't use ClientnameLibrary::translate('login') on that place. I added the line App::uses('ClientnameLibrary', 'Lib'); in my model, and tried this in the validate part:
'lastname' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => ClientnameLibrary::translate('lastname_validation_error'),
),
),
Is there a way I can use my custom Library in a model? And if not, what is the best way to translate the validation messages in my model (from the database)?
This is the code I use in controllers/views:
App::uses('ClientnameLibrary', 'Lib'); //include at top of file
echo ClientnameLibrary::translate('login'); //to get translated word from database
Save the DB translations in a po file when the translations change. Without caching, reading every translation with a new query is silly, so you will have to cache it any way. So just turn the DB content into a po file and use the standard translation functions from CakePHP?
Check how the i18n shell extracts the translation strings into pot (NOT po) files. You could probably override the shell to update your DB with the required identifiers as well.

Passing variable from view to controller with POST in CakePHP

I'm new to CakePHP, and am trying to do some blog-like exercise, then I ran into some problems.
See have a Model called Post, then under the PostsController I generated a view action for checking a single blog post. What I want is to allow the users to be able to add comment to the post in the Posts/view page instead of being redirected to a new Comments/add page. To do that I need to tell my CommentsController which post the user is commenting on. So wrote this in my /app/View/Posts/view.ctp:
<?php
echo $this->Form->create('Comment', array('controller' => 'comments', 'action' => 'add');
echo $this->Form->input('content', array('row' => '3'));
// this is the line I'm not sure about
echo $this->Form->input('post_id', array('default' => $post['Post']['id'], 'type' => 'hidden'));
echo $this->Form->end('Submit');
?>
Now this solution will send the value of $post['Post']['id'] to the add action in CommentsController in the form of $this->request->data['post_id'], but call me anal, I worry that whether this is the correct, or "professional" way to do this, since one can easily make the hidden field visible by altering some attributes with "inspect element' inside of any modern browser, leaving not necessarily potential security vulnerabilities, but something I personally don't feel comfortable with. So please, if anyone's worked with CakePHP before, share some experience with me on that.
First you can shorten that line to:
$this->Form->hidden('post_id', array('value' => $post['Post']['id']));
To prevent form tampering use the security component. It will:
Restricting which HTTP methods your application accepts.
CSRF protection.
Form tampering protection
Requiring that SSL be used.
Limiting cross controller communication.
Also I would validate that any data that is processed is valid. So you might want to check that the post exists and is public as well for example to prevent people can add comments to a non-public post. The same concept applies for everything: Never trust any input, not user nor API. Always validate the data and circumstances.

Cakephp Plugin model name prefix

I have a plugin with the name 'Admin' and my methods are like index, add etc. Since I want to apply unique model names and controller names (for ACL implementation), I prefixed all controllers and models with the plugin name (please see cakephp plugin model/controller cache issue with main model/controller). After that, Im facing the following problems. I have a table called users and I am using cakephp2.0.
1) I have to access the url with domain.com/admin/admin_users/index or admin/content/admin_index, instead I want to access by admin/users/index or admin/content/index. How to set this in routes in a general way so that it will be applied to all ?
2) In view, it is showing undefined index User (I have baked the views before). Everything is coming as AdminUser. After setting public $alias = 'User' this issue has been solved. Is this correct ?
3) In controller, I have to change "$this->User->some var/fn " to $this->AdminUser->some var/function is all places. Any way to solve this ?
Anything wrong with plugin name giving as admin (I have not set admin routing) ?
You can safely name your plugin admin, this is by no means a reserved word. However, Cake doesn't take plugin names into account when parsing model / controller names, so AdminUsersController and AdminUser are actually going to be seen as classes belonging to some abstract AdminUser. So to solve all your problems using only Cake magic you'd have to actually name them User and UsersController, and hope these names don't clash. If this is not an option, you can provide some of your own magic to solve these things:
1) How to alias a controller is one of the route configuration examples in the cookbook
2) Yups, if you want to use "User" as a key, that is correct.
3) Not really using only Cake magic, because the $uses variable doesn't support aliasing. You can, however, take advantage of the new lazy-loading of 2.0, by doing something like this in your AdminUsersController:
<?php
public function __get($name) {
// Note, the isset triggers lazy-loading. Check out Controller::__isset()
// if you want to see how that works.
if ($name == 'User' && isset($this->AdminUser)) {
// Assign to admin user here to bypass the next time
return ($this->User = $this->AdminUser);
}
// Delegate to CakePHP's magic getter
return parent::__get($name);
}

CakePHP - Customizing Message

Is there any way to set a layout to my messages in my model code?
Here is my model:
var $validate = array(
'email' => array(
'rule' => array('email', true),
'message' => 'Please supply a valid email address.'
)
);
This can be done with CakePHP. However, you have your concerns mixed up. The Model is there for data gathering, manipulation and massaging. The layout of the data is under the responsibilities of the View. In CakePHP specifically the Form Helper.
For more info about how to specify your own layout for a data validation message check out:
http://book.cakephp.org/view/1639/options-inputDefaults
They provide a pretty great code sample on exactly how to do this.
I also highly suggest you read through the whole book. It will prove invaluable.
Edit: Answer after clarification from comment
You would create an element and put it in app/views/elements. Should name the file using normal Cake conventions. Let's go with flash_error.
You would set this up to be your HTML that you want displayed. To make sure your message is displayed simply add this bit of PHP wherever is appropriate
<?php echo $message; ?>
That's step 1.
Step 2 is in your $this->setFlash() call pass the appropriate parameters. So your new calls would look like this with the element we named above:
$this->setFlash($message, 'flash_error');
Now your setFlash messages will use the layout defined in step 1. Wanna different layout? Just create a new element and pass the new element name.
The setFlash() method has 2 more parameters that come in handy (particularly if you want to have multiple flash() messages on the same page). Another link to the book:
http://book.cakephp.org/view/1313/setFlash

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.

Resources