mul14
8/31/2015 - 3:52 AM

Simple Laravel Search Trait

Simple Laravel Search Trait

Usage

Put SearchTrait.php in app directory. Then use SearchTrait in your model, like so

use App\SearchTrait;
use Illuminate\Database\Eloquent\Model;

class Article extends Model {

    use SearchTrait;
    
    // Optional property
    protected $search = ['title', 'content'];

}

Somewhere in your controller

$keyword = 'lorem';

// Match any fields
Article::search($keyword)->paginate();

// Match all fields
Article::search($keyword, true)->paginate();
<?php

namespace App;

use Illuminate\Support\Facades\Schema;

trait SearchTrait
{
    /**
     * @param \Illuminate\Database\Eloquent\Builder|static $query
     * @param string $keyword
     * @param boolean $matchAllFields
     */
    public static function scopeSearch($query, $keyword, $matchAllFields = false)
    {
        return static::where(function ($query) use ($keyword, $matchAllFields) {

            foreach (static::getSearchFields() as $field) {
                if ($matchAllFields) {
                    $query->where($field, 'LIKE', "%$keyword%");
                } else {
                    $query->orWhere($field, 'LIKE', "%$keyword%");
                }
            }

        });
    }

    /**
     * Get all searchable fields
     *
     * @return array
     */
    public static function getSearchFields()
    {
        $model = new static;

        $fields = $model->search;

        if (empty($fields)) {
            $fields = Schema::getColumnListing($model->getTable());

            $others[] = $model->primaryKey;

            $others[] = $model->getUpdatedAtColumn() ?: 'created_at';
            $others[] = $model->getCreatedAtColumn() ?: 'updated_at';

            $others[] = method_exists($model, 'getDeletedAtColumn')
                ? $model->getDeletedAtColumn()
                : 'deleted_at';

            $fields = array_diff($fields, $model->getHidden(), $others);
        }

        return $fields;
    }
}