Giter VIP home page Giter VIP logo

search's Introduction

CakeDC Search Plugin

Bake Status Downloads Latest Version

This Search plugin enables developers to quickly implement the POST-Redirect-GET pattern.

The Search plugin is an easy way to implement PRG in your application, and provides you with a paginate-able search in any controller. It supports simple methods to search inside models using strict and non-strict comparing, but also allows you to implement any complex type of searching.

  • PRG Component: The component will turn GET parameters into POST to populate a form and vice versa.
  • Search Behaviour: The behavior will generate search conditions passed in the provided GET parameters.

This is not a Search Engine or Index

As mentioned before, this plugin helps you to implement searching for data using the PRG pattern. It is not in any way a search engine implementation or search index builder, although it can be used to search an index such as Elastic Search or Sphinx.

Requirements

  • CakePHP 2.5+
  • PHP 5.2.8+

Documentation

For documentation, as well as tutorials, see the Docs directory of this repository.

Support

For bugs and feature requests, please use the issues section of this repository.

Commercial support is also available, contact us for more information.

Contributing

This repository follows the CakeDC Plugin Standard. If you'd like to contribute new features, enhancements or bug fixes to the plugin, please read our Contribution Guidelines for detailed instructions.

License

Copyright 2007-2014 Cake Development Corporation (CakeDC). All rights reserved.

Licensed under the MIT License. Redistributions of the source code included in this repository must retain the copyright notice found in each file.

search's People

Contributors

adambrett avatar admad avatar ajibarra avatar alaaattya avatar andrej-griniuk avatar ceeram avatar davidyell avatar dogmatic69 avatar evilbloodydemon avatar fabiokr avatar htstudios avatar jameswatts avatar josegonzalez avatar joshuapaling avatar lorenzo avatar majna avatar matayoshi avatar oldskool avatar phpnut avatar predominant avatar ravage84 avatar rchavik avatar real34 avatar renan avatar richerlariviere avatar skie avatar steinkel avatar yeliparra avatar zeroasterisk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

search's Issues

query filter array_merge vs array_merge_recursive

Maybe in SearchableBehavior.php in function _addCondQuery() better way to use array:merge_recursive.

If you had more than one custom search query what filling up 'OR' or 'AND' conditions, the last one overwrites the conditions what was set before.

Variable cannot be unset when using filterEmpty

When a dropdown is used to set a filter value from a form, it works as expected. It filters the find results with the value from the selected option. However, when you want to unset the value by selecting the "empty" option, combined with setting the allowEmpty option of the commonProcess handler, the value is not unset, rather the last selected value is kept.

Example:
When I filter my invoices/index action on customer_id:1, it shows me only the invoices for customer 1. All good so far. Now when I select my All customers option, which is the "empty" option of my FormHelper generated drowdown, after submitting the form I get redirected back to: invoices/index/customer_id:1.

When I unset the filterEmpty option, or set it to false. I get redirected to invoices/index/customer_id: and the list is properly "unfiltered", which is the expected behaviour. This just doesn't seem to work together.

Searching multiple object types at once?

I'm looking to implement Search, but I am hoping to use a single form and text field to search multiple object types. A person might type "haircut", and I want to match both Companies called "Haircuts inc" and ServiceTypes called "Haircuts", and present them in a unified search result.

My instinct is that this component probably isn't appropriate for that -- it really seems to want a separate form and result for each object type. But I'm a bit of a CakePHP newb, and may be missing something. Can someone confirm/explain/refute/help?

one search bar but search using `LIKE` in different fields of different tables

I have the following

Employee hasOne EmployeeProfile
Employee hasMany Qualification

So I have a single search bar.

the search bar will search using LIKE through the following fields
Employee.name
EmployeeProfile.email
Qualification.title

how do I configure the model Employee->filterArgs for this search?

Thank you!

How do I add a permanent condition in the controller?

This is my permanent condition:
$this->Paginator->settings = (array(
'conditions' => array('SurveyReport.user_id' => $user_id),
'order' => array('SurveyReport.id' => 'desc')
));

This is the search in my controller:
$this->SurveyReport->validate = array(); // Stop validation.
$this->Prg->commonProcess();
$this->Paginator->settings['conditions'] = $this->SurveyReport->parseCriteria($this->Prg->parsedParams());

multiple condition on same field

what I did:

$filterArgs = array(
'search_exact_beginning' => array('field' = 'name', 'type' => 'like', 'before' => false),
'search_exact_end' => array('field' = 'name', 'type' => 'like', 'after' => false),
);

I expected I can create query like this

SELECT * FROM users WHERE name LIKE 'john%' and name LIKE '%doe'

What happened: when i fill the field 'search_exact_end' the second conditions overwrite the fisrt and the query doesn't take account of the first LIKE

I resolved changing this line in _addCondLike function from

$cond[$fieldName . " LIKE"] = $field['before'] . $value . $field['after'];

to

