I am building some user profiles and want to add social links to the profiles so users can link to their, let's say Steam, YouTube, Google+ profiles.
So i can't find any way of validating against specific url's in laravel. I want a user, if he set a link in steam text field to validate if given url is really url to steampowered.com, or if not to throw an error that url is not valid.
I have read the documentation on validation and i read that there is a URL validation, but as i have read it's only validating agains the input if it's formated as an url. so basically user can post any url and it will be validated.
Is there a filter or some additional condition to URL validation for a specific url. So the input field will be valid only if user insert like: http://steamcommunity.com in the field.
How can someone achieve that, or i must write old php regex expression?
You should definetely write your own custom Validator and use a regexp to verify that:
\Validator::extend('checkUrl', function($attribute, $value, $parameters)
{
$url = $parameters[0];
//Your pattern, not pretending to be super precise, so it's up to you
$pattern = '/^((http|https)\:\/\/)?(www\.)?'.$url.'\..+$/'
if( preg_match( $pattern,$value)
{
return true;
}
return false;
});
And to use it provide it as a rule to your validator
$rules = [
your_field => 'checkUrl:http://steamcommunity.com'
];
Such a thing is not built in. You can write a custom validation rule and then use regex as you said.
Validator::extend('steam_url', function($attribute, $value, $parameters)
{
$pattern = "#^https?://([a-z0-9-]+\.)*steamcommunity\.com(/.*)?$#";
return !! preg_match($pattern, $value);
});
Usage: 'url' => 'steam_url
Or something more generic:
Validator::extend('domain', function($attribute, $value, $parameters)
{
$domain = $parameters[0];
$pattern = "#^https?://([a-z0-9-]+\.)*".preg_quote($domain)."(/.*)?$#";
return !! preg_match($pattern, $value);
});
Usage: 'url' => 'domain:steamcommunity.com'
Both of your answers are correct guys, however i never liked using regex and i remembered what i did on some site i was making last year to match the website url, and to match it to the point where is no possible for user to input wrong url, and this will also match both http and https. So my final solution is to use parse_url method, very simple and thanks to your examples of validator parameters i can also use it on multiple different domains.
Here's my final code.
Validator::extend('checkUrl', function($attribute, $value, $parameters) {
$url = parse_url($value, PHP_URL_HOST);
return $url == $parameters[0];
EDIT: there is even simpler solution instead of using if method and returning false or true, you can just use return method with option you want to validate.
return $url == $parameters[0];
This would be resolved as
if($url == $parameters[0]) {
return true
} else {
return false
}
Related
I have a form (defined in XML) which is used with Joomla's JForm to handle. What I'd like to know is if it's possible to validate against multiple rules at once.
Typically, I've come to understand that Joomla's JForm accepts only one rule for validation, defined in the XML of the form:
Joomla's JForm internals also seem to suggest I can't, the following area being the only one I can find handing validation:
// Get the field validation rule.
if ($type = (string) $element['validate'])
{
// Load the JFormRule object for the field.
$rule = $this->loadRuleType($type);
// If the object could not be loaded return an error message.
if ($rule === false)
{
throw new UnexpectedValueException(sprintf('%s::validateField() rule `%s` missing.', get_class($this), $type));
}
// Run the field validation rule test.
$valid = $rule->test($element, $value, $group, $input, $this);
// Check for an error in the validation test.
if ($valid instanceof Exception)
{
return $valid;
}
}
This isn't wrapped in a loop, so I'm quite concerned that I can't apply multiple rules at once to a particular field.
Are you looking for server or client side validation? Sean's answer seems to cover server side so I figured I'd add some insight into client side techniques.
You enable client side validation two ways. The first and simplest would be by adding the following to your form field definition, which would ensure any required fields are filled out to proceed.
required="true"
Second would be to add a class to the form field definition to let Joomla core know you want to validate the field and how. Joomla offers 4 validations built into the core: validate-username, validate-password, validate-numeric and validate-email.
These in and of themselves don't help you much, but the ability to create and reference custom client-side validations does. For my example we're going to ensure a check box is marked before allowing the form to submit. So in the form field definition I'll add:
class="validate-checked"
On the page where you render the form, be sure to load the JS library for validation using:
JHtml::_('behavior.formvalidation');
In addition, add the class form-validate to your form HTML element.
Add this javascript to handle the actual validation, here I have a checkbox input type with an ID of tos I'm verifying. In the setHandler method, the first parameter is the custom name I entered in the form field definition class statement, validate-checked:
<script>
window.addEvent('domready', function(){
document.formvalidator.setHandler('checked', function(value) {
var tos = document.getElementById('tos');
if (tos.checked) {
return true;
} else {
return false;
}
});
});
</script>
Now, capture the submit event and verify all core and custom validations passed before submitting the form.
Joomla.submitbutton = function(task) {
if (task == 'user.cancel' || document.formvalidator.isValid(document.id(".myFormId"))) {
Joomla.submitform(task, document.getElementById('myformId'));
}
You can create as many custom client-side validation scripts as you want. Inside the setHandler method you can interact with the DOM and use the passed in value parameter to determine if the field should pass, only needing to worry about returning true or false to indicate results and Joomla will handle the rest. So you can either create one complicated validation or many smaller concise validations to suit your needs.
Hope that helps...
This is a common request. There are a few possibilities. You could write your own JFormRule with more complex validation. The other is that you could programatically add an attribute to the field that runs the additional validation sort of like what Sean is advocating.
This answer assumes that it is not possible to natively add multiple rules on one field.
Assuming that it is not possible to apply multiple rules to one field natively, then it may be possible to extend JForm::validateField() to enable such a feature by simply calling the validate method for each validation rule found.
// Extending class JForm
protected function validateField(SimpleXMLElement $element, $group = null, $value = null, JRegistry $input = null) {
if($type = (string) $element['validate'])
{
$multiple_types = explode('|', $type);
if(is_array($multiple_types) && $multiple_types[0] !== $type)
{
foreach($multiple_types as $single_type)
{
$result = parent::validateField($element, $group, $value, $input);
// Validation failed, return the result and stop validating.
if($result !== true)
{
return $result;
}
}
return true;
}
else
{
return parent::validateField($element, $group, $value, $input);
}
}
}
With that example, validation rules could be structured like:
validate="rule1|rule2"
I need to handle a SEO-friendly URL in my Yii application. My URL structures in the pattern: "domain.com/url-string/uniqueid". For example:
domain.com/properties-in-dubai/325fgd
domain.com/properties-in-USA/4577ds6
domain.com/properties-in-india/567dew
domain.com/apartments-in-anderi-mumbai/645fki
The above URL strings and ID are populated by us. When the user access this URL:
first need to validate the URL pattern.
second extract the I'd and URL string and match with my data store.
third when above URL and I'd exist in our data store pass a referenced parameters to existing search page.
Kindly, anyone help me solve this issue and give sleep to me.
First, you add a new rule to your urlManager application configuration.
'rules' => array(
'<slug>/<id:\d+>' => 'property/view'
// ...
)
Then you can retrieve the slug and ID in the action:
class PropertyController extends CController
{
public function actionView($slug, $id)
{
$id = (int) $id;
// Check if $id, $slug exist; replace line below
$exists = true;
if($exists){
// Redirect to elsewhere
$this->redirect();
}
}
}
I am using php form builder class
$form->addTextbox("Tags:", "thread_tags", "", array("required" => 1));
Does anyone know how you can validate tags (e.g. split by strings tag1, tag2, tag3) using this class? Do you do it after validation or before?
Obviously you can use preg_split, but where would you do it here? I want to make sure each tag is atleast 3 chars in length.
This isn't a nice form builder to work with, but here is how I managed to create the validation for the tag element.
Add a textbox element:
$form->addTextbox('Tags:', 'tags', "", array("required" => 1));
There is a method "bind([form object], [javascript condition], [php condition])", I think this method is to add a validation rule to an element.
$form->bind($form, '', 'validateTags()');
The third parameter is a function to validate the tag value. return true if the textbox contains correct data, or false if it's incorrect. Also, if the value is incorrect add an error message to the form error session and then return false.
function validateTags($form) {
if (isset($_POST["tag"])) {
$value = strip_tags($_POST["tag"]);
$tags = explode(',', $value);
foreach ($tags as $tag) {
if (strlen($tag) < 3) {
// there might be a better way to do this!
// validation_2 == id of the form
$_SESSION["pfbc-errors"]['validation_2']["errormsg"]['tag'] = "validation message....";
return false;
}
}
unset($_SESSION["pfbc-errors"]['validation_2']["errormsg"]['tag']);
}
return true;
}
Hope this helps
I have an element. I want to add a custom validator and custom filter to it. The validator makes sure the input is one of several permitted values, then the filter adds some custom values to the input. This means I have to validate the original input first before running the filter. I do it in this order
$element = new Zend_Form_Element_Text('element');
$element->addValidator('PermittedValue', false);
$element->addFilter('TotalHyphen', false);
$this->addElement($element);
but this order isn't being respected. The filter runs first and changes the data, then the validator runs on the filtered data which means it always fails even for valid input. It seems from documentation that this is intentional
Note: Validation Operates On Filtered
Values Zend_Form_Element::isValid()
filters values through the provided
filter chain prior to validation. See
the Filters section for more
information.
How can I specify the order in which validators and filters run?
Sure seems like creating a custom element that supports post-validation filtering would be the way to go. How about this:
/**
* An element that supports post-validation filtering
*/
class My_Form_Element_PostValidateFilterable extends Zend_Form_Element_Text
{
protected $_postValidateFilters = array();
public function setPostValidateFilters(array $filters)
{
$this->_postValidateFilters = $filters;
return $this;
}
public function getPostValidateFilters()
{
return $this->_postValidateFilters;
}
public function isValid($value, $context = null)
{
$isValid = parent::isValid($value, $context);
if ($isValid){
foreach ($this->getPostValidateFilters() as $filter){
$value = $filter->filter($value);
}
$this->setValue($value);
}
return $isValid;
}
}
Usage would be something like this:
$elt = $form->addElement('PostValidateFilterable', 'myElement', array(
'label' => 'MyLabel',
'filters' => array(
'StringTrim',
// etc
),
'validators' => array(
'NotEmpty',
// etc
),
// here comes the good stuff
'postValidateFilters' => array(
new My_Filter_RunAfterValidateOne(),
new My_Filter_RunAfterValidateTwo(),
),
));
This keeps the validation and filtering in the form - keeping the controller thin.
Not tested, just a stab in the dark. And surely you could fatten/modify the API to add/remove filters by key, etc.
Whaddya think?
Maybe don't add the filter at all. Validate the content first in the controller, and then use the filter separately:
$request = $this->getRequest();
if ($request->isPost() && $form->isValid($request->getParams())) {
$filter = new Filter_Whatever();
$val = $filter->filter($request->getParam('element'));
... //call your model or whatever
}
I've never done this, but I suppose this (or something similar) might work.
Good point ! ,
AFAIK filters should or must run before validating the input :
from ZF docs
It's often useful and/or necessary to
perform some normalization on input
prior to validation. For example, you
may want to strip out all HTML, but
run your validations on what remains
to ensure the submission is valid. Or
you may want to trim empty space
surrounding input so that a
StringLength validator will use the
correct length of the input without
counting leading or trailing
whitespace characters.
but if and only if you are in case which can't solve mingos's answer must be the help
What you want to achieve is to change default behavior of how text element is being processed. Thus, I think you could create your own element (e.g. My_Form_Element_Text) that extends Zend_Form_Element_Text and overload its isValid() method.
Specifically you could just change second line in the orginal isValid() method, from $value = $this->getValue(); into $value = $this->getUnfilteredValue();. This way your validation will be performed using unfiltered values.
I have a question field with a list of allowed characters : A-Z,0-9,colon (:), question mark (?), comma(,), hyphen(-), apostrophe (').
I have the regex which works fine, in the fashion :
$question->addValidator('regex', true, array(<regular expresstion>))
The default error message is something like ''' does not match against pattern ''
I want to write a custom error message that says ' is not allowed in this field'
Is there a simple way to do it using the existing zend components that I'm missing?
Is writing a custom validator the only way to achieve what I'm trying to achieve?
If yes, how do I write a custom validator (I looked at the documentation and didn't quite understand how I can customize the error messages)
If there is any other way, I'd most appreciate that input too.
Thanks for taking the time to answer this!
Yes, the custom validator fits your needs. On how to write it, please refer to this manual.
With regards to a code snippet, here's a simple validator(partial) for validating employer ID
protected $_messageTemplates = array(
self::UNIQUE => 'The id provided is already in use',
);
public function isValid($value, $context = null)
{
$this->_setValue($value);
$personnel = new Personnel();
$isValid = true;
if( $personnel->isExistingIdEmployee($value) && ($value != $this->_id) ) {
$this->_error(self::UNIQUE);
$isValid = false;
}
return $isValid;
}