Accessing data in kohana validation - validation

i'll try and be as clear as possible.
I'm working on some form validation using the wonderful kohana framework. However i have come at a crossroads and not sure whether the way i have taken is a wise choice.
Basically, i have a date selector using several select boxes (i toyed with the idea of using javascript date pickers but the select boxes proved to be more suitable for my purpose) and a date field in a database. I wanted to concatenate these select boxes into the date field so it can be checked to make sure its valid.
protected $_rules = array(
'mydate' => array(
'not_empty' => NULL,
'date' => NULL,
),
);
Now to me, it makes most sense to include the validation in the model, since that's where the data layer is in the MVC pattern, so i decided to create some class attributes named $_rules, $_filters and $_callbacks, each set as protected and with my basic rules applied. And then a function in the model that sets up a validation object using these attributes and returning it to whatever controller is calling it, then the controller can just run the validation and the job is done.
My problem comes when i want to concat these select boxes, to me it makes most sense to make a custom filter and pass in the post data, but with the filters rules and callbacks being attributes, i can't add any variables to them. My current solution is to manually add the extra filter in when the validation setup function is being run something similar to this:
public function setupValid($post) {
$this->_filters['mydatefield'] = array(
'MyClass::MyConcat' => array($post);
);
//creates a validation object and adds all the filters rules and callbacks
}
But i don't feel this is the cleanest solution, i'm probably nit picking as the solution works the way i require it to. However i'm not sure whether a filter was ever intended to do such a thing as this, or whether this should be a callback as the callback has access to the array by default, but then again callbacks are called last, which would mean i couldn't apply any rules like, 'not_empty' (not important in this case since they are pre populated select boxes, but might be in another case)
So i guess my question is, am i using filters as they were intended to be used?
I hope i've managed to explain this clearly.
Thanks

you need to keep in mind that you should only validate fields inside the $_rules that are very important to your database or business logic.
so for example if you would try to setup other form somewhere else in your app or you would provide a restfull api for your app, validation of the field 'day_field_(that_doesnt_exists_in_the_database_and_is_used_to_privide_a_better_ux_in_this_one_form)' => array('not_empty' => NULL) will give you a hard time to do that.
so i suggest you to keep your $_rules like they are now and provide some logic to your values() method:
// MODEL:
public function values($values)
{
if ( ! empty($values['day']) && ! empty($values['month']) && ! empty($values['year']))
{
$values['mydate'] = $values['year'].'-'.$values['month'].'-'.$values['day'];
}
return parent::values($values);
}
// CONTROLLER:
if ($orm->values($form['form_array'])->check())
{
$orm->save();
}
else
{
$this->template->errors = $orm->validate()->errors('validation');
}

Related

how to use safe validation rule in yii2?

I have some doubt about safe validator.There is four case
i)I have some validation rule like below
[['name'], 'required','message' => 'You must enter name'],
In that case i want safe validation or it is enough
ii)I have some validation rule with some scenarios like below
public function scenarios()
{
return [
self::SCENARIO_INFO => ['title', 'phone'],
];
}
rule like that
[['title'], 'required','message' => 'You must enter Title','on' => 'info'],
In that case also i want safe validation or it is enough.
iii)Third case i have only public property no validation rules apply in that property,but i want that property in form user will enter.
iv)Fourth case i have only public property no validation rules apply in that property,and i don't want that property even form also,using only internally (i.e model).
In which cases the safe validation rule is must,i am new in yii so please explain easily understandable way.Thanks in advance
From the cases you have provided, it appears case# iii) will be the right situation for using safe.
For proper understanding please get your concepts clear about Safe Attributes, Massive Assignments. Refer to the links below:
http://www.yiiframework.com/doc-2.0/guide-structure-models.html#massive-assignment
http://www.yiiframework.com/doc-2.0/guide-structure-models.html#safe-attributes

MVC URL issues (Codeigniter)

I'm building a website using Codeigniter and I really like how in the MVC pattern URLs are used to reference controller methods. It seems very logical and intuitive however, I seem to be running in an array of issues with this very pattern!
So I am building an events website and currently I'm passing everything through one main Site controller, passing a number of parameters:
public function index($page = NULL, $city = NULL, $type_venue = NULL, $slug = NULL)
{
// if the page argument is empty show the homepage
if( ! ($page))
{
$page = 'home';
}
// create an array for passing to the views
$data = array(
'title_city' => $city,
'title_type_venue' => str_replace('-', ' ', $type_venue),
'locations' => $this->locations_model->load(),
'events' => $this->events_model->load($city, $type_venue, $slug),
'venues' => $this->venues_model->load($city, $slug)
);
// construct the page layout with the following views
$this->load->view('partials/head', $data);
$this->load->view('partials/header', $data);
$this->load->view('content/'.$page, $data);
$this->load->view('partials/footer');
}
This works fine, in that it loads content for the following URLs:
site.com/events/bristol/open-mic/city-varieties/another-incredible-event
site.com/events/bristol/open-mic/city-varieties/
site.com/events/bristol/open-mic/
site.com/events/bristol/
However if I want to pass anything else through this controller that isn't an event, i.e. register/user, I have to write a specific route for this!
Worth noting my routing is:
$route['(:any)'] = 'site/index/$1';
I could write separate controllers for each entity, i.e. events, venues, cities but each one would look largely like the above (correct?) in that each would need the parameters to get the data.
My question is - what is the best practice approach for developing long query strings like this? Is a single controller correct? It doesn't feel like it, but then multiple controllers would violate DRY, just because they all need so much similar data. Any help appreciated!
Avoid putting everything into a single controller; even further, in each controller, avoid putting everything into a single index function.
There is no need to write specific controllers for each function in Codeigniter - suggest you read that part again in the manual. Most of your routing will be done automatically for you if you follow the normal guidelines.
The more you try to use a single controller or function, the more you will have to add untestable, unmanageable, unscalable conditional code later.

