Skip to content

Commit

Permalink
Object based unique and exists rules for validation. (#15809)
Browse files Browse the repository at this point in the history
* allow toString objects

* work on fluent validation rules

* Add tests for new features.

* add tests

* remove group

* Applied fixes from StyleCI (#15808)
  • Loading branch information
taylorotwell committed Oct 7, 2016
1 parent 1c78e00 commit cc1df99
Show file tree
Hide file tree
Showing 9 changed files with 473 additions and 9 deletions.
17 changes: 15 additions & 2 deletions src/Illuminate/Validation/DatabasePresenceVerifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Illuminate\Validation;

use Closure;
use Illuminate\Support\Str;
use Illuminate\Database\ConnectionResolverInterface;

Expand Down Expand Up @@ -52,7 +53,13 @@ public function getCount($collection, $column, $value, $excludeId = null, $idCol
}

foreach ($extra as $key => $extraValue) {
$this->addWhere($query, $key, $extraValue);
if ($extraValue instanceof Closure) {
$query->where(function ($query) use ($extraValue) {
$extraValue($query);
});
} else {
$this->addWhere($query, $key, $extraValue);
}
}

return $query->count();
Expand All @@ -72,7 +79,13 @@ public function getMultiCount($collection, $column, array $values, array $extra
$query = $this->table($collection)->whereIn($column, $values);

foreach ($extra as $key => $extraValue) {
$this->addWhere($query, $key, $extraValue);
if ($extraValue instanceof Closure) {
$query->where(function ($query) use ($extraValue) {
$extraValue($query);
});
} else {
$this->addWhere($query, $key, $extraValue);
}
}

return $query->count();
Expand Down
30 changes: 30 additions & 0 deletions src/Illuminate/Validation/Rule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Illuminate\Validation;

class Rule
{
/**
* Get a exists constraint builder instance.
*
* @param string $table
* @param string $column
* @return \Illuminate\Validation\Rules\Exists
*/
public static function exists($table, $column = 'NULL')
{
return new Rules\Exists($table, $column);
}

/**
* Get a unique constraint builder instance.
*
* @param string $table
* @param string $column
* @return \Illuminate\Validation\Rules\Unique
*/
public static function unique($table, $column = 'NULL')
{
return new Rules\Unique($table, $column);
}
}
149 changes: 149 additions & 0 deletions src/Illuminate/Validation/Rules/Exists.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

namespace Illuminate\Validation\Rules;

use Closure;

class Exists
{
/**
* The table to run the query against.
*
* @var string
*/
protected $table;

/**
* The column to check for existence on.
*
* @var string
*/
protected $column;

/**
* There extra where clauses for the query.
*
* @var array
*/
protected $wheres = [];

/**
* The custom query callback.
*
* @var \Closure|null
*/
protected $using;

/**
* Create a new exists rule instance.
*
* @param string $table
* @param string $column
* @return void
*/
public function __construct($table, $column = 'NULL')
{
$this->table = $table;
$this->column = $column;
}

/**
* Set a "where" constraint on the query.
*
* @param string $column
* @param string $value
* @return $this
*/
public function where($column, $value = null)
{
if ($column instanceof Closure) {
return $this->using($column);
}

$this->wheres[] = compact('column', 'value');

return $this;
}

/**
* Set a "where not" constraint on the query.
*
* @param string $column
* @param string $value
* @return $this
*/
public function whereNot($column, $value)
{
return $this->where($column, '!'.$value);
}

/**
* Set a "where null" constraint on the query.
*
* @param string $column
* @return $this
*/
public function whereNull($column)
{
return $this->where($column, 'NULL');
}

/**
* Set a "where not null" constraint on the query.
*
* @param string $column
* @return $this
*/
public function whereNotNull($column)
{
return $this->where($column, 'NOT_NULL');
}

/**
* Register a custom query callback.
*
* @param \Closure $callback
*/
public function using(Closure $callback)
{
$this->using = $callback;

return $this;
}

/**
* Format the where clauses.
*
* @return string
*/
protected function formatWheres()
{
return collect($this->wheres)->map(function ($where) {
return $where['column'].','.$where['value'];
})->implode(',');
}

/**
* Get the custom query callbacks for the rule.
*
* @return array
*/
public function queryCallbacks()
{
return $this->using ? [$this->using] : [];
}

/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
return rtrim(sprintf('exists:%s,%s,%s',
$this->table,
$this->column,
$this->formatWheres()
), ',');
}
}
180 changes: 180 additions & 0 deletions src/Illuminate/Validation/Rules/Unique.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<?php

namespace Illuminate\Validation\Rules;

use Closure;

class Unique
{
/**
* The table to run the query against.
*
* @var string
*/
protected $table;

/**
* The column to check for uniqueness on.
*
* @var string
*/
protected $column;

/**
* The ID that should be ignored.
*
* @var mixed
*/
protected $ignore;

/**
* The name of the ID column.
*
* @var string
*/
protected $idColumn = 'id';

/**
* There extra where clauses for the query.
*
* @var array
*/
protected $wheres = [];

/**
* The custom query callback.
*
* @var \Closure|null
*/
protected $using;

/**
* Create a new unique rule instance.
*
* @param string $table
* @param string $column
* @return void
*/
public function __construct($table, $column = 'NULL')
{
$this->table = $table;
$this->column = $column;
}

/**
* Set a "where" constraint on the query.
*
* @param string $column
* @param string $value
* @return $this
*/
public function where($column, $value = null)
{
if ($column instanceof Closure) {
return $this->using($column);
}

$this->wheres[] = compact('column', 'value');

return $this;
}

/**
* Set a "where not" constraint on the query.
*
* @param string $column
* @param string $value
* @return $this
*/
public function whereNot($column, $value)
{
return $this->where($column, '!'.$value);
}

/**
* Set a "where null" constraint on the query.
*
* @param string $column
* @return $this
*/
public function whereNull($column)
{
return $this->where($column, 'NULL');
}

/**
* Set a "where not null" constraint on the query.
*
* @param string $column
* @return $this
*/
public function whereNotNull($column)
{
return $this->where($column, 'NOT_NULL');
}

/**
* Ignore the given ID during the unique check.
*
* @param mixed $id
* @param string $idColumn
* @return $this
*/
public function ignore($id, $idColumn = 'id')
{
$this->ignore = $id;
$this->idColumn = $idColumn;

return $this;
}

/**
* Register a custom query callback.
*
* @param \Closure $callback
*/
public function using(Closure $callback)
{
$this->using = $callback;

return $this;
}

/**
* Format the where clauses.
*
* @return string
*/
protected function formatWheres()
{
return collect($this->wheres)->map(function ($where) {
return $where['column'].','.$where['value'];
})->implode(',');
}

/**
* Get the custom query callbacks for the rule.
*
* @return array
*/
public function queryCallbacks()
{
return $this->using ? [$this->using] : [];
}

/**
* Convert the rule to a validation string.
*
* @return string
*/
public function __toString()
{
return rtrim(sprintf('unique:%s,%s,%s,%s,%s',
$this->table,
$this->column,
$this->ignore ?: 'NULL',
$this->idColumn,
$this->formatWheres()
), ',');
}
}
Loading

0 comments on commit cc1df99

Please sign in to comment.