How to remove validation on a Select Element in Zend Framework 2 - zend-form

I wanted to bypass the annoying validation for the Select Element in Zend Framework 2. My requirement is that I have two select drop down boxes where I pass the values from the left select box to right select box and finally when I click the submit button, I post the values from right select box.
So basically the left select box is there to show the values to the user, my problem is that in the left select box as no value is selected it throws this error:
["selectAll"] => array(1) {
["isEmpty"] => string(36) "Value is required and can't be empty"
}
I have seen some old posts from Stackoverflow, where this is possible in Zend Framework 1 like one can disable the validation for the particular select element´
Examples:-
$selectAllElement->setRequired(false);
or
$selectAllElement->removeDecorator('Errors');
which some how these methods are not available in Zend Framework 2. In case if somebody has a solution of how disable the validation for a particular select element, please do share your knowledge, will be hepful for people getting into Zend Framework 2.
EDIT:
In my Form-
$select = new Element\Select('selectAllElement');
$select->setAttribute('title', 'Select a Value')
->setAttribute('id', 'id');
$options = array(
array(
//Fetching the values from database
),
);
$select->setAttribute('multiple', 'multiple')
->setAttribute('required', false)
->setValueOptions($options);
$this->add($select);
As per request from Sam, I have provided the code how I am adding the select element to my form and setting the attributes.
NOTE: I am not using any FIELDSETS

To clarify this as an answer, using the setRequired()-Method on any Zend\Form\Element only declares if the HTML-Attribute required="(bool)" should be rendered or not.
If you want to exclude a Field/Element from Validation you need to define this inside your InputFilters setting 'required' => false

Sometimes with me, the setRequired(false) not works when working with select multiple or checkbox that is not in the view, and so, i just override the isValid method and remove the validator as the code above:
public function isValid() {
$this->getInputFilter()->remove('alterarsenha');
$this->getInputFilter()->remove('usuario_perfis');
return parent::isValid();
}

I know this topic is most probably very outdated, but still maybe one consider this as useful.
In version of zf2 which I'm using there is a bug in class Zend\Form\Element\Select, this class provides InputProviderInterface, especially method getInputSpecification(), in this method option
$spec = array(
'name' => $this->getName(),
'required' => true,
);
So if you redefine method getInputSpecification it should works.

Related

How To Write An Inner Join With WP Query

I have a ACF relationship field for a custom post type, properties. Moreover, the content of these properties can either be in English or Spanish. When I use a ACF relationship field to associate properties to a user on the user edit page -- /wp/wp-admin/user-edit.php -- everything works as expected, and I can select from the relationship drop down the properties I want for this user.
My question is this: how can I write a query inside this filter such that only the English properties appear, regardless of the language of the page (English or Spanish) which is set by the WPML toggle? I know how to write such a query in SQL:
SELECT *
FROM wp_2_posts
INNER JOIN wp_2_icl_translations
ON wp_2_icl_translations.element_id = wp_2_posts.id
AND wp_2_icl_translations.language_code = 'en'
WHERE wp_2_posts.post_type = 'properties';
But the filter requires that changes be made to $args which adhere to WP_Query. I do not know how to write the above INNER JOIN on wp_2_icl_translations to only show custom post types properties in English. Can someone please instruct me how so that I can get the acf filter to work the way I need it to?
Ok so the way I was able to just show English properties on the user admin page was with this posts_request hook:
add_filter('posts_request', function($sql, $query) {
$is_user_edit_page = (
isset($_SERVER['HTTP_REFERER']) &&
strpos($_SERVER['HTTP_REFERER'], 'user-edit') !== false
);
$is_property_sql = (strpos($sql, 'property') !== false);
if ($is_user_edit_page && $is_property_sql) {
$sql = str_replace("'sp'", "'en'", $sql);
}
return $sql;
}, 10, 2);
In this hook I make sure it only runs on the user-edit page and that the sql it's changing relates to the properties. If all those cases are true, then I just replace the Spanish language code with the English one. And as a result, the SQL used to query the properties is forced to only query for English ones.

How to make a field required for customers but not for administrators in prestashop?

I made a custom field in prestashop.
I would like to know if there is some way to make this field only required on the frontend and not for administrators.
this is my code in Customer class
array('type' => self::TYPE_STRING, 'required' => true, 'size' => 64),
Thanks in advance
Can't think of a quick way to make this possible exactly as you want it, so here are two suggestions:
1 - Remove the 'required' => true from the definition and create some kind of custom validation like if (Tools::getValue('type ') == "") { return false; } in an override of the front office AuthController (Warning: code is completely untested and should definitely be improved, also according to your particular PS version).
2 - Use frontend validation by giving the frontend form field the required attribute (you should do this even if oyu use 1)

