I would like to create a filter where the search would only give me the entries starting with what is searched.
For exemple, I'm searching for a post code starting with "92". With the current filter, it gives me "92000", but also "29200" when I only want the first one.
In SQl it would be "where postcode like $value%" or something like that.
Edit after the 2 first answers:
I tried the custom callback. But the exemple is a for a linked entity displayed as a checked box, and I just want a "where like something%" on a field in the entity. No leftjoin !
Here is my code so far, but I get "Warning: Illegal string offset 'value'"
$this->datagrid->add('postCode', 'doctrine_orm_callback', array(
'callback' => function($queryBuilder, $field, $value) {
if (!$value['value']) {
return;
}
$queryBuilder->andWhere('s.postCode like :value');
$queryBuilder->setParameter('value', $value);
return true;
}
));
The field is 'postCode' in the entity 'Trainer'
You need a "custom callback filter" to set the rules you need to the queryBuilder.
It is well covered in Sonata documentation on filters.
I had given up on this feature for a while, but then I tried to solve this again, and bam ! it works ! So here is my solution in case anybody needs it:
$this->datagrid->add('postCode', 'doctrine_orm_callback', array(
'callback' => function($queryBuilder, $alias, $field, $value) {
if (empty($value['value'])) {
return;
}
$queryBuilder->where('t.postCode LIKE :postcode');
$queryBuilder->setParameter('postcode', $value['value'].'%');
$queryBuilder->orderBy('t.postCode', 'ASC');
return true;
},
'field_type' => 'text'
));
Related
I made module with form, that use autocomplete field like that:
$form['field_taxonomy_tags'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'taxonomy_term',
'#selection_settings' => [
'target_bundles' => array('tags'),
],
'#autocreate' => array(
'target_bundles' => array('tags'),
'bundle' => ('tags'),
),
'#title' => ('tags'),
'#tags' => TRUE,
];
Autocomplete works fine, and i can add taxonomy terms from tags vocabulary easily. But there is some problem with #autocreate option i think. Have searched all documentation, and code inside drupal core. Entity is never created ;/
When i try to get value from this field, my browser is dead... there is some entity type variable, but huge.
After some debugging i found way to get it work, but im not happy about it :) Very strange, maybe some of you guys can help me to find better way?
public function submitForm(array &$form, FormStateInterface $form_state) {
$tags = $form_state->getValue('field_taxonomy_tags');
foreach ($tags as $tag)
{
if(is_object($tag['entity']))
{
$tag['entity']->save();
}
}
}
As you can see, I need to save those tags manually, dont know why ;/ Without it, there is no term created.
It is better way. I dont need to save every tag, its enough if we attach them to a node. Its entity object, that can be passed as node value, and after that, all tags will be created:
$node = Node::create(array(
'type' => 'YOUR_content_type',
'title' => $form_state->getValue('title')
));
$fieldNames = array_keys($node->getFieldDefinitions());
$values = $form_state->getValues();
// be aware with that, i use this loop for testing because i have same names
// you can use $node->set('content type field name', $value); directly without any field definitions
foreach ($values as $key=>$value)
{
if(in_array($key, $fieldNames))
{
$node->set($key, $value);
}
}
// here we save all data, taxonomy entities too
$node->save();
Obviously, I can't do this, but is there some way to achieve what I am trying to? I only found can not do's online, but no potential workarounds.
Here is what I am trying to do.
Currently I get the following error... "Cannot use [] for reading"
For my theme, I have a framework and the fields from that framework are built using an array that I create.
It looks something like this (minus the 300+ lines of code that I actually use)...
$options[] =
array(
'title' => 'This Field Tab Title',
'name' => 'this-field-tab-slug',
'fields' =>
array(
// ----------------------------------------------------------------------
// This Field Option Name
// ----------------------------------------------------------------------
array(
'type' => 'this_field_type',
'id' => 'this_field_types_id',
),
// ----------------------------------------------------------------------
// This Field Option Name
// ----------------------------------------------------------------------
array(
'type' => 'this_field_type',
'id' => 'this_field_types_id',
),
// ----------------------------------------------------------------------
// This Field Option Name
// ----------------------------------------------------------------------
array(
'type' => 'this_field_type',
'id' => 'this_field_types_id',
),
),
);
I am running a grouped field type, so my output has many options/fields within this grouped field/area which can then be added again and again as many times as the user needs. Then I am repeating that whole process/code again but for other taxonomies of the user's site.
So for example, the whole process above applies to post types, categories, tags, archived, etc. etc. So instead of having thousands of lines of repetitive codes, I'm trying to create my own function and pass the variables to that function.
But for the function, I find I can't return $options[];
Here is a screenshot of what I mean by the grouped field that can be added as many times as the user needs.
And here's an example of the function I am trying to create!
public static function layout_settings_config($title_name = '', $title_slug = '', $title_id = '', $query = '') {
$title_name = 'Post Type';
$title_slug = 'post-type';
$title_id = 'post_type';
$query = 'post_types';
$options[] =
array(
// all the config array codes in here...
);
return $options ??? $options[]; doesn't work.
}
Is this possible to achieve what I am trying to a different way? I'm still a little new to creating my own functions and OOP, but nothing I find online for this specific issue with a workaround.
Thanks!
$options[] is not object but it is an operation like function.
You should return $options instead.
and, by the way, when you say $options[] = something. it actually insert something inside an array called $option. so effectively you have to access your options like this.
$option[0]->title.
So I suggest Instead of making it complex like this. simply say
$option = something.
I have trouble with search feature in sugarcrm modules, I always use %-sign in field box example: %john to show search result, i need only john not %john
I was edit my file at /modules/Accounts/Account.php at method:
function build_generic_where_clause ($the_query_string) {
$where_clauses = Array();
$the_query_string = $GLOBALS['db']->quote($the_query_string);
array_push($where_clauses, "accounts.name like '%$the_query_string%' ");
if (is_numeric($the_query_string)) {
array_push($where_clauses, "accounts.phone_alternate like '%$the_query_string%'");
array_push($where_clauses, "accounts.phone_fax like '%$the_query_string%'");
array_push($where_clauses, "accounts.phone_office like '%$the_query_string%'");
}
and edit /modules/Accounts/metadata/SearchFields.php at
'name' => array( 'query_type'=>'default', 'operator' => 'like'),
But Always fail,
Do you have solution for this?
Solution
I edited my config.php and added 'search_wildcard_infront' => true
Regards,
Rampak
Im using drupal 7
I have a date field.
Which displays the date selected as it is supposed to.
However I would to change the display to say 'this date is almost over' under certain php validation or 'this date is now closed' under different validation.
I cant use string over reides as it doesnt accept php. Would I have to use a custom module and use hook form alter or node api?
thanks for any help
Yes, you would have to use a module to adjust how the image field is displayed. You can either create a new display format using hook_field_formatter_info() along with hook_field_formatter_view(), or you can hook an existing display using hook_field_formatter_view() by checking $display['type']. I would recommend the former.
Here is an example of how the two hooks could work together:
function modulename_field_formatter_info()
{
return array(
'modulename_formatter' => array(
'label' => t('Custom Date Format'),
'field types' => array('date'),
),
);
}
function modulename_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display)
{
if ($display['type'] != 'modulename_formatter')
return;
foreach ($items as $delta => item)
{
if ($item['date'] < time()) //Or 'datetime' or 'datestamp'
$element[$delta]['#markup'] = 'this date is now closed.';
}
return $element;
}
I might have some of the indices wrong, but they should be pretty close.
http://api.drupal.org/api/drupal/modules!field!field.api.php/function/hook_field_formatter_info/7
http://api.drupal.org/api/drupal/modules!field!field.api.php/function/hook_field_formatter_view/7
I'm using CakePHP 1.3.8, and I've installed the CakeDC Search plugin. I have a Tutorial model, which is in a HABTM relationship with a LearningGoal model.
I have a search action & view in the Tutorials controller with which I can successfully search fields in the Tutorial model. I'd also like to filter my tutorial search results using LearningGoal checkboxes on the same form. I've tried adding various parameters to Tutorial's $filterArgs and TutorialsController's $presetVars. I've also tried moving the relevant $filterArgs to the LearningGoal model. I have not yet been able to successfully trigger the entry for learning goals in $filterArgs.
I think I must be missing something obvious. Or maybe the Search plugin doesn't support what I'm trying to do. Does anyone know how to use this plugin to search on associated models?
So here's what I've figured out. You can combine what's below with the Search plugin directions to search on related models.
The $filterArgs piece in the Tutorial model must look like this:
var $filterArgs = array(
array('name' => 'LearningGoal', 'type' => 'subquery', 'method' => 'findByLearningGoals', 'field' => 'Tutorial.id'),
);
Here's the supporting function in the Tutorial model:
function findByLearningGoals($data = array()) {
$ids = explode('|', $data['LearningGoal']);
$ids = join(',', $ids);
$this->LearningGoalsTutorial->Behaviors->attach('Containable', array('autoFields' => false));
$this->LearningGoalsTutorial->Behaviors->attach('Search.Searchable');
$query = $this->LearningGoalsTutorial->getQuery('all',
array(
'conditions' => array('LearningGoalsTutorial.learning_goal_id IN (' . $ids . ')'),
'fields' => array('tutorial_id'),
)
);
return $query;
}
In TutorialsController, $presetVars should look like this:
public $presetVars = array(
array('field' => 'LearningGoal', 'type' => 'checkbox', 'model' => 'Tutorial'),
);
And in my search action in TutorialsController, I did this:
$this->LearningGoal = $this->Tutorial->LearningGoal;
The Prg component seems to need that.
I am using CakePHP version 2.X
Every time I come to do this in a project I always spend hours figuring out how to do it using CakeDC search behavior so I wrote this to try and remind myself with simple language what I need to do. I've also noticed that although Michael is generally correct there is no explanation which makes it more difficult to modify it to one's own project.
When you have a "has and belongs to many" relationship and you are wanting to search the joining table i.e. the table that has the two fields in it that joins the tables on either side of it together in a many-to-many relationship you want to create a subquery with a list of IDs from one of the tables in the relationship. The IDs from the table on the other side of the relationship are going to be checked to see if they are in that record and if they are then the record in the main table is going to be selected.
In this following example
SELECT Handover.id, Handover.title, Handover.description
FROM handovers AS Handover
WHERE Handover.id in
(SELECT ArosHandover.handover_id
FROM aros_handovers AS ArosHandover
WHERE ArosHandover.aro_id IN (3) AND ArosHandover.deleted != '1')
LIMIT 20
all the records from ArosHandover will be selected if they have an aro_id of 3 then the Handover.id is used to decide which Handover records to select.
On to how to do this with the CakeDC search behaviour.
Firstly, place the field into the search form:
echo $this->Form->create('Handover', array('class' => 'form-horizontal'));?>
echo $this->Form->input('aro_id', array('options' => $roles, 'multiple' => true, 'label' => __('For', true), 'div' => false, true));
etc...
notice that I have not placed the form element in the ArosHandover data space; another way of saying this is that when the form request is sent the field aro_id will be placed under the array called Handover.
In the model under the variable $filterArgs:
'aro_id' => array('name' => 'aro_id', 'type' => 'subquery', 'method' => 'findByAros', 'field' => 'Handover.id')
notice that the type is 'subquery' as I mentioned above you need to create a subquery in order to be able to find the appropriate records and by setting the type to subquery you are telling CakeDC to create a subquery snippet of SQL. The method is the function name that are going to write the code under. The field element is the name of the field which is going to appear in this part of the example query above
WHERE Handover.id in
Then you write the function that will return the subquery:
function findByAros($data = array())
{
$ids = ''; //you need to make a comma separated list of the aro_ids that are going to be checked
foreach($data['aro_id'] as $k => $v)
{
$ids .= $v . ', ';
}
if($ids != '')
{
$ids = rtrim($ids, ', ');
}
//you only need to have these two lines in if you have not already attached the behaviours in the ArosHandover model file
$this->ArosHandover->Behaviors->attach('Containable', array('autoFields' => false));
$this->ArosHandover->Behaviors->attach('Search.Searchable');
$query = $this->ArosHandover->getQuery('all',
array(
'conditions' => array('ArosHandover.aro_id IN (' . $ids . ')'),
'fields' => array('handover_id'), //the other field that you need to check against, it's the other side of the many-to-many relationship
'contain' => false //place this in if you just want to have the ArosHandover table data included
)
);
return $query;
}
In the Handovers controller:
public $components = array('Search.Prg', 'Paginator'); //you can also place this into AppController
public $presetVars = true; //using $filterArgs in the model configuration
public $paginate = array(); //declare this so that you can change it
// this is the snippet of the search form processing
public function admin_find()
{
$this->set('title_for_layout','Find handovers');
$this->Prg->commonProcess();
if(isset($this->passedArgs) && !empty($this->passedArgs))
{//the following line passes the conditions into the Paginator component
$this->Paginator->settings = array('conditions' => $this->Handover->parseCriteria($this->passedArgs));
$handovers = $this->Paginator->paginate(); // this gets the data
$this->set('handovers', $handovers); // this passes it to the template
If you want any further explanation as to why I have done something, ask and if I get an email to tell me that you have asked I will give an answer if I am able to.