Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
TitasGailius committed Sep 1, 2018
0 parents commit 4e4f508
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 0 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/dist
/.idea
/vendor
/node_modules
package-lock.json
composer.phar
composer.lock
phpunit.xml
.phpunit.result.cache
.DS_Store
Thumbs.db
24 changes: 24 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "titasgailius/search-relations",
"description": "A Laravel Nova tool.",
"keywords": [
"laravel",
"nova",
"search",
"relations"
],
"license": "MIT",
"require": {
"php": ">=7.1.0"
},
"autoload": {
"psr-4": {
"Titasgailius\\SearchRelations\\": "src/"
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
}
37 changes: 37 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Search relationships in Laravel Nova

This package allow you to include relationship columns into Laravel Nova search query.

## Screenshot

![screenshot of the search relations tool](./screenshot.png)

## Installation

```
composer require titasgailius/search-relations
```

Next, add `Titasgailius\SearchRelations\SearchesRelations` trait to your base resource class `App\Nova\Resource`
```php
use Titasgailius\SearchRelations\SearchesRelations;

abstract class Resource extends NovaResource
{
use SearchesRelations;
```

## Usage

Simply add `public static $searchRelations` array to any of your Nova resources.
This array has a relationship name as a key and an array of columns to search for as a value.
```php
/**
* The relationship columns that should be searched.
*
* @var array
*/
public static $searchRelations = [
'user' => ['username', 'email'],
];
```
Binary file added screenshot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 90 additions & 0 deletions src/SearchesRelations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Titasgailius\SearchRelations;

use Closure;
use Illuminate\Database\Eloquent\Builder;

trait SearchesRelations
{
/**
* Apply the search query to the query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $search
* @return \Illuminate\Database\Eloquent\Builder
*/
protected static function applySearch($query, $search)
{
return tap(parent::applySearch($query, $search), function ($query) use ($search) {
static::applyRelationSearch($query, $search);
});
}

/**
* Apply the relationship search query to the given query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $search
* @return void
*/
public static function applyRelationSearch(Builder $query, string $search)
{
foreach (static::searchableRelations() as $relation => $columns) {
$query->orWhereHas($relation, function ($query) use ($columns, $search) {
$query->where(static::searchQueryApplier($columns, $search));
});
}

// All search conditionals have to be combined into 1 nested conditional.
// We just applied a query to search for relationship columns while Nova
// has also applied a separate query to search for model columns. That's
// why we merge last 2 conditionals into 1 nested conditional which leaves
// us with this nicely formatted query that also seatches in relationships.
// SELECT ? FROM ? WHERE ($searchQuery OR $relationQuery)
static::mergeLastWheres($query, 2);
}

/**
* Get the searchable columns for the resource.
*
* @return array
*/
public static function searchableRelations(): array
{
return static::$searchRelations ?? [];
}

/**
* Returns a Closure that applies a search query for a given columns.
*
* @param array $columns
* @param string $search
* @return \Closure
*/
public static function searchQueryApplier(array $columns, string $search): Closure
{
return function ($query) use ($columns, $search) {
foreach ($columns as $column) {
$query->orWhere($column, 'LIKE', '%'.$search.'%');
}
};
}

/**
* Merge last where conditionals into a 1 nested conditional.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $count
* @return void
*/
public static function mergeLastWheres(Builder $query, int $count)
{
$query = $query->getQuery();
$queries = array_splice($query->wheres, $count);

$query->where(function ($query) use ($queries) {
$query->wheres = array_merge($query->wheres, $queries);
});
}
}

0 comments on commit 4e4f508

Please sign in to comment.