$cond[] = array( $fieldName . " LIKE" => $field['before'] . $value . $field['after']);

It works for me but I don't know if it affects the behaviors

PRG Component Issue

Well I am not sure what could be the issue.
I have a search implemented using this plugin.
As CakeDC search uses Post to Get behaviour using PRG component,it works fine on my localhost server but when I deploy on Live server it probably stops working...as when I check the request type in controller function, it remain POST instead of being GET,
while at localhost it does become GET.

Let me know what could be the issue, as its working at localhost.
My localhost is wamp and deployment is a linux hosting server.

filterArgs for subquery must have a name

Currently, the filterArgs for a subquery must have a name attribute, though the readme indicates that is optional if it matches the key name.

your unit test specifies the 'name' attribute:
http://screencast.com/t/tMsxur1J1eM

but the readme says:

Each filter record should contain array with several keys:
* name - the parameter stored in Model::data. 
  In the example above the 'search' name used to search 
  in the Article.description field (can be ommited if they key is the name).

This is causing my unit tests to fail:
http://screencast.com/t/n3kgiUP5J7

Please either update the documentation to make name required, or update the code to extract/autoset from the key if not otherwise specified.

paginate() on a non-object error in find()

the old find function works however the new paginator is returning non-object error.
2013-10-28 07:33:41 Error: [FatalErrorException] Call to a member function paginate() on a non-object

old one
public function find() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->Event->parseCriteria($this->Prg->parsedParams());
$this->set('events', $this->paginate());
}

new one
public function find() {
$this->Prg->commonProcess();
$this->Paginator->settings['conditions'] = $this->Event->parseCriteria($this->Prg->parsedParams());
$this->set('events', $this->Paginator->paginate());
}

Search Not Working

I am having diffculty getting the search plugin to work with my code:

Here's my model code:

App::uses('Security', 'Utility');
App::uses('SearchableBehavior', 'Search.Model/Behavior');
App::uses('AppModel', 'Model');

