wondering if anyone can help.
I have a two pages in my Yii application that use the same controller/model, but use different model functions. My initial page is pretty standard 'admin' page that uses the default search() as the model (this works fine - including filtering), but i've subsequently made a secondary view/action which looks at an altered search function - this has an ID passed into it (pulled from URL params). This works fine, but the filters in page don't work which is annoying.
I think it's because in the controller, i'm not passing the ID variable through correctly???
Here's some of my code;
Model:
public function searchByEvent($event_id) {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id, true);
$criteria->compare('event_id', $this->event_id, true);
$criteria->compare('status_id', $this->status_id, true);
$criteria->compare('checkin_status_id', $this->checkin_status_id, true);
$criteria->compare('guest_of_user_id', $this->guest_of_user_id, true);
$criteria->compare('user_id', $this->user_id, true);
$criteria->compare('assign_group', $this->assign_group, true);
$criteria->with = 'user';
$criteria->compare('user.forename', $this->user_forename, true);
$criteria->compare('user.surname', $this->user_surname, true);
$criteria->compare('user.company', $this->user_company, true);
$criteria->order = 'user.surname ASC';
$criteria->condition = "event_id = :event_id";
$criteria->params=(array(':event_id'=>$event_id));
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination'=>array('pageSize'=>50),
));
}
Controller:
public function actionAdminByEvent() {
$model = new EventAttendees('searchByEvent');
$model->unsetAttributes(); // clear any default values
if (isset($_GET['EventAttendees']))
$model->attributes = $_GET['EventAttendees'];
$this->render('webroot.themes.'.Yii::app()->name.'.views.adminEventAttend.adminByEvent', array(
'model' => $model,
));
}
View;
$event_id = Yii::app()->getRequest()->getParam('event_id');
this->widget('booster.widgets.TbGridView', array(
'id' => 'event-attendees-grid',
'dataProvider' => $model->searchByEvent($event_id),
'pager' => array(
'class' => 'booster.widgets.TbPager',
'displayFirstAndLast' => true,
),
'filter' => $model,
'template'=>'{summary}{pager}{items}{pager}',
'selectableRows' => 0,
'selectionChanged' => 'function(id){ location.href = "' . $this->createUrl('view') . '/id/"+$.fn.yiiGridView.getSelection(id);}',
'columns' => array(...
Can anyone see where i'm going wrong with the filters, or if im missing a step with search?
If I were to guess, it's because the attributes in your model are not declared as "safe" when it is under the "searchByEvent" scenario. If you used gii and looked at your model's rules method, you would find an entry there that marks all attributes as "safe" when using the "search" scenario. You are using a different scenario called "searchByEvent" in your controller action ($model = new EventAttendees('searchByEvent')) and if you did not create a new rule that flags your attributes as safe under this scenario, then your mass assignment line ($model->attributes = $_GET['EventAttendees']) will fail for any attributes without any scenario-less rules.
If that isn't the case though, another thing you might want to look at is changing the following:
$criteria->condition = "event_id = :event_id";
$criteria->params=(array(':event_id'=>$event_id));
to
$criteria->addColumnCondition(array('event_id' => $event_id))
Your params line might be overwriting all the other parameters that were set with all the previous compare statements because you are not merging your new parameters into the current set. Using the proper CDbCriteria methods helps get around this.
Related
I am very much new to laravel framework.
I have one form , which i need to update on submit button click.
when submit button clicks control goes to controller.php 's update() function .
But I am unable to edit any field's value.
here is my code.
public function update($id)
{
//echo "<pre>";print_r(Input::all());exit;
$product = $this->product->find($id);
$input = Input::only('designer', 'sku', 'name', 'display_name', 'description', 'price', 'main_category', 'sub_category', 'lead_time', 'sizing', 'woven', 'body_fabric', 'lining_fabric', 'fit', 'primary_color', 'secondary_color', 'care_label', 'neck_type', 'closure', 'trims', 'special_finishings', 'image1', 'image2', 'image3', 'image4', 'image5','top', 'combo_products', 'keywords', 'visibility', 'featured');
//echo "<pre>";print_r($input);exit;
try
{
$this->adminNewProductForm->validate($input);
} catch(\Laracasts\Validation\FormValidationException $e)
{
return Redirect::back()->withInput()->withErrors($e->getErrors());
}
$slug = Str::slug(Input::get('name'));
$slug = $this->product->getSlug($slug);
$input = array_add($input, 'slug', $slug);
DB::transaction(function() use($product, $input)
{
$product->fill($input)->save();
$stock_count = 0;
if(!empty(Input::get('xsmall_size')))
{
$rows = DB::table('products_variants')->where('product_id', $product->id)->where('variant_name', 'XS')->get();
$stock_count += Input::get('xsmall_stock');
if(!empty($rows))
{
DB::table('products_variants')->where('product_id', $product->id)->where('variant_name', 'XS')->update(array('variant_specs' => Input::get('xsmall_size'), 'price_change' => Input::get('xsmall_price'), 'total_stock' => Input::get('xsmall_stock'), 'stock_used' => 0));
} else {
DB::table('products_variants')->insert(array('product_id' => $product->id, 'variant_name' => 'XS', 'variant_specs' => Input::get('xsmall_size'), 'price_change' => Input::get('xsmall_price'), 'total_stock' => Input::get('xsmall_stock'), 'stock_used' => 0));
}
}
$input = array();
$input['flagship_status'] = Input::get('flagship_status');
if(Input::get('flagship_status'))
{
$input['stock_count'] = Input::get('small_stock');
}else {
$input['stock_count'] = $stock_count;
}
$product->fill($input)->save();
});
//echo "<pre>";print_r(Input::all());exit;
return Redirect::back()->withFlashMessage('Product Updated Successfully!');
}
Also I cant understand , what is going on by this line ? because i did not find validate function anywhere in my code.
$this->adminNewProductForm->validate($input);
I need to update table products not products_variants.
validate is inherited from the FormRequst class.
https://laravel.com/api/5.0/Illuminate/Foundation/Http/FormRequest.html#method_validate
You've provided too much code and too little information. You said you need to update a specific table, but yet there are two lines where you are very intentionally manually updating a database entry.
This is one of them:
DB::table('products_variants')->where('product_id', $product->id)->where('variant_name', 'XS')->update(array('variant_specs' => Input::get('xsmall_size'), 'price_change' => Input::get('xsmall_price'), 'total_stock' => Input::get('xsmall_stock'), 'stock_used' => 0));
When you call this:
$product->fill($input)->save();
It also saves 'dirty' (modified) models that also belong to it, which can include products_variants relationships. From the sound of it, you are incorrectly applying changes directly through SQL, and then the model's save method is overwriting it.
You seem unclear about what your code is actually doing, and I would strongly suggest simplifying it down and adding in code as you begin to understand what each line does. I think your question is the byproduct of copying an example and adding your own work without understanding how Laravel handles relationships and models. There is almost never a good reason to use raw SQL or DB statements.
I am creating a basic CMS to teach myself the fundamentals of Laravel and PHP.
I have a 'pages' table and I am storing a url_title. I want this URL title to be unique for obvious reasons. However, whatever I do to validate it, fails. It just saves anyway. I'm sure it is something simple. Can you spot what is wrong with this code?
I am also using Former in the view, that doesn't validate either. I have tried hard-coding a value as the last option in the unique method and it fails also.
http://anahkiasen.github.io/former/
http://laravel.com/docs/validation#rule-unique
States: unique:table,column,except,idColumn
Here is my Controller:
public function store()
{
$validation = Pages::validate(Input::all());
if($validation->fails()) {
Former::withErrors($validation);
return View::make('myview');
} else {
Pages::create(array(
'title' => Input::get('title'),
'url_title' => Input::get('url_title'),
'status' => Input::get('status'),
'body' => Input::get('body'),
'seo_title' => Input::get('seo_title'),
'seo_description' => Input::get('seo_description')
));
//check which submit was clicked on
if(Input::get('save')) {
return Redirect::route('admin_pages')->with('message', 'Woo-hoo! page was created successfully!')->with('message_status', 'success');
}
elseif(Input::get('continue')) {
$id = $page->id;
return Redirect::route('admin_pages_edit', $id)->with('message', 'Woo-hoo! page was created successfully!')->with('message_status', 'success');
}
}
}
Here is my model:
class Pages extends Eloquent {
protected $guarded = array('id');
public static $rules = array(
'id' => 'unique:pages,url_title,{{$id}}'
);
public static function validate($data) {
return Validator::make($data, static::$rules);
}
}
I have tried the following:
public static $rules = array(
// 'id'=> 'unique:pages,url_title,{{$id}}'
// 'id'=> 'unique:pages,url_title,$id'
// 'id'=> 'unique:pages,url_title,:id'
// 'id'=> 'unique:pages,url_title,'. {{$id}}
// 'id'=> 'unique:pages,url_title,'. $id
);
Any ideas? I spoke to the guy who created Former. He can't make head nor tail about it either. He suggested tracking it back to find our what query Laravel uses to check the uniqueness and try running that directly in my DB to see what happens. I can't find the query to do this. Does anyone know where to track it down?
Many thanks
Your rule should be:
public static $rules = array(
'url_title' => 'unique:pages,url_title,{{$id}}'
);
As I guessed from your code Input::get('url_title')
You have to use the field name used in the form.
Thanks peeps. I have been using the Laravel unique solutions and it hasn't been working well. I found this package which solves the issue brilliantly.
https://github.com/cviebrock/eloquent-sluggable#eloquent
Definitely worth a look.
Thanks for your feedback.
I am new in yii. I want to search by attribute (field name) from my model and need to view in view page or another page by zii.widgets.grid.CGridView.
how can I create a search() function in model by findByAttribute()
so that we can show the results by attribute without any search
here is my model function but it is not working.. :: ERROR Undefined variable: pp_requisitionno
public function searchView()
{
$criteria=new CDbCriteria();
$criteria->select= 'pp_requisitionno';
$criteria->addSearchCondition('pp_requisitionno',$pp_requisitionno);
$criteria->compare('pp_requisitionno',$this->pp_requisitionno);
$criteria->condition = 'pp_requisitionno=:pp_requisitionno';
$criteria->params = array(':pp_requisitionno'=>Yii::app()->Request->Getpost('pp_requisitionno'));
$model = Requisitiondt::model()->find();
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Any help please...
It's probably going to be more useful to define a general search function that can be reused for different searches. This can be done in the following way:
/**
* Retrieves a list of models based on the current search/filter conditions.
* #return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search() {
$criteria = new CDbCriteria;
//Define all your searchable fields here
$criteria->compare('t.title', $this->title, true);
$criteria->compare('t.type', $this->type, true);
$criteria->compare('t.published', $this->published, true);
$criteria->compare('category.id', $this->category_id, true);
//Add any other criteria, like the default sort order etc.
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
));
}
Then in your controller you can use the search like this;
pubic function actionSearch(){
$model = new Requisitiondt;
if (isset($_POST)){
$model->attributes = $_POST;
$dataProvider = $model->search();
$this->render('searchView', array('dataProvider' => $dataProvider));
}
}
The view 'searchView' then looks like this;
<?php
$this->widget('CGridView', array(
'dataProvider' => $dataProvider,
'columns' => array(
//Add in whatever columns you want the grid to show
)
));
?>
Obviously you'll need to replace your own model names and field names, but this is the general idea. This way will search for any attributes you include in the POST request,and is more reusable.
You need use Relations in your model, read here.
Then add 'filter' => $model, in your GridView Widget options array
I'm trying to work with a YII CGridview to display some data.
This is home my model search function looks like:
/**
* Retrieves a list of models based on the current search/filter conditions.
* #return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
*/
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('ip',$this->ip,true);
$criteria->compare('first_use',$this->first_use,true);
$criteria->compare('last_use',$this->last_use);
$criteria->compare('memberid',$this->memberid);
$criteria->compare('countryid',$this->countryid);
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
And this is how my view looks like
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'iplog-grid',
'dataProvider'=>$oIPLog->search(),
'filter'=>$oIPLog,
'summaryText' => 'showing you {start} - {end} of {count} logged Ips',
'columns'=>array(
array(
'name'=>'ip',
'type'=>'raw',
),
array(
'name'=>'first_use',
'type'=>'datetime',
),
array(
'name'=>'last_use',
'type'=>'datetime',
),
),
));
Displaying the CGridview works, but I can't seem to get the filter on top of it to work. It sends the call and I don't get any error as reponse, it just returns the whole unfiltered data again..
Any clues?
And how exactly does your controller look like?
For the CGridview filter to work you need to check in your controller if there are any filters set and then return the filtered object.
To clarify, something like this should be placed into your controller action
$oObject = new Object('search');
if (isset($_GET['Object'])) {
$oObject->attributes = $_GET['Object'];
}
Hope this helps
You Have to apply these points:
1.Specify the global variable($_REQUEST) in function of your controller
for example
$model = new User('search');
$model->unsetAttributes(); // clear any default values
if (isset($_REQUEST['User'])){
$model->attributes = $_REQUEST['User'];
}
$this->render('admin', array(
'model' => $model,
));
Set method type in search form
<?php $form=$this->beginWidget('CActiveForm', array(
'action'=>Yii::app()->createUrl('user/admin'),
'method'=>'POST',
)); ?>
3.In Cgrid view you have to define the url like
'ajaxUrl'=>Yii::app()->createUrl( 'controller/function' ),
How can I pass the model in array format.
I want to pass models in this format from controller to view:-
Users[user_contact]=Contact
Users[user_contact][contat_city]=City
Users[user_contact][contact_state]=state
This is what I am doing
public function actionCreate() {
$user = new Users;
$presContact = new Contacts;
$presCity = new Cities;
$presState = new States;
$contactArr = array();
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['Users'])) {
$transaction = CActiveRecord::getDBConnection()->beginTransaction();
$contactArr = CommonFunctions::saveContact($_POST['Users']['user_pres_contact'],'user_pres_contact',$errorArr);
$presContact = $contactArr['contact'];
$presCity = $contactArr['city'];
$presState = $contactArr['state'];
$user->attributes = $_POST['Users'];
$user->user_pres_contact_id = $presContact->contact_id;
if($user->save()){
$transaction->commit();
$this->redirect(array('view', 'id' => $user->user_id));
} else {
$transaction->rollback();
}
}
$this->render('createUser', array(
'Users' => $user,
'Users[\'user_pres_contact\']'=>$presContact,
'Users[\'user_pres_contact\'][\'contact_city\']'=>$presCity,
'Users[\'user_pres_contact\'][\'contact_state\']'=>$presState,
));
}
I am able to access only $users but
I m not able to access $Users['user_pres_contact'] in the view
That's because you are assigning them as strings...
The correct way of doing things would be (btw, what you are asking for can't done literally, it is impossible to assign 2 values to one key):
$user = array(
'user_press_contact' => array(
'contact' => $presContact,
'city' => $presCity,
'state' => $presState,
),
);
$this->render('createUser', array(
'Users' => $user,
));
It will give you $Users['user_press_contact']['contact'] for the name in the view, etc.
You can use
$user->getAttributes() //it returns an array of data.
Hope that's usefull
It is possible to solve this using model relations? You can define a relation from the User model to the City model (e.g. naming it relation_to_city), then you can just assign the user model in the controller
$this->render('view', 'user'=>$user);
and access the city (from the view)
$user->relation_to_city