CakePHP - Custom validation for linked model only in certain parent models

I have a generic Image model that is linked to by other models that need to have images attached. In most places the image is not required and we have fallbacks in case there is no image uploaded, but in a few particular cases I need to force the upload of an image for the form to validate, but I'm not sure how to validate that through another model. For instance, my model is something like this:
class Person extends AppModel
{
public $belongsTo = array(
'Image' => array(
'className' => 'Image',
'foreignKey' => 'image_id',
'type' => 'LEFT',
)
);
public $validate = array(
...
);
}
The Person model contains some text fields that folks have to enter as well as a redirect_url field. If a redirect is set the page logic will skip trying to load anything and will redirect directly to that URL. But, if it is not set then a bunch of other fields are required. I've got this working properly using a custom validation method in my Person model, but image_id field is not explicitly checked by the Person model since it is just a pointer to the Image model.
Can I somehow add a custom/dynamic validation rule to Image in this instance to have it check if Person.redirect_url is set? The only thing I can figure to do is to add this to my beforeSave() and basically manually check it using $this->data but I'd like to do this the "right" way if it's possible, hooking into the Validation class.
I tried a few variations on using something like this, with no luck thus far:
$this->Person->Image->validate['id']=array(...);
Edit:
Here is what I've tried doing, which kind of works:
public function beforeValidate($options=array()) {
parent::beforeValidate($options);
if(empty($this->data['redirect_url'])) {
if (!isset($this->data['Image']['filepath']) {
$this->invalidate('Image.filepath', 'Custom error message.');
return false;
}
}
}
This lets me invalidate the field without having to add extra code elsewhere, but when printing out the form field on the front end, I end up getting a generic "This file is required" error instead of my "Custom error message". I think this might be because file uploads are handled by a plugin that spirits them away to S3 instead of the local filesystem and it's getting overridden somewhere up the chain.

Advanced Validation with Lithium PHP Framework

I'm building a pretty complex and dynamic form via the Lithium PHP framework.
I've got the form working and saving to MongoDB with little problem. But I am having trouble with validation.
Simple validations (such as checking if a field is not empty or is numeric) are working fine. But I have to do a few complex validations that rely on a number of fields in the form.
For example, I have a form where a user can enter a question and then enter an unlimited number of possible answers for this question. The field ID for each answer is listed such as "answer_1", "answer_2", "answer_3", etc. The user can add an unlimited number of answers. This happens via some fancy JavaScript that inserts extra elements to the form on the client side.
At the validation level, I want to make sure that every answer which was added is not null.
I would like to do this using the "traditional" Validator functionality built within Lithium. I am also doing this at the Model level, not the Controller level (note - I have a workaround to solve this on the Controller level, but would rather do it the "right" way at the Model)
The problem, as far as I can tell, is that you can only pass a single value to the validator rule. I just need to pass back ALL values in the form to the validator. If I could do that, I would be golden. The pseudo-code for what I'm looking to do looks like this:
Validator::add('CorrectTest', function(&$value, $format = null, array $options = array()) {
foreach ($_data as $key => $value) {
if (stristr($key, "answer_")) {
if ($value == "") {
return false;
}
}
}
return true;
});
This code doesn't work, because the $_data value is not present. If I could just figure out a way to get a fully-populated "$_data" object into the Validator function, I think I could get this to work.
Thanks in advance for the help
Take a look at what's inside $options. You should have a 'values' key in there that has all of the values from the form.
So try
$_data = $options['values'];

CakePHP validation not working for contact form

I am trying to do some very simple validation in my CakePHP contact form, but validation does not work eventhough I think I did everything necessary. Here's what I did:
I made a model like this:
class Office extends AppModel
{
var $name = 'Office';
var $useTable = false;
public $validate = array('onderwerp' => 'notEmpty');
}
(I also tried many other values for $validate from the CakePHP online manual)
In Config/bootstrap.php I made this rule for not letting CakePHP expect plural "Offices":
Inflector::rules('plural', array('rules' => array(),
'irregular' => array(),
'uninflected' => array('office')));
In OfficeController, I do this in my method contact():
$this->Office->set($this->request->data);
if($this->Office->validates()){
echo "code validates";
} else {
print_r($this->Office->validationErrors);
}
And in my Office/contact.ctp view, I have (amongst other code like starting and ending the form) this code:
$this->Form->input('onderwerp', array('label'=>false, 'size' => 60));
Now, even when I fill in the form, leaving empty the field 'onderwerp', it executes the code that should be executed when the code is executed.
When I print_r($this->request->data) or print_r($this->Office) I see that my onderwerp field is there and that it is empty (or filled when I do fill in something).
Now, when I add a public function validates() in my model and echo something there, it IS being displayed. So I'd say CakePHP knows where to find my model, and does execute my controller code. I also tried adding return parent::validates(); in my validates() function, but this also yielded no validation error, or any other error for that matter. My debug level is set to 2.
I guess I'm missing a needle in this haystack. Thanks for helping me finding it!
so drop all the inflector stuff.
and use the right model in your Form->create()
either
$this->Form->create(null)
or
$this->Form->create('Office');
and if you follow my advice to use a table less model with schema you will also have more power over input creation and validation.

Resources