I work on a project, built with Lithium PHP framework and some other libraries like the "Resource" library. And so - I have a controller, that starts with:
<?php
namespace app\controllers\admin;
class Prices extends Base {
protected $_parameters = array(
'index' => array(
'prices' => array(
'required' => false,
'call' => array(
'all',
'conditions' => array(
'advertiser' => 'query:advertiser'
)
)
)
)
);
And the problem is that when I open the url with $_GET parameter advertiser - it is not passed to the model.
BUT - if I hardcode the advertiser ID like this:
...
'prices' => array(
'required' => false,
'call' => array(
'all',
'conditions' => array(
'advertiser' => '123'
)
)
)
and then I get the prices only for this advertiser - as I should.
What could be wrong? ...
You need to setup filter to achieve that, also natebele promised it will refactor li3_resources library to be more flexible:
Here is the link to the filter: https://gist.github.com/nateabele/5667381
It also includes simple use case in code comments if you need one.
Related
I am using the search plugin for CakePHP.
I try to dynamically setup the $filterArgs array that is used for filtering the input from the user. The reason why I want to do this is because my customers can create customer specific input fields. I want to make them filterable and searchable.
Customer.php:
public function beforeFind($queryData) {
$this->filterArgs['garantie'] = array(
'type' => 'subquery',
'method' => 'findCustomerCustomFieldsByText',
'field' => array('Customer.id'),
'encode' => true
);
}
Debugging $filterArgs shows that the entry was made:
array(
'garantie' => array(
'type' => 'subquery',
'method' => 'findCustomerCustomFieldsByText',
'field' => array(
(int) 0 => 'Customer.id'
),
'encode' => true
)
)
Unfortunately the method findCustomerCustomFieldsByText() is not called.
It looks like beforeFind() might not be the correct method to call. What callback-method should I use so I can use dynamic creation of $filterArgs?
Edit:
My question is not identical to the linked question because it is about the callback methods that prevent the filter from working.
I am trying to implement a search with CakeDC's Search plugin. In this search I have a field which has 'multiple' => 'checkbox' is set. This field allows user to select multiple cities so that they can filter results according to city/cities. What I did in favour to this, I simply specified the 'type' => 'IN' for that field in Searchable Model's $filterArgs. But noting happened it just responded with all result no searching/filtration happened. To get the clear picture of what I have implemented here are the code snippets:
Model.php
public $actsAs = array(
'Search.Searchable'
);
public $filterArgs = array(
'city' => array(
'type' => 'in',
'field' => 'Model.city'
));
search_form.ctp
echo $this->Form->create('Model', array('url' => array('controller' => 'models', 'action' => 'search')));
echo $this->Form->input('city', array(
'multiple' => 'checkbox',
'options' => array(
'city1' => 'city1',
'city2' => 'city2',
'cityn' => 'cityn')
));
echo $this->Form->end('search');
ModelsController.php
public function search() {
$this->layout = 'front_common';
$this->Prg->commonProcess();
$this->Paginator->settings = array(
'conditions' => $this->Model->parseCriteria($this->Prg->parsedParams()),
'limit' => 10
);
$this->set('Data', $this->Paginator->paginate());
}
also once I tried to use a beforeFilter() in ModelsController to implode the city array() with (,) to be used with IN but same all results. I want to ask if there is any other plugin to do this or any hack to do this with cakeDC's search plugin. Please help.
This should work fine, assuming you are passing in the arg to parseCriteria() as a simple array of values.
public $filterArgs = array(
array(
'name' => 'city',
'type' => 'value',
'field' => 'Model.city'
)
);
And you should be able to pass city:houston|dallas|austin in the URL
It should parse that into an array of args => [city => [houston, dallas, austin]]
And parseCriteria() will translate that into the following conditions fragment: [Model.city => [houston, dallas, austin]]
And CakePHP natively translates that into a SQL where fragment: IN(houston, dallas, austin)
Use DebugKit and monitor your SQL... you can debug() at any step of the process, you should get these values.
Here's the full docs on the Search plugin:
https://github.com/CakeDC/search/tree/master/Docs/Documentation
(I use it heavily, and I love how it lets me organize all search filters)
I was using Yii's CGridView(actually it's yiistrap's TbGridView), I created a custom CButtonColumn template with a listen button, everything works fine until I found myself copy this code every where I need a listen button for the table list.
array(
'class'=>'bootstrap.widgets.TbButtonColumn',
'template'=>'{listen}{delete}',
'buttons'=>array(
'listen'=>array(
'label'=>'listen',
'options' => array('class'=>'view headphones'),
'icon' => 'icon-headphones',
'url' => '#',
'visible' => '$data->filename_32',
),
),
),
Is there something I can do to make this little piece of code globally configured? Such as:
array(
'template'=>'{listen}{delete}',
'buttons'=>array(
'listen' => 'xxxx.widgets.buttons.Listen',
)
)
Something like this.
You can! In your config/main.php, add:
'components' => array(
'widgetFactory' => array(
'widgets' => array(
'bootstrap.widgets.TbButtonColumn' => array(
'template' => '{listen}{delete}',
'buttons' => array(
'listen' => 'xxxx.widgets.buttons.Listen',
)
),
)
)
),
This method is mainly used to pre-configure internal widgets though, in situations where you can't control the exact class of the widget that'll be loaded. In your case it looks like you specify the widget classname manually though, so simply overriding the TbButtonColumn widget could be an easier and cleaner solution:
class MyTbButtonColumn extends TbButtonColumn {
public $template = '{listen}{delete}';
public $buttons = array(
'listen' => 'xxxx.widgets.buttons.Listen',
);
}
array(
'class' => 'MyTbButtonColumn',
),
I have duplicated data across my config/form_validation.php and my controller.
the field and label from form_validation is the same that I specify in my controller for the id, name and placeholder
Do I have to extract that data to yet a third location and reference it in both of these?
application/config/form_validation.php
$config = array(
'register' => array(
array(
'field' => 'register_username',
'label' => 'Username',
'rules' => 'trim|required|exact_length[5]'
),
.....
application/controllers/mycontroller.php
$this->viewdata['register_username'] = array(
'id' => 'register_username',
'name' => 'register_username',
'type' => 'text',
'placeholder' => 'Username'
);
...
I'm not sure why you have your data duplicated in the controller itself. You might find it easier to use Jamie Rumbelow's model/schema libraries mashup.
This will clean up your model/application structure as a whole. The model extension library itself allows for the automation of CRUD methods.
I created an install script to add two fields to customer using the script below.
But I get this error.
Source model "" not found for attribute "dob_month"
Am I not defining the model in the first line? What does that actually do? What is the best way to fix this?
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttribute('customer', 'dob_month', array(
'label' => 'Month',
'type' => 'varchar',
'input' => 'dropdown',
'visible' => true,
'required' => true,
'position' => 1,
'option' => array (
'value' => array (
'optionone' => array('January'),
'optiontwo' => array('February'),
'optionthree' => array('March'),
'optionfour' => array('April'),
'optionfive' => array('May'),
'optionsix' => array('June'),
'optionseven' => array('July'),
'optioneight' => array('August'),
'optionnine' => array('September'),
'optionten' => array('October'),
'optioneleven' => array('November'),
'optiontwelve' => array('December')
)
)
));
$setup->addAttribute('customer', 'dob_year', array (
'label' => 'Year',
'type' => 'varchar',
'input' => 'text',
'visible' => true,
'required' => true,
'position' => 1
));
If you've already added the attribute, you'll want to use updateAttribute to set the source model value in the eav_attribute table.
<?php
$installer = Mage::getResourceModel('customer/setup','default_setup');
/***
* When working with EAV entities it's important to use their module's setup class.
* See Mage_Customer_Model_Resource_Setup::_prepareValues() to understand why.
*/
$installer->startSetup();
$installer->updateAttribute(
'customer',
'dob_month',
'source_model', //a.o.t. 'source'
'whatever/source_model',
)
$installer->endSetup();
If not, then you can use addAttribute(), which - due to the Mage_Eav setup class' _prepareValues() method - requires an alias for the source_model column as indicated in Alexei's answer ('source' as opposed to 'source_model').
Source model is used when Magento needs to know possible values of your attribute. For example, when rendering dropdown for your attribute. So no, you're not defining it. If my memory doesn't fail me, you can do that by adding 'source' to attribute definition array. Something like:
...
'source' => 'eav/entity_attribute_source_table'
...
That will mean that all your possible options are stored in tables eav_attribute_option and eav_attribute_option. So if your options from install script are successfully added to these tables, that should work. Or you can write your own source model, which I prefer more.