How to pass a parameter to a scenario in Yii?

How to pass $id to search scenario? Maybe in model look like this, so I can call like in controller like:
$model = new job('search',$id);
I think that you are trying to do a search. Search is one thing, a "scenario" is something else.
Scenarios are used in validation rules in order to be able to validate the same model in multiple ways depending from where you're inserting/adding OR searching data.
There's also a scenario called 'search' that is used by the model's search() method, but I tell you why:
There are a couple of ways to search for something in your database using Yii, I will mention two:
1) By using ClassName::model()->findCommandHere
And there are a couple of them:
ClassName::model()->findByPk($id);
ClassName::model()->findAll("id=$id");
ClassName::model()->findByAttributes(array('id'=>$id));
And so on, more here: http://www.yiiframework.com/doc/guide/1.1/en/database.ar#reading-record
2) By using the model's search() method
This way of finding data is mostly used for easily creating search pages and in combination with data grids.
If you generate CRUD code with the GII code generation tool it will generate all the parts for you, but I will explain each part how it works.
This code is from the blog demo found in Yii files:
In controller it defines a $model using Post class and 'search' as scenario.
$model=new Post('search');
if(isset($_GET['Post'])) // <- checks if there are search params in the URL
$model->attributes=$_GET['Post']; // <- assigns all search params masively to the model (later you'll see why)
$this->render('admin',array(
'model'=>$model,
));
The 'search' scenario here tells Yii what validation rules to use when assigning search parameters directly from $_GET (URL).
You can see that the params are assigned massively to reduce code written but $model->attributes=$_GET['Post'] it is the same as doing:
$model->title=$_GET['Post']['title'];
$model->status=$_GET['Post']['status'];
In the Post model you can find the validation rules for the search scenario. Tells Yii that it is safe to assign title and status fields in order to later use them in the search.
public function rules()
{
return array(
// ... //
array('title, status', 'safe', 'on'=>'search'),
);
}
Then also in the Post model you can see the search() method that will actually be used to get the data:
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('title',$this->title,true);
$criteria->compare('status',$this->status);
return new CActiveDataProvider('Post', array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'status, update_time DESC',
),
));
}
The search method creates a "criteria" and applies the desired way of filtering using the values you have previously assigned to this model. See the $this->title it comes from the $model->attributes=$_GET['Post'] you used in the controller.
The criteria can be used directly on the model, such as Post::model()->findAll($criteria), but in this case the search() method uses something different, a "data provider".
The data provider is a good thing because it provides you a lot of tools in one place, it returns you the data, but also the pagination, and the sorting, so you don't have to manually define more code for that purposes (CPagination, CSort).
Finally, in the view admin.php in this case it will display the results using a grid view:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'type'=>'raw',
'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
),
array(
'name'=>'status',
'value'=>'Lookup::item("PostStatus",$data->status)',
'filter'=>Lookup::items('PostStatus'),
),
),
));
Now you can see that in the configuration of the grid it passes $model->search() method as the dataProvider that the grid should use.
Now the grid can access the rest of the dataProvider elements such as sort, pagination and display them on the page.
If you did not want to use the CGridView because it's a very basic table and you want to create your own html markup, you can also retrieve the dataProvider and its components one by one and place them in your HTML code and display data as you want:
$dataProvider=$model->search(); // get the dataprovider from search method
$models=$dataProvider->getData(); // actually get the data (rows) and assign them to a $models variable that you can put in a foreach loop
// show pagination somewhere
$this->widget('CLinkPager', array(
'pages' => $dataProvider->pagination,
));
// create sort links
echo $dataProvider->sort->link('title', 'Title');
So I hope it solves some of your doubts on how to use Yii for displaying/searching data.
I suggest you read the official manual: http://www.yiiframework.com/doc/guide/1.1/en/index
I also suggest to look at the API and so search there all the Yii components to see what methods and params they have: http://www.yiiframework.com/doc/api/
Also exploring the framework codebase manually is quite a good way to learn. If you don't know how CActiveDataProvider works, then find the CActiveDataProvider class file in the code and you'll see all the methods and properties that it uses, so do this for everything you don't understand how it works.
Also for beginners I recommend using a good IDE that auto-completes code and allows you to Ctrl+Click a class name and it will locate the original file where it was defined. I use NetBeans for PHP and after creating a project I add Yii framework files to the project's include paths that way NetBeans knows how to find the framework files for auto-complete and for ctrl+click.
Yes you can define scenario with parameter but that is included within the class constructor of the model
$model = new Job('search'); // creating a model with scenario search
If you wish to include more parameters, then you need to use createComponent -remember, all is a component
$model = Yii::createComponent(array('class'=>'Job','scenario'=>'search'));
I think this will simply do the job without needing any scenario
$model = new job;
$model->search($id);
But If I have failed to understand your problem then you can also try this
$model = new job('search');
$model->search($id);
Think of scenarios as a special variable that you can use in the model.
$userModel = new User("register");
$userModel->setId = 10;
which is the same
$userModel = new User();
$userModel->scenario = 10
$userModel->setId = 10;
And in your model
class Manufacturer extends CActiveRecord
{
// :
if ($this->scenario == 'register') ...
// :
}