class Venue extends AppModel {

public $name = 'Venue';
public $actAs = array(
'Containable',
'Search.Searchable');

public $filterArgs = array(
'name' => array('type' => 'like')
);

//Controller code:

public function find(){
$this->Prg->commonProcess();
$this->Paginator->settings['conditions'] = $this->Venue->parseCriteria($this->Prg->parsedParams());
$this->set('venues', $this->Paginator->paginate());
}

//View code
echo $this->Form->create('Venue', array(
'url' => array_merge(array('action' => 'find'), $this->params['pass'])
));
echo $this->Form->input('name', array('div' => false));
echo $this->Form->submit(__('Search'), array('div' => false));
echo $this->Form->end();

Error recieved:
Notice (8): Array to string conversion [CORE\Cake\Model\Datasource\DboSource.php, line 460]
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'parseCriteria' at line 1
SQL Query: parseCriteria

Cannot send search params = 0

Reported by Predominant | January 13th, 2011 @ 01:30 AM

trying to search my db for status = 0

using search plugin, status:0 evaluates to empty and does not get passed into the search conditions

in my case it is a query, so the issue lies on like 266 of searchable.php
if ((method_exists($model, $field['method']) || $this->__checkBehaviorMethods($model, $field['method'])) && !empty($data[$field['name']])) {

(Migrated from Github issues)

Option to dynamically change query keyword

I am building a search engine and I have an interesting query to be made.
User can search with combination of keyword(s).
I want the flexibility to dynamically try and test the different combinations. For instance, if someone searches for "Hello World",

This plugin gives an option to search for "Hello World%", "%Hello World", "%Hello World%", using connectors, etc.

But, in controller I can only do :

 public function find() {
        $this->Prg->commonProcess();
        $this->paginate['conditions'] = $this->Model->parseCriteria($this->Prg->parsedParams());
        $this->set('articles', $this->paginate());
    }

However, I can only use 'either' of combinations i.e. before => true or after => true .
I need the ability to loop through and switch from before => true to after => true if before true could not find any good results. Also, if there are 2 or more words, maybe an ability to add a wildcard in between?
but, if there are no results and say, I want to change and if I do:

if(empty($this->paginate())) { //change query and loop through $this->Prg->commonProcess() }

It just doesn't work!

Maybe an option to instantiate this plugin from outside and then dropping the object to pick up another?

PS: I don't know where to add the label - I would add it as a feature request 👍

Using search with unit testing

Hi, I'm trying to use the search plugin within a testcase.
My controller contains:

        $this->Gasto->recursive = 0;
        $this->Prg->commonProcess();
        $this->Paginator->settings = $this->paginate;
        $this->Paginator->settings['conditions'] =  $this->Gasto->parseCriteria($this->Prg->parsedParams());

And in my test:

        $fini = new DateTime('now');
        $fini->setDate( 2014, 1, 1 );
        $ffin = new DateTime('now');
        $ffin->setDate( 2014, 1, 31 );
        $data = array(
          'Gasto' => array(
              'fecha_max' => $fini->format( 'j-m-y' ),
              'fecha_min' => $ffin->format( 'j-m-y' ),
              'categoria_gasto_id' => '',
          'usuario_id' => '',
          'pagado' => ''
          )
        );
        $this->testAction( '/gastos/index',
                array( 'data' => $data,
                       'method' => 'GET'
                )
        );
        $this->assertGreaterThanOrEqual( 0, count( $this->vars['gastos'] ) );
        foreach( $this->vars['gastos'] as $gasto ) {
            $f = new DateTime( $gasto['Gasto']['fecha'] );
            $this->assertGreaterThanOrEqual( $fini, $f );
            $this->assertLessThanOrEqual( $ffin, $f );
        }

But in the returned data never get's applied the search params... the test always fails in the first assert inside the foreach.
I've tried using GET and POST as methods but with the same result.
Using the methor with the web interface applies the filters correcty, so it's this a problem with my approach or a conflict with PRG approach used in conjuntion with phpunit?

method search : return getQuery is slow ?

I tested with table mangas and mangas_genre that each has 7000 rows ( but don't index )
array('name' => 'genres', 'type' => 'subquery', 'method' => 'findByGenres', 'field' => 'Manga.id').

function findByGenres($data = array()) {
$this->bindModel(array('hasOne' => array('MangasGenre')));
$this->MangasGenre->Behaviors->attach('Search.Searchable');
$genres = explode('|', $data['genres']);
$query = $this->MangasGenre->getQuery('all',array(
'fields'=>'manga_id',
'conditions'=>array('genre_id'=>$genres),
'group'=>'manga_id HAVING COUNT(genre_id) =' . count($genres)
));
return $query;
}

is very very slow .But
function findByGenres($data = array()) {
$this->bindModel(array('hasOne' => array('MangasGenre')));
$genres = explode('|', $data['genres']);
$ids = $this->MangasGenre->find('list', array(
'fields' => 'manga_id',
'conditions' => array('genre_id' => $genres),
'group' => 'manga_id HAVING COUNT(genre_id) =' . count($genres)
));
if (empty($ids))
return 0;
return implode(',', $ids);
}
result <100ms

I think you can consider this matter.

Bug with PRG::CommonProcess not encoding inputs

Reported by Dunhamzzz | July 26th, 2011 @ 04:43 AM

There is a problem with the PRG::commonProcess() in that it does not encode the inputs it passes from $_GET to $params.

If an URL contains a % sign, it breaks apache(possibly others) and it throws a 400 bad request error. This problem arises when someone inputs a % sign and the PRG:commonProcess() turns this from ?foo=bar% to /foo:bar%

Complicated Search and Need Advice

I have what has turned into a pretty complicated search, but I'm thinking that I may be overcomplicating it a bit. I've added the methods that I'm using below and if you have the time, I'd really appreciate any advice on how to simplify it.

Model code:
https://gist.github.com/robksawyer/964415231b52f9183501

Controller code:
https://gist.github.com/robksawyer/dea603bede9d6cb74a29

Applicable Search Form View code:
https://gist.github.com/robksawyer/e59bc16ec4e6fd74d51c

Search in multiple models

How do I search in multiple tables and return on a single page, for example tables have the news, galleries, calendar items and would like to do a search on all of them and return in one place, it is possible with this plugin?

Someone who did could post an example please.

Numeric 0 in a field form is interpreted as empty field

I made a field of type 'int':

public $presetVars = array(
  array('field' => 'number', 'type' => 'value'),
  ...
}

When I type 0 in that search form field, the search plug-in ignores it. It works fine when I type any other number.

Does VirtualField not allowed?

app/Model/User.php

public $virtualFields = array( 'age' => "TRUNCATE((date_format(CURRENT_DATE, '%Y%m%d')-date_format(birthday, %Y%m%d'))/10000, 0) );

this is getting age from birthday.

Browser output errors like this.

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'User.age' in 'where clause'

SQL select field name was not correct.

(TRUNCATE((date_format(CURRENT_DATE, '%Y%m%d')-date_format(birthday, '%Y%m%d'))/10000, 0)) AS User__age

What is "User__age" field ?

Regards.

$this->params['pass'] vs. $this->params['named']

I recently synced my fork and I'm now having some issues. I'm wondering, if I'm using the plugin https://github.com/pedroelsner/filter_results, should I be using $this->params['named'] in place of $this->params['pass']? At the moment, my queries are NOT being parsed when I run $this->Prg->commonProcess(); and $this->Prg->parsedParams().

array_merge(array('action' => 'index'), $this->params['pass']);

Update: I just realized that maybe you meant to use $this->request->params['pass'] instead of $this->params['pass']. This would make more sense, right? http://book.cakephp.org/2.0/en/development/routing.html#passed-arguments

cannot send search params = 0

trying to search my db for status = 0

using search plugin, status:0 evaluates to empty and does not get passed into the search conditions

in my case it is a query, so the issue lies on like 266 of searchable.php
if ((method_exists($model, $field['method']) || $this->__checkBehaviorMethods($model, $field['method'])) && !empty($data[$field['name']])) {

Method search : return getQuery is slow ?

Reported by Pierre Martin | January 13th, 2011 @ 01:32 AM

Original ticket posted on Github, by meotimdihia

I tested with table mangas and mangas_genre that each has 7000 rows ( but don't index )
array('name' => 'genres', 'type' => 'subquery', 'method' => 'findByGenres', 'field' => 'Manga.id').

function findByGenres($data = array()) {
    $this->bindModel(array('hasOne' => array('MangasGenre')));
    $this->MangasGenre->Behaviors->attach('Search.Searchable');
    $genres = explode('|', $data['genres']);
    $query = $this->MangasGenre->getQuery('all',array(
        'fields'=>'manga_id',
        'conditions'=>array('genre_id'=>$genres),
        'group'=>'manga_id HAVING COUNT(genre_id) =' . count($genres)
    ));
    return $query;
}

is very very slow .But

function findByGenres($data = array()) {
    $this->bindModel(array('hasOne' => array('MangasGenre')));
    $genres = explode('|', $data['genres']);
    $ids = $this->MangasGenre->find('list', array(
                'fields' => 'manga_id',
                'conditions' => array('genre_id' => $genres),
                'group' => 'manga_id HAVING COUNT(genre_id) =' . count($genres)
            ));
    if (empty($ids))
          return 0;
    return implode(',', $ids);
}

result <100ms

I think you can consider this matter.

Search genres Film

Reported by Pierre Martin | January 13th, 2011 @ 01:29 AM

Original ticket posted on Github, by meotimdihia

genre is an array of Genre.id

if i only search name but dont search genre : errors: Undefined index: genres
search plugin must have data of all field in $presetVars ?

in the Controller

public $presetVars = array(
    array('field' => 'name', 'type' => 'value'),
    array('field'=>'genres','type'=>'checkbox')
);

in view.ctp

echo $form->input('Film.genres',array('type'=>'select','multiple' => 'checkbox','options'=>array(1=>'adventure',2=>'action')));

Error can be fixed with:

if (empty($this->data['Film']['genres']))
  $this->data['Film']['genres'] = null;

support for bootstrap tabs

Now i have to manually catch and do some actions with url, because when i have two paginators on two different tabs (in same view), first one after search action add his fieldset url, and when i change tab and use next paginator it adds url to previous one and as result i have very long paginator with database error ;<

Highlight results of the search

Related to my call for help ( #142 ) one of the things I was doing with php code was the highlighting of the resulting coincidences with a code like this:
while($row = mysql_fetch_array($result)){ echo ".str_replace($word,"<hl>$word</hl>",$row['entry'])." - ".str_replace($word,"<hl>$word</hl>",$row['lemma_tag'])." }
So the question is how can achieve this using search plugin, or it is not related?, So far I have found that exists a helper called Text that enables highlighting, but again I'm short in well understanding of it, some advice?

merged fields search (e.g. first_name last_name)

Hi. Recently found this awesome plugin, was wondering how to configure to find by name which merges across first and surname.

This doesn't work so well as you can find ali bakir by search "ali" or "bakir" but not "ali bakir":
'name' => array('type' => 'like','field'=>array('User.first_name','User.last_name')),

Is there a way?
Thanks

Small code error

I just want to highlight that there is a small code error where you have:

$this->paginate['conditions'] = $this->Article->parseCriteria($this->passedArgs);

Instead, it should be $this->paginate = array('conditions' => $this->Article->parseCriteria($this->passedArgs));

Your version of it gives and "Invalid $paginate modification error".

Issue on searching under several query-like fields

I'll try to describe what I've discover, and how I did to manage it.


Assumptions


You are familiar with cakephp, php language, and capable of understand pseudo-code explanations written very very late :)


Issue


Suppose I want to search in some model, by two fields simultaneously. Let's call them A and B. In the corresponding model, both are specified as of type "query" in the $filterArgs array: this is, both need methods which implement the conditions to be performed in the underlying real query. Let's call those methods filterA and filterB.

The problem I found rises (in its simple case/flavour) when both methods (filterA and filterB) return an array indexed by the exact same key. For example, let's say that methods filterA and filterB return something like

  function filterA($data, $field){

            ... code ...

    return array(
        'OR' => array(
                         .... conditions regarding A ...
             );
  }

  function filterB($data, $field){

            ... code ...

    return array(
        'OR' => array(
                         .... conditions regarding B ...
             );
  }

If you examine the current implementation of the searchable behaviour (under /plugins/search/models/behaviours/searchable.php), you will notice that every array obtained by calling this methods are merged all-together in the following fashion:

protected function _addCondQuery(Model $model, &$conditions, $data, $field) {
    if ((method_exists($model, $field['method']) || $this->__checkBehaviorMethods($model, $field['method'])) && !empty($data[$field['name']])) {
        $conditionsAdd = $model->{$field['method']}($data);
        $conditions = array_merge($conditions, (array)$conditionsAdd);
    }
    return $conditions;
}

the problem (which has nothing to do with the plugin) is that array_merge function will not work as expected. If you check its oficial specification at http://www.php.net/manual/en/function.array-merge.php, you will find this paragraph:

[quoting]
"Merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.

If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended."
[/quoting]

So what's happening right now with the plugin: if something like my example happens, the search will simply be performed just under the last field queried/submitted. The first one is just overwrittern by the second. And all because of the array_merge function.


My solution


By checking cakephp cookbook on how to build complex conditions for querying, I did notice that when you want to perform this kind of queries, you need to build it in a "onion" or "wrapped" fashion. The idea is to begin with conditions, and when you face a collision, then wrap the current set of conditions under an "AND" array, and just after that perform the merging of conditions. Let me depict it to make it just a little clearer:

[example]
I want to query under " (p1 OR p2) AND (p3 OR p4) AND p5"

//1st stage: add p5
$conditions = array(
p5
);
result (looking inside $conditions):
[0] => p5

//2nd stage: add (p3 OR p4)
$conditions['OR'] = array(p3, p4);
result (looking inside $conditions):
'OR' => (p3,p4)
[0] => p5

//3rd stage: add (p1 OR p2)
CANNOT DO
$conditions['OR'] = array(p1, p2);
result (looking inside $conditions):
'OR' => (p1,p2)
[0] => p5
(p3 OR p4 is LOST... this is what array_merge is doing)

WHAT YOU SHOULD DO
$conditions['AND'] = $conditions;
$conditions['OR'] = array(p1,p2);
result (looking inside $conditions):
'OR' => (p1,p2)
'AND' => [
'OR' => (p3, p4)
[0] => p5
]

[/example]

I implemented the above solution by updating the _addCondQuery function. Before sharing it, I would like to discuss it just a little further, so when you read my patch you understand it. I hope by this point you are not lost nor bored nor aslept. Well, by this time you should have the idea that upon a collision of keys (logical operators, such as 'OR'), the idea is to wrap the existing conditions, and then add the new one. Ok, this might work... but there's more. If you remember the default representation of conditions in cakephp,

$conditions = array( p1, p2, p3, .... )

there's an implicit operator always present: yes, the logical 'AND'. The problem with this is... suppose we face a collision on 'AND' keys! . By following the above procedure, we should wrap existing conditions inside an array under an 'AND' key, and then add the new set of conditions under ... an 'AND' key! . Got the problem? not yet? ... yesssss! the problem is that the new set of conditions WILL OVERWRITE the former set of conditions that were wrapped. Ok, this is a problem, but an easy one to solve: instead of wrapping and merging, we just need to merge both sets of conditions. The argument for this is we are operating under AND operators all the time, at the biggest ultimate level.

Well, the updated function looks like this. And it worked for me under several escenarios and apps.

protected function _addCondQuery(Model $model, &$conditions, $data, $field) {
    if ((method_exists($model, $field['method']) || $this->__checkBehaviorMethods($model, $field['method'])) && !empty($data[$field['name']])) {
        $conditionsAdd = $model->{$field['method']}($data);
        $keyAdd = array_keys($conditionsAdd);
        foreach($keyAdd as $key2add){
            if( array_key_exists($key2add, $conditions) ){
                //cannot array_merge(), because existing conditions 
                //under $key2add in $conditions array will be overwritten
                if( $key2add == 'AND' ){
                    //add this set of conditions to existing $conditions['AND']
                    $conditions['AND'] = array_merge( $conditions['AND'], $conditionsAdd['AND'] );
                    //delete value from $conditionsAdd (they're now under $conditions['AND']
                    unset( $conditionsAdd['AND'] );
                }else{
                    //wrapp them
                    $conditions['AND'] = array( $conditions ); // no keys in this wrapper, so no future collission                      
                }
            }
        }
        $conditions = array_merge($conditions, (array)$conditionsAdd);
    }
    return $conditions;
}

Search after a primary key value

Reported by Andreas | April 19th, 2011 @ 08:30 AM

Hallo!

I have implemented a search form with your plugin which works great for (nearly) every value of my MySQL table.

But I would like to search after my primary key which is an integer and unfortunately it's not visible
on the form. The html code also shows that this part is hidden:

<input type="hidden" name="data[Store][kdnr]" id="StoreKdnr" />

So why?

I have implemented the following parts:

Model:

public $filterArgs = array(
            array('name' => 'kdnr', 'type' => 'like'),
            array('name' => 'name', 'type' => 'like'),
            array('name' => 'city', 'type' => 'like'),
            array('name' => 'zip', 'type' => 'like'),
            array('name' => 'street', 'type' => 'like'),
            array('name' => 'tel', 'type' => 'like'),
        );

Controller:

public $presetVars = array(
        array('field' => 'kdnr', 'type' => 'int'),
        array('field' => 'name', 'type' => 'value'),
        array('field' => 'stadt', 'type' => 'value'),
        array('field' => 'zip', 'type' => 'value'),
        array('field' => 'street', 'type' => 'value'),
        array('field' => 'tel', 'type' => 'value')
    );

View:

<?php
    echo $this->Form->input('kdnr', array('div' => false));
    echo $this->Form->input('name', array('div' => false, 'maxLength' => 50));
    echo $this->Form->input('city', array('div' => false, 'maxLength' => 50));
    echo $this->Form->input('zip', array('div' => false, 'maxLength' => 5));
    echo $this->Form->input('street', array('div' => false, 'maxLength' => 40));
    echo $this->Form->input('tel', array('div' => false, 'maxLength' => 30));
?>

Any help would be great.

Thanks in advance!

Andreas

Encode search parameters.

I implemented the search plugin in my cakephp app, with a very similar config than in the documentation example.

It works fine, but when I type the '%' character in a form field, I get a "400 Bad Request" error. ¿Can be this an issue of the search plugin?

CakePHP version is 1.3.2.

subquery error on PostgreSQL

I'm using CakPHP 2.3.7 with PostgreSQL 9.1.4 and try to do subquery. I got an error SQLSTATE[42P01]: Undefined table:.

According to this page, it seems need DboSource::expression(). So I changed like this on SearchableBehavior::_addCondSubquery() line 448. Then it works.

// $conditions[] = array("$fieldName in ($subquery)");
$db = $Model->getDataSource();
$conditions[] = $db->expression("$fieldName in ($subquery)");

How to use data from another model for a search

Hi,
this is not an issue of the search plugin, but more of my current project related to cakephp search.
I have two models, the first contains the data which is searchable by a web form, this is working fine.

Now I want to create a 2nd Model which contains customers:
Lets say model 1 contains cars (car-model, hp, size ...)
model 2 contains customers who search a car with special specifications.

As the search plugin is already working really fine with the standard search I now try to use it with data that does not come from a post/search form, but from another criteria source.
How do I set this up to work? Is there any option or entry point to pass data not from parsed params, but pass data directly with a variable/array?

$this->Prg->commonProcess();
$parsedParams = $this->Prg->parsedParams(); // at this point I want to pass my data
$this->Car->parseCriteria($parsedParams));
...

I tried to set $parsedParams to my search-data array, but that doesn't work

I know i could do a regular find with common cakephp functions, but I set up the search plugin with some tolerance functions to show more results which are near the search criterias. So I want to reuse this.

Thanks for your help and the plugin.
Best regards
Alex

Warning: Illegal string offset when debug turned on

Forgive me if this is something to do with my code rather than the plugin. When I use the plugin it works fine with debug set to zero, however, once its on I get lots of:

Warning (2): Illegal string offset 'name' [APP/Plugin/Search/Model/Behavior/SearchableBehavior.php, line 52]

When I expand the code in the warning I get:

$Model = object(WebformDocument) {}
$config = array()
$key = 'name'
$val = 'WebformCategory'
SearchableBehavior::setup() - APP/Plugin/Search/Model/Behavior/SearchableBehavior.php, line 52
BehaviorCollection::load() - CORE/Cake/Model/BehaviorCollection.php, line 148
BehaviorCollection::init() - CORE/Cake/Model/BehaviorCollection.php, line 68
Model::__construct() - CORE/Cake/Model/Model.php, line 733
ReflectionClass::newInstance() - [internal], line ??
ClassRegistry::init() - CORE/Cake/Utility/ClassRegistry.php, line 156
Model::_constructLinkedModel() - CORE/Cake/Model/Model.php, line 1016
Model::__isset() - CORE/Cake/Model/Model.php, line 842
Model::__get() - CORE/Cake/Model/Model.php, line 872
DboSource::read() - CORE/Cake/Model/Datasource/DboSource.php, line 1065
Model::find() - CORE/Cake/Model/Model.php, line 2631
UsersController::login() - APP/Controller/UsersController.php, line 482
ReflectionMethod::invokeArgs() - [internal], line ??
Controller::invokeAction() - CORE/Cake/Controller/Controller.php, line 485
Dispatcher::_invoke() - CORE/Cake/Routing/Dispatcher.php, line 186
Dispatcher::dispatch() - CORE/Cake/Routing/Dispatcher.php, line 161
[main] - APP/webroot/index.php, line 96

Most of the errors come when I attempt to log in (my projects use auth and ACL). The line it mentions in the error for user users controller is

$userStatusCheck = $this->User->find('first',array('conditions'=>array('User.username'=>$this->request->data['User']['username'], 'User.live'=>1)));

I have the plugin set up as descripted in the readme. Could someone tell me where I'm going wrong?

Thanks in advance

PrgComponent doesn't work if controller uses some models.

class PostController extends AppController {
    public $uses = ['User', 'Post'];
    public $components = array('Search.Prg');

In this case, Search.Prg work to use User model.
If it want to use Post Model, I have not idea.

// PrgComponent.php
    public function initialize(Controller $controller) {
        $this->controller = $controller;

                // ....

        $model = $this->controller->modelClass;
        if (!empty($settings['model'])) {      // (1)
            $model = $settings['model'];
        }

I think PrgComponent look like has solution for the problem using component option.
But, $settins['model'](1) is not exist on the scope.

$this->_defaults['presetForm']['model'] is seem like.

Search on HABTM Association

I am trying to implement a search in CakePHP 2.2.7 on an HABTM association between tables named herbs and herbal_actions. The join table is herbal_actions_herbs. I have spent countless hours researching how to do this and can't find anything that works. I currently have implemented your response to Issue #64 HABTM in this issue forum, and it fails miserably. I'm hoping that you will be able to provide me with some guidance on how to fix/achieve this. I can't imagine why Cake hasn't made this whole thing much simpler; it's very common to have lookup tables when entering data and then the need to pull the data by those criteria.

Basically, here's what I've got in terms of associations:
In my Herb model

public $hasAndBelongsToMany = array(
            'HerbalAction'           => array(
                'className'             => 'HerbalAction',
                'joinTable'             => 'herbal_actions_herbs',
                'foreignKey'            => 'herb_id',
                'associationForeignKey' => 'herbal_action_id',
                'unique'                => 'keepExisting',
                'order'                 => 'HerbalAction.name',
                'with'                  => 'HerbalActionsHerb',
            ),
        );

In my HerbalAction model

public $hasAndBelongsToMany = array(
            'Herb' => array(
                'className'             => 'Herb',
                'joinTable'             => 'herbal_actions_herbs',
                'foreignKey'            => 'herbal_action_id',
                'associationForeignKey' => 'herb_id',
                'unique'                => 'keepExisting',
                'order'                 => 'Herb.name',
            ),
        );

In the filterArgs

public $filterArgs = array(
            'name_filter'          => array('type' => 'query', 'method' => 'orConditionsName'),
            'description_filter'   => array('type' => 'query', 'method' => 'orConditionsDescription'),
            'herbal_action_id'     => array('type' => 'subquery', 'field' => 'Herb.id', 'method' => 'findByActions'),
            'medical_condition_id' => array('type' => 'value'),
            'property_id'          => array('type' => 'value'),
        );

The findByActions function (from your reponse to Issue#64

public function findByActions($data = array()){

            $this->HerbalActionsHerb->Behaviors->attach('Search.Searchable');
            $query = $this->HerbalActionsHerb->getQuery('all', array(
                                                                    'conditions' => array('herbal_action_id'  => $data['tag_id']),
                                                                    'fields' => array('herb'),
                                                                    'contain' => array(
                                                                        'HerbalAction',
                                                                        'Herb'
                                                                    )
                                                               ));
            return $query;
        }

All of which produces this error message and SQL

Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'HerbalActionsHerb.herb' in 'field list'

With this SQL Query

SELECT `Herb`.`id`, `Herb`.`name`, `Herb`.`slug`, `Herb`.`common_name`, `Herb`.`also_known_as`, `Herb`.`overview`, `Herb`.`constituents`, `Herb`.`summary`, `Herb`.`parts_used`, `Herb`.`typical_preparation`, `Herb`.`precautions`, `Herb`.`comments`, `Herb`.`created`, `Herb`.`creator_id`, `Herb`.`modified`, `Herb`.`modifier_id`, `Creator`.`id`, `Creator`.`username`, `Creator`.`slug`, `Creator`.`password`, `Creator`.`password_token`, `Creator`.`email`, `Creator`.`email_verified`, `Creator`.`email_token`, `Creator`.`email_token_expires`, `Creator`.`tos`, `Creator`.`active`, `Creator`.`last_login`, `Creator`.`last_action`, `Creator`.`is_admin`, `Creator`.`group_id`, `Creator`.`creator_id`, `Creator`.`created`, `Creator`.`modifier_id`, `Creator`.`modified`, `Modifier`.`id`, `Modifier`.`username`, `Modifier`.`slug`, `Modifier`.`password`, `Modifier`.`password_token`, `Modifier`.`email`, `Modifier`.`email_verified`, `Modifier`.`email_token`, `Modifier`.`email_token_expires`, `Modifier`.`tos`, `Modifier`.`active`, `Modifier`.`last_login`, `Modifier`.`last_action`, `Modifier`.`is_admin`, `Modifier`.`group_id`, `Modifier`.`creator_id`, `Modifier`.`created`, `Modifier`.`modifier_id`, `Modifier`.`modified` FROM `lel`.`herbs` AS `Herb` LEFT JOIN `lel`.`users` AS `Creator` ON (`Herb`.`creator_id` = `Creator`.`id`) LEFT JOIN `lel`.`users` AS `Modifier` ON (`Herb`.`modifier_id` = `Modifier`.`id`) WHERE `Herb`.`id` in (SELECT `HerbalActionsHerb`.`herb` FROM `lel`.`herbal_actions_herbs` AS HerbalActionsHerb WHERE herbal_action_id IS NULL) ORDER BY `Herb`.`name` asc LIMIT 10

Of course, that can't work, so I'm hoping you'll be able to tell me what I can do next or where I've gone wrong.

add searchable behavior in readme

Not really a problem with the plugin itself, but in the readme part of sample of configuring the plugin maybe it should say that you must add the searchable behavior to the model to make it work

Base64 encoding is useless in URLs

Because base64-encoded strings can contain '/' and '+', which have the special meanings in URLs.

I suggest you to encode the data in hexadecimal representation instead of base64 encoding.

$encoded = bin2hex($data);
$decoded = pack('H*', $encoded);

Or you can just store the data into query strings rather than named parameters.

Search plugin with PHP4

Hi everybody,
I ‘m beginner developper in France and I need your help about this plugin.

In fact, I use your plugin for my cakephp 1.3 app (lorenzo version) but my php’s version is too old (4.4.4) to use it.

Could you tell me what would be the changes (in searchable.php or prg.php) to be done to make it compatible with my version of php. How to adapt your code to my application ?

I would be very grateful.

Victor

search genres Film

genre is array of Genre.id
if i only search name but dont search genre :
errors: Undefined index: genres
search plugin must have data of all field in $presetVars ?
in COntroller
public $presetVars = array(
array('field' => 'name', 'type' => 'value'),
array('field'=>'genres','type'=>'checkbox')
);
in VIEW.ctp
echo $form->input('Film.genres',array('type'=>'select','multiple' => 'checkbox','options'=>array(1=>'adventure',2=>'action')));

Error can fix :
if (empty($this->data['Film']['genres']))
$this->data['Film']['genres'] = null;

HABTM

Can someone give a detailed explanation about how to setup a habtm search ? i can't seem to find a source of information related to it.

With model/controller/view if possible

thanks

Question: Why initialize and not startup?

I have run into some issues using this plugin with a multi-tenant database structure (isolated databases), because the initialize() function in PrgComponent constructs models before my authentication code has had a chance to figure out which tenant database to use.

I have renamed initialize() function to startup() (so it is executed after my Auth has had a chance to login the user), and everything still seems to be working correctly - but I am wondering whether there is some kind of issue with this beneath the surface that I have not uncovered?

Any info would be much appreciated.

URL Encoding

Reported by John Gerhardt | July 18th, 2011 @ 03:56 PM

Attempting to create a search... but running into problems when a user enters more than one word into the field.

Model:

    var $actsAs = array('Search.Searchable');

    var $filterArgs = array(
        array('name' => 'name', 'type' => 'query', 'method' => 'filterByName'),
    );

    function filterByName ($data, $field = null) {
        if(empty($data['name'])) {
            return array();
        }
        $name = '%' . $data['name'] . '%';
        return array(
            'OR' => array(
                $this->alias . '.name LIKE' => $name,
                $this->alias . '.description LIKE' => $name,
            )
        );
    }

Controller:

    var $components = array('Search.Prg');

    var $presetVars = array(
        array('field' => 'name', 'type' => 'value', 'encode' => true),
    );

    function index() {
            $this->Prg->commonProcess();
            $this->paginate['conditions'] = $this->Firm->parseCriteria($this->passedArgs);
    $this->set('firms', $this->paginate());
}

View:

    <div class="filter">
        <?php
            echo $this->Form->create('Firm', array(
                'url' => array_merge(array('action' => 'index', $this->params['pass']))
            ));
            echo $this->Form->input('name', array('div' => false, 'empty' => true));
            echo $this->Form->submit(__('Search', true), array('div' => false));
            echo $this->Form->end();
        ?>
    </div>

I've tried adding urldecode($data['name']) in my model, which results in the proper query, but the text in the input field that is displayed to the user still includes %20 instead of a regular space. For example, "word1 word2" queries correctly, but is displayed in the input field as "word1%20word2".

implement complex search with or condition

Hi there, I'm trying to implement a single search that corresponds to this query:
SELECT * FROM termsWHEREentryLIKE '%$word%' ORlemma_tagLIKE '%$word%' ORDER BYentry``
I could achieve a search but only for the field "entry" , for what comes after the OR I haven't been able, I'm a little confused with the example here: https://github.com/CakeDC/search/blob/master/Docs/Documentation/Examples.md, I don't know what to put and where, and what to eliminate, because as you can see I have only 2 fields where to search, what confuses me most is this part:
"In this example the search by OR condition is shown. For this purpose we defined the method orConditions() and added the filter method."

    'name' => 'filter',
    'type' => 'query',
    'method' => 'orConditions')```

that array I can not find where to put it, if I have to. Can you please help me on this, I'm just starting with cakephp and there are lots of things I can not grab

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.