GithubHelp home page GithubHelp logo

jedrzej / searchable Goto Github PK

View Code? Open in Web Editor NEW
122.0 8.0 22.0 55 KB

Search/filter functionality for Laravel's Eloquent models

License: MIT License

PHP 100.00%
laravel eloquent search searchable-models filter filtering eloquent-models php

searchable's People

Contributors

jadjoubran avatar jedrzej avatar jedrzej-x-team-com avatar morloderex avatar pablomaurer 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

searchable's Issues

Problem with LIKE operator

I have this problem, when i use LIKE operator. I want to filter %Carlos%, but dont work because Builder resolve this: "value" => b"Êrlos%".

screenshot_1

` protected function processSearchFilter(Builder $builder, Constraint $constraint)
{
// this logic should happen for LIKE/EQUAL operators only

    if ($constraint->getOperator() === Constraint::OPERATOR_LIKE || $constraint->getOperator() === Constraint::OPERATOR_EQUAL) {
        $builder->whereHas('tercero',function ($query) use ($constraint) {
                $query->where('nombre1', $constraint->getOperator(), $constraint->getValue())
                    ->orWhere('nombre2', $constraint->getOperator(), $constraint->getValue())
                    ->orWhere('apellido1', $constraint->getOperator(), $constraint->getValue())
                    ->orWhere('apellido2', $constraint->getOperator(), $constraint->getValue())
                    ->orWhere('identificacion', $constraint->getOperator(), $constraint->getValue());

            });
        return true;
    }


    // default logic should be executed otherwise
    return false;
}`

Where between?

Hello i have noticed there is no way to do a where between.

And overriding the filter doesn't work either sense the filter method is beeing hit twice and not once with an array of the constraints.

Consider this:
date[]=2016-07-26&date[]=2016-07-29

This makes the dateProgressFilter beeing hit but its beeing hitted twice.

So i have a single value to work with..

Is it possible to somehow get both constraint objects a once so i can do something like the fallowing:

$builder->whereBetween()

Using OR and AND at the same query

For example, we have a small service for blog posts management and a blog itself.

At our search, we want to do the following query:

            'query' => [
                'mode' => 'or',
                'city' => "%$query%",
                'state' => "%$query%",
                'store_name' => "%$query%",
                'title' => "%$query%",
            ],

Thats nice, it will search for everything we need but we want to filter by published posts also. But, Its not possible since we're using OR mode.

Is there a way to make something like?

            'query' => [
                'mode' => 'and',
                'status' => 'published',
                [
                    'mode' => 'or',
                    'city' => "%$query%",
                    'state' => "%$query%",
                    'store_name' => "%$query%",
                    'title' => "%$query%",
                ],
            ],

ILIKE instead of LIKE

I am using postgres, where LIKE is case sensitive. This does not provide best experience with filters. ILIKE should be used in this case.

Can this be fixed?

Search for content containg comma

Is it possible to search for content, like "Smith, John"?
Right now, it is looking for "Smith" OR "John".
Is there some kind of config to disable "OR" functionality for comma, or change it to another character?

Allow negative relation search

At the moment it's possible to do positive search by relation - find records that have matching related records. It's needed to allow also negative search - find records that don't have matching related records.

Search operator position is better at param key

Usually users do not input operators like (ge)2018-04-16
It make view code little hacky like change values before send

I think operators should be in query keys, not values like below

Now
<input name="foo" value="(ge)2018-04-16">
My opinion
<input name="(ge)foo" value="2018-04-16">

Ambiguous columns

I'm filtering on a model but a filed like created_at appears in many of my models so this is causing an error whereby created_at is ambiguous. I believe this occurs because I am running pimp() on a relation instead on the model itself. How can I fix this?

$user->transactions()->pimp()

Allow filtering by fields of related models

The package now allows to search only among fiields of given searchable models. The scope of this issue is to add possibility to filter also fields of related models (one-to-one, many-to-one, many-to-many relations)

SimplePaginate with "page" attribute stop working.

I installed pimpable package, but I think the problem is with searchable package.
When I have something like this:
Model::pimp()->simplePaginate();
It gives me:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'page' in 'where clause' (SQL: select * fromsectionspage = 1 limit 16 offset 0)
I found a way to allow everything except 'page' attribute, but it would be nice to have this effect in package.

My implementation in Model;
protected function getSearchableAttributes() { return array_except(Input::all(), 'page'); } // or something like this public $searchableExcept = ['page'];

Multiple columns

Hello, pleasure, first of all to thank the developers for the beautiful work. I've been looking for something like this for some time.

Sorry I'm Brazilian so my English isn't very good, it's just technical.

I would like to know if with this tool I can do the research of several fields through just one attribute.

Example:

posts?search=%searchstring%

colums search: [title, desc, keyword]

Searching Related Models Using OR

When using this package to search multiple relations using the OR mode the query generated is not produced as expected. For example, consider the following if we have a one to one relation between "providers" and "users" where the users table contains first_name and last_name and the providers table has a user_id column:

?user:first_name&user:last_name&mode=or will generate the following query

 where exists (select * from `users` where `providers`.`user_id` = `users`.`id` and (`last_name` = ?)) **and** 
exists (select * from `users` where `providers`.`user_id` = `users`.`id` and (`first_name` = ?))

The expected result would be

 where exists (select * from `users` where `providers`.`user_id` = `users`.`id` and (`last_name` = ?)) **OR** 
exists (select * from `users` where `providers`.`user_id` = `users`.`id` and (`first_name` = ?))

As a side note, I believe this query should actually group the two queries under the same subquery like this:

 where exists (select * from `users` where `providers`.`user_id` = `users`.`id` and (`last_name` = ? OR `first_name` = ?)) 

however I believe this is a separate issue. I propose the following changes in Constraint.php

 public function apply(Builder $builder, $field, $mode = Constraint::MODE_AND)
    {
        if ($this->isRelation($field)) {
            list($relation, $field) = $this->splitRelationField($field);
            if (static::parseIsNegation($relation)) {
                $builder->doesntHave($relation, $mode, function (Builder $builder) use ($field, $mode) {
                    $this->doApply($builder, $field, $mode);
                });
            } else {
                $builder->has($relation,'>=',1,$mode, function (Builder $builder) use ($field, $mode) {
                    $this->doApply($builder, $field, $mode);
                });
            }
        } else {
            $this->doApply($builder, $field, $mode);
        }
    }

Where the ->whereDoesntHave() is replaced with doesntHave() passing in the $mode and the whereHas() is replaced with has(). This could actully simplify the doApply() function as well instead of resolving the method name 'whereIn' 'orWhereIn' etc, the $mode could be passed in directly the function.

No search for existance of a relation is available

Some of users of model Student have foreign key to model User. I create relation student() in model User with hasOne() to join them. Now in model User I need to filter those who are student. How can I do that?

I tried
public $searchable = ['name', 'mobile', 'email', 'id', 'student:id'];

and in string query I set

student:id=(null)

and doesn't work because the relation doesn't exist in the first place.

Allow overriding relation filter

Now it's possible to override a filter by implementing processAttributeFilter method in the model. Similar functionality should exist for relation filters.

BETWEEN on relations not grouped

Hi,

?start_date[]=(ge)2018-08-01&start_date[]=(le)2018-08-02

translates to the following MySQL query:

WHERE `start_date` >= 2018-08-01 
AND 
`start_date` <= 2018-08-02

Which is the expected result. However,

?instances:start_date[]=(ge)2018-08-01&instances:start_date[]=(le)2018-08-02

becomes

WHERE EXISTS 
( 
       SELECT * 
       FROM   `expedition_instances` 
       WHERE  `expeditions`.`id` = `expedition_instances`.`expedition_id` 
       AND    `start_date` >= '2018-08-01') 
AND 
EXISTS 
( 
       SELECT * 
       FROM   `expedition_instances` 
       WHERE  `expeditions`.`id` = `expedition_instances`.`expedition_id` 
       AND    `start_date` <= '2018-08-02')

The expected result is

WHERE EXISTS 
( 
       SELECT * 
       FROM   `expedition_instances` 
       WHERE  `expeditions`.`id` = `expedition_instances`.`expedition_id` 
       WHERE  `start_date` >= 2018-08-01 
       AND    `start_date` <= 2018-08-02 )

Feel free to change the issue's title, I wasn't able to think of any better name for it atm.

Edit 1

The constraints looks correctly grouped into instances:start_date:

/expeditions?with[]=instances&instances:start_date[]=(ge)2018-08-01&instances:start_date[]=(le)2018-08-02

array(1) {
  ["instances:start_date"]=>
  array(2) {
    [0]=>
    object(Jedrzej\Searchable\Constraint)#715 (3) {
      ["operator":protected]=>
      string(2) ">="
      ["value":protected]=>
      string(10) "2018-08-01"
      ["is_negation":protected]=>
      bool(false)
    }
    [1]=>
    object(Jedrzej\Searchable\Constraint)#716 (3) {
      ["operator":protected]=>
      string(2) "<="
      ["value":protected]=>
      string(10) "2018-08-02"
      ["is_negation":protected]=>
      bool(false)
    }
  }
}

Edit 2

I think that all constraints of the group should be applied when doing

$builder->whereHas($relation, function (Builder $builder) use ($field, $mode) {
    $this->doApply($builder, $field, $mode);
});

Something like

$builder->whereHas($relation, function (Builder $builder) use ($constraints, $mode) {
    foreach($constraints as $constraint){
        $this->doApply($builder, $constraint->field, $mode);
    }
});

Of course that's just hypothetical, there is no access to the group of the same constraints as they are isolated in buildConstraints (Jedrzej/Searchable/SearchableTrait.php#L120)

Allow switching to OR search instead of AND search

Current version of the package allows only searching using AND operator on all criteria - meaning that all criteria need to be met in order to record to be returned. The scope of this issue is to allow switching to OR search - the result of such search are records that meet any of given criteria. One example of such feature being useful is searching among multiple text fields (email, username, first/last name) for some kind of user autosuggest.

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.