yii cGridView multicomment

I'm not sure what is the way to do this , so here I ask:
I have a Person model and Event model, and a connection table Person_Event.
The interface that I got now works in the following way:
A person is logging in and his id is being send via URL
The person is selecting events he is interested in from the cGridView (checkbox column)
Writing some comment
4.Pressing send button , and the following create action is being triggered:
public function actionXcreate()
{
$model=new Person_Event;
if(isset($_POST['Person_Event']))
{
foreach ($_POST['selectedIds'] as $eventId)
{
$pmodel=new Person_Event;
$pmodel->person_id=$this->_person->id; //the id of the person who is logged in
$pmodel->attributes=$_POST['Person_Event']; //the comment
$pmodel->event_id = $eventId; //all the events he checked in the grid
if (!$pmodel->save()) print_r($pmodel->errors);
}
$this->redirect(array('site/success'));
}
So far , all is logical and simple. However , what I end up is that the comment the person wrote is being duplicated to every person_event row in the DB.
I want to put a text box in each row of the grid , and the commnet that will be written there will go to the specific event.
Now , I found this topic in yii about "admin-panel"
which is kind of helpful , BUT:
I already have a foreach in the action , the one that matches the person's id with the event's id , so how can I put another individual comment for each combo?
The default CGridView supports only basic functionality, you would need to extend CGridView or use an extension to make columns editable
Easiest way to do this is use something like TbEditableColumn from Yii-booster library
see http://yiibooster.clevertech.biz/extendedGridView#gridcolumns EditableColumn in the additional column types section
If you do not like or wish to use twitter-bootstrap styling a standalone extension like http://www.yiiframework.com/extension/eeditable will help.
Alternatively you can extend CGridView yourself to extend it to support column level editing

kohana ORM question

i am using kohana ORM in order to get some results from the database. My problem is: even though i have consulted the documentation, i can't find a way to select only the column i am interested in. To be more explicit, i have:
$sale_stock = Model::factory('product_type')
->where('product_type_id','=', $id )
-> find_all();
var dumping it, it selects me all the "SELECT product_type.* from product_type where etc".
But i want to select only the 'stock' field from the salestock table. doing find('stock') instead find_all() returns a weired object... Where am i wrong, and how can i actually select only the column 'stock' using kohana orm?
thank you!
ORM methods find() and find_all() always select all table columns, so there is two ways to get specified fields:
Load full table rows and get columns
from it:
$sale_stock = Model::factory('product_type')
->where('product_type_id','=', $id )
-> find_all();
// get array of id=>stock values
$columns = $sale_stock->as_array('id', 'stock');
Create special method in model using
Query Builder:
// model Model_Product_Type
public function get_stocks($product_type_id)
{
return DB::select(array('stock'))
->from($this->_table_name)
->where('product_type_id', '=', $product_type_id)
->execute($this->_db);
}
I realise this isn't exactly what you're looking for, but I've pulled the following from the Kohana documentation ...
$articles = ORM::factory('article')->select_list('id', 'title');
foreach ($articles as $id => $title)
{
// Display a list of links
echo html::anchor('articles/'.$id, $title);
}
// Display a dropdown list
echo form::dropdown('articles', $articles);
You could think of it as a discount, two fields for the price of one.
It's common practice for ORMs to return a 'non-standard' object when partial model or merged model fields are requested. This prevents confusing operations using the original object (ie. how do you save an object when it contains only 2 of 8 fields, plus maybe some fields from another model?).
If you print_r the object, and give me an indication of how that looks ... it might be just what you want.
I know this is an old question, but i found maybe easier solution:
$sale_stock = ORM::factory('product_type')
->where( 'product_type_id','=', $id )
->find_all();
die($sale_stock->stock);