I have two search functions. One for public and one for admin search. They are exactly the same:
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
//$criteria->compare('ID',$this->ID);
$criteria->compare('t.IDkorisnik',Yii::app()->user->getId());
$criteria->compare('start_time',$this->start_time,true);
$criteria->compare('end_time',$this->end_time,true);
//$criteria->compare('information',$this->information,true);
$criteria->compare('country',$this->country,true);
$criteria->compare('city',$this->city,true);
$criteria->compare('start_price',$this->start_price);
$criteria->compare('min_bid',$this->min_bid);
$criteria->compare('valuta',$this->valuta,true);
$criteria->compare('title',$this->title,true);
$criteria->with=array('relationIDuzgajivac','relationIDgolub');
$criteria->compare('username',$this->uzgajivacSearch);
$criteria->compare('brojgoluba',$this->golub_search, true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
'pagination'=>array('pageSize'=>50),
));
}
except in search() I have this
$criteria->compare('t.IDkorisnik',Yii::app()->user->getId());
in publichsearch() I don't.
As you may see there is relation search. when I open admin page it works in publicsearch page it doesn't work, I don't know why
I never realized that when I'm creating new action
public function actionPublicSearch()
{
$model=new Auction('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Auction']))
$model->attributes=$_GET['Auction'];
$this->render('publicsearch',array(
'model'=>$model,
));
}
this $model=new Auction('search'); within model always has to be 'search' not something like 'public_search'
and then within view, where CGridView is created
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'auction-grid',
'dataProvider'=>$model->public_search(),
dataProvider is a place where I put my search function, in this case public_search
Related
I am having an issue inserting a record into the database. I am a beginner with the Yii framework, so I may have made some stupid mistakes.
This is from the SiteController
public function actionCreatePost(){
$model = new PostForm();
$post = new Post();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$post->body = $model->body;
$post->title = $model->title;
$post->save();
return $this->redirect('index');
}else {
return $this->render('createPost', ['model' => $model]);
}
}
This is from the Post class
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => new Expression('NOW()'),
],
[
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'id_author',
]
];
}
The issue is that you have created a PostForm class for the form (which is correct) but you are then trying to load the response into the Post class - a completely different class. This won’t work without modification.
If you have a look at the response:
var_dump(Yii:$app->request->post());
You will see the form data is located within the PostForm key. Yii will therefore only load the data into the PostForm class.
The correct solution is therefore to create a savePost() function within the PostForm eg:
public function savePost(){
$model = new Post();
$model->propertyABC = $this->propertyABC
...etc...
$model->save();
So the action would appear as follows:
$model = new PostForm();
If($model->load(Yii::$app->request->post()) && $model->validate()){
$model->savePost();
The other option is to rename the key from PostForm to Post. Yii will then load the data but this is not the best approach as it is a bit obscure.
Hope that helps
I would guess the issue is with the validation.
I can see several issues I will point out. First, I cannot figure out why are you creating a new PostForm, loading the data in it and verifying it, just to dump some values in a new Post and save it. Are there some functions, you are running in the PostForm model, that are triggered by load or verify? If that is not the case, I would suggest dropping one of the models, and using only the other. Usually, that is the Form model. It serves as a link between the ActiveForm and the model handling everything. You can do everything in the createPost() function in the Form model, and then in the controller it will look like
if ($model->load(Yii::$app->request->post())) {
$model->save();
return $this->redirect('index');
}
Second of all, you can dump post->getErrors() before the save to see if there are any errors with the validation. What you can also do, is call $post->save(false) instead. If you pass false to it, it will not trigger $post->validate(), and some errors can be neglected. Please, let me know if there is anything unclear.
I read a lot of things of things in the cookbook or on stackoverflow but I can't find something adapted and clearly explained about how to solve my problem.
I have an SQL request that allows me to find schools that teaches a specific subject. I need to set this SQL request so that when I load the page containing my form, the request is done and I see the result (a list of school) in a multi select form. My best guess is that I need to set it inside my controller, but then again, I'm not even sure of that since it's the first time that I need to do that
I don't know if I should show you any code, so ask if you need to see something!
Thank you in advance
edit Here is my formType
<?php
namespace MissionBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use SocieteBundle\Entity\Societe;
class PublicType extends AbstractType{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('public')
->add('ecolesDispo')
// My goal is to replace 'ecolesDispo' (that is currently a one-to-many)
// by my SQL request.
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MissionBundle\Entity\Mission'
));
}
}
Surely not in the controller. You need to use the "query_builder" attribute when you add the field to the form. Take a look at this example, from the Symfony cookbook : http://symfony.com/doc/current/reference/forms/types/entity.html#using-a-custom-query-for-the-entities
And you should translate your raw SQL query into DQL, so it's database-agnostic.
UPDATE about using a query builder with native SQL : http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/native-sql.html#the-nativequery-class
So something like this following piece of code should work (you'll have to edit some property names and fill the query though)
$builder->add('ecolesDispo', EntityType::class, array(
'class' => 'AppBundle:Ecole',
'query_builder' => function (EntityRepository $er) {
return $er->createNativeQuery('SELECT * FROM ecoles WHERE [...]');
},
'choice_label' => 'title',
));
i dont know where am i going wrong i did play round with it but did not achieve anything.
i wanna display data using cListview but unable to do so
i have a function in model
Model
public function psearch1()
{
$name=$_GET['search'];
$criteria=new CDbCriteria;
$criteria->alias="t";
$criteria->select="t.id,t.name,t.model";
$criteria->condition='name LIKE "%'.$name.'%"';
return new CActiveDataProvider($this,array('criteria'=>$criteria,));
}
controller
public function actionPsearchindex()
{
$dataProvider=new Modelname('psearch');
$this->render('psearchindex',array(
'dataProvider'=>$dataProvider,
));
}
view
psearchindex
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_psearchindex1',
));
_psearchindex
echo CHtml::encode($data->name);
when i execute i get the following
error
Modelname and its behaviors do not have a method or closure named "getData".
this is my first attempt am doing so but unable to figure out whats wrong
a new model is not a data provider, call your custom search on it
public function actionPsearchindex()
{
//$dataProvider=new Modelname('psearch');// a new model is not a data provider
$model = new Modelname('psearch');
$this->render('psearchindex',array(
'dataProvider'=>$model->psearch1(), // this will give you a data provider that you can use
));
}
I'm using the Yii-dynamic-active-record model class to get and put data to various database tables. Now I'd like to use cgridview to quickly build some views of this data, but I'm getting hung-up on writing a search function for this class.
I know that I could always do a foreach loop within the view and make my own html table, but if I could get the Yii way working that would be great for DRY.
*All the db tables have a ID column and this is the only column that really needs to be displayed... if you could get all the columns that would just be bonus points.
Thanks :)
Model
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('ID',$this->ID);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
View
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'entry-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'ID',
),
));
Controller
$tablename=$_GET['tname'];
$table=Entry::forTable($tablename);
$model=$table->findAll();
if(isset($_GET['Entry']))
$model->attributes=$_GET['Entry'];
$this->render('all',array(
'model'=>$model,
));
I am a little confused by what you have done here, however I think I have a solution. First off, in line 3 of your controller code, you call $model = $table->findAll(); this is likely not what you intended, as it will provide you with an ActiveRecord[]. What you want to do is to pass your $table into the gridview. So your controller code would look like this:
$tablename=$_GET['tname'];
$model=Entry::forTable($tablename);
if(isset($_GET['Entry']))
$model->attributes=$_GET['Entry'];
$this->render('all',array(
'model'=>$model,
));
you then need to pass in the table name to the CActiveDataProvider in your model:
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('ID',$this->ID);
return new CActiveDataProvider($this->tableName(), array(
'criteria'=>$criteria,
));
}
now for the "yucky" part, you need to edit the static model method of CActiveRecord to this:
if(isset(self::$_models[$className]))
return self::$_models[$className];
else
{
if(class_exists($className)){
$model=self::$_models[$className]=new $className(null);
$model->_md=new CActiveRecordMetaData($model);
$model->attachBehaviors($model->behaviors());
}
else{
$model = Entry::forTable($className);
}
return $model;
}
This tells it to load from the Entry table when a class of that name does not exist. This practice is discouraged, however its the only way I see of getting around your issue.
How to filter the search results as a combination of checkboxes and dropdown in Yii? I have some categories as checkboxes and budget as dropdown that is listing from database. WIth multiple checkboxes checked and selecting a value from dropdown, how can I filter out the search results.. Is there any better way ?? (My requirement is like in this link. http://www.ebay.in/sch/i.html?_from=R40&_sacat=0&_nkw=pendrives&rt=nc&LH_FS=1 )
I recommend to use a search model. This could look like this:
class SearchProducts extends CFormModel
{
public $minPrice;
public $maxPrice;
public $categories;
// Add a public property for each search form element here
public function rules()
{
return array(
// You should validate your search parameters here
array('minPrice,maxPrice,categories', 'safe'),
);
}
public function search()
{
$criteria = new CDbCriteria;
if(!empty($this->minPrice))
$criteria->addCondition('price > '.(int)$this->minPrice);
if(!empty($this->maxPrice))
$criteria->addCondition('price < '.(int)$this->maxPrice);
if(!empty($this->categories))
$criteria->addInCondition('category_id', $this->categories);
// Add more conditions for each property here
return new CActiveDataProvider('Product', array(
'criteria' => $criteria,
// more options here, e.g. sorting, pagination, ...
));
}
}
In your controller you create a new instance of the search form and assign search variables as usual:
public function actionProducts()
{
$searchModel = new ProductSearch();
if(isset($_POST['ProductSearch']))
$searchModel->attributes = $_POST['ProductSearch'];
$this->render('products', array(
'searchModel' => $searchModel,
));
}
Finally in your view you can now render
A regular Yii form for $searchModel properties which will be your search filter form
A CListView or a CGridView where you set the provider to $searchModel->search() which will be your search results.
For the checkboxes you'd use a checkBoxList:
<?php $this->formCheckBoxList($model, 'categories[]', Category::opts()) ?>
Note the [] which indicates that this should be posted as array. For convenience i usually also implement a static opts() method in some models, which returns a list of id=>name that you can use for dropDownList or checkBoxList options.
This is only the basic pattern. You can easily extend it to create really powerful search forms and result list. Just always keep in mind that you should keep all search related data in another model.
try this extension: ddautofilter
https://bitbucket.org/jwerner/yii-ddautofilter/overview