Commaaa2
This commit is contained in:
0
vendor/laravel/framework/src/Illuminate/Database/Capsule/Manager.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Capsule/Manager.php
vendored
Normal file → Executable file
@@ -3,11 +3,23 @@
|
||||
namespace Illuminate\Database\Concerns;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\MultipleRecordsFoundException;
|
||||
use Illuminate\Database\RecordsNotFoundException;
|
||||
use Illuminate\Pagination\Cursor;
|
||||
use Illuminate\Pagination\CursorPaginator;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use Illuminate\Support\Traits\Conditionable;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
trait BuildsQueries
|
||||
{
|
||||
use Conditionable;
|
||||
|
||||
/**
|
||||
* Chunk the results of the query.
|
||||
*
|
||||
@@ -48,12 +60,34 @@ trait BuildsQueries
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a map over each item while chunking.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $count
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function chunkMap(callable $callback, $count = 1000)
|
||||
{
|
||||
$collection = Collection::make();
|
||||
|
||||
$this->chunk($count, function ($items) use ($collection, $callback) {
|
||||
$items->each(function ($item) use ($collection, $callback) {
|
||||
$collection->push($callback($item));
|
||||
});
|
||||
});
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each item while chunking.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function each(callable $callback, $count = 1000)
|
||||
{
|
||||
@@ -83,6 +117,8 @@ trait BuildsQueries
|
||||
|
||||
$lastId = null;
|
||||
|
||||
$page = 1;
|
||||
|
||||
do {
|
||||
$clone = clone $this;
|
||||
|
||||
@@ -100,13 +136,19 @@ trait BuildsQueries
|
||||
// On each chunk result set, we will pass them to the callback and then let the
|
||||
// developer take care of everything within the callback, which allows us to
|
||||
// keep the memory low for spinning through large result sets for working.
|
||||
if ($callback($results) === false) {
|
||||
if ($callback($results, $page) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lastId = $results->last()->{$alias};
|
||||
|
||||
if ($lastId === null) {
|
||||
throw new RuntimeException("The chunkById operation was aborted because the [{$alias}] column is not present in the query result.");
|
||||
}
|
||||
|
||||
unset($results);
|
||||
|
||||
$page++;
|
||||
} while ($countResults == $count);
|
||||
|
||||
return true;
|
||||
@@ -123,15 +165,124 @@ trait BuildsQueries
|
||||
*/
|
||||
public function eachById(callable $callback, $count = 1000, $column = null, $alias = null)
|
||||
{
|
||||
return $this->chunkById($count, function ($results) use ($callback) {
|
||||
return $this->chunkById($count, function ($results, $page) use ($callback, $count) {
|
||||
foreach ($results as $key => $value) {
|
||||
if ($callback($value, $key) === false) {
|
||||
if ($callback($value, (($page - 1) * $count) + $key) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}, $column, $alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunks of the given size.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function lazy($chunkSize = 1000)
|
||||
{
|
||||
if ($chunkSize < 1) {
|
||||
throw new InvalidArgumentException('The chunk size should be at least 1');
|
||||
}
|
||||
|
||||
$this->enforceOrderBy();
|
||||
|
||||
return LazyCollection::make(function () use ($chunkSize) {
|
||||
$page = 1;
|
||||
|
||||
while (true) {
|
||||
$results = $this->forPage($page++, $chunkSize)->get();
|
||||
|
||||
foreach ($results as $result) {
|
||||
yield $result;
|
||||
}
|
||||
|
||||
if ($results->count() < $chunkSize) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunking the results of a query by comparing IDs.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function lazyById($chunkSize = 1000, $column = null, $alias = null)
|
||||
{
|
||||
return $this->orderedLazyById($chunkSize, $column, $alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunking the results of a query by comparing IDs in descending order.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function lazyByIdDesc($chunkSize = 1000, $column = null, $alias = null)
|
||||
{
|
||||
return $this->orderedLazyById($chunkSize, $column, $alias, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunking the results of a query by comparing IDs in a given order.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @param bool $descending
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function orderedLazyById($chunkSize = 1000, $column = null, $alias = null, $descending = false)
|
||||
{
|
||||
if ($chunkSize < 1) {
|
||||
throw new InvalidArgumentException('The chunk size should be at least 1');
|
||||
}
|
||||
|
||||
$column = $column ?? $this->defaultKeyName();
|
||||
|
||||
$alias = $alias ?? $column;
|
||||
|
||||
return LazyCollection::make(function () use ($chunkSize, $column, $alias, $descending) {
|
||||
$lastId = null;
|
||||
|
||||
while (true) {
|
||||
$clone = clone $this;
|
||||
|
||||
if ($descending) {
|
||||
$results = $clone->forPageBeforeId($chunkSize, $lastId, $column)->get();
|
||||
} else {
|
||||
$results = $clone->forPageAfterId($chunkSize, $lastId, $column)->get();
|
||||
}
|
||||
|
||||
foreach ($results as $result) {
|
||||
yield $result;
|
||||
}
|
||||
|
||||
if ($results->count() < $chunkSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lastId = $results->last()->{$alias};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result.
|
||||
*
|
||||
@@ -144,52 +295,143 @@ trait BuildsQueries
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback's query changes if the given "value" is true.
|
||||
* Execute the query and get the first result if it's the sole matching record.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return mixed|$this
|
||||
* @param array|string $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|object|static|null
|
||||
*
|
||||
* @throws \Illuminate\Database\RecordsNotFoundException
|
||||
* @throws \Illuminate\Database\MultipleRecordsFoundException
|
||||
*/
|
||||
public function when($value, $callback, $default = null)
|
||||
public function sole($columns = ['*'])
|
||||
{
|
||||
if ($value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
} elseif ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
$result = $this->take(2)->get($columns);
|
||||
|
||||
if ($result->isEmpty()) {
|
||||
throw new RecordsNotFoundException;
|
||||
}
|
||||
|
||||
return $this;
|
||||
if ($result->count() > 1) {
|
||||
throw new MultipleRecordsFoundException;
|
||||
}
|
||||
|
||||
return $result->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the query to a given callback.
|
||||
* Paginate the given query using a cursor paginator.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
* @param int $perPage
|
||||
* @param array $columns
|
||||
* @param string $cursorName
|
||||
* @param \Illuminate\Pagination\Cursor|string|null $cursor
|
||||
* @return \Illuminate\Contracts\Pagination\CursorPaginator
|
||||
*/
|
||||
public function tap($callback)
|
||||
protected function paginateUsingCursor($perPage, $columns = ['*'], $cursorName = 'cursor', $cursor = null)
|
||||
{
|
||||
return $this->when(true, $callback);
|
||||
if (! $cursor instanceof Cursor) {
|
||||
$cursor = is_string($cursor)
|
||||
? Cursor::fromEncoded($cursor)
|
||||
: CursorPaginator::resolveCurrentCursor($cursorName, $cursor);
|
||||
}
|
||||
|
||||
$orders = $this->ensureOrderForCursorPagination(! is_null($cursor) && $cursor->pointsToPreviousItems());
|
||||
|
||||
if (! is_null($cursor)) {
|
||||
$addCursorConditions = function (self $builder, $previousColumn, $i) use (&$addCursorConditions, $cursor, $orders) {
|
||||
$unionBuilders = isset($builder->unions) ? collect($builder->unions)->pluck('query') : collect();
|
||||
|
||||
if (! is_null($previousColumn)) {
|
||||
$builder->where(
|
||||
$this->getOriginalColumnNameForCursorPagination($this, $previousColumn),
|
||||
'=',
|
||||
$cursor->parameter($previousColumn)
|
||||
);
|
||||
|
||||
$unionBuilders->each(function ($unionBuilder) use ($previousColumn, $cursor) {
|
||||
$unionBuilder->where(
|
||||
$this->getOriginalColumnNameForCursorPagination($this, $previousColumn),
|
||||
'=',
|
||||
$cursor->parameter($previousColumn)
|
||||
);
|
||||
|
||||
$this->addBinding($unionBuilder->getRawBindings()['where'], 'union');
|
||||
});
|
||||
}
|
||||
|
||||
$builder->where(function (self $builder) use ($addCursorConditions, $cursor, $orders, $i, $unionBuilders) {
|
||||
['column' => $column, 'direction' => $direction] = $orders[$i];
|
||||
|
||||
$builder->where(
|
||||
$this->getOriginalColumnNameForCursorPagination($this, $column),
|
||||
$direction === 'asc' ? '>' : '<',
|
||||
$cursor->parameter($column)
|
||||
);
|
||||
|
||||
if ($i < $orders->count() - 1) {
|
||||
$builder->orWhere(function (self $builder) use ($addCursorConditions, $column, $i) {
|
||||
$addCursorConditions($builder, $column, $i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
$unionBuilders->each(function ($unionBuilder) use ($column, $direction, $cursor, $i, $orders, $addCursorConditions) {
|
||||
$unionBuilder->where(function ($unionBuilder) use ($column, $direction, $cursor, $i, $orders, $addCursorConditions) {
|
||||
$unionBuilder->where(
|
||||
$this->getOriginalColumnNameForCursorPagination($this, $column),
|
||||
$direction === 'asc' ? '>' : '<',
|
||||
$cursor->parameter($column)
|
||||
);
|
||||
|
||||
if ($i < $orders->count() - 1) {
|
||||
$unionBuilder->orWhere(function (self $builder) use ($addCursorConditions, $column, $i) {
|
||||
$addCursorConditions($builder, $column, $i + 1);
|
||||
});
|
||||
}
|
||||
|
||||
$this->addBinding($unionBuilder->getRawBindings()['where'], 'union');
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$addCursorConditions($this, null, 0);
|
||||
}
|
||||
|
||||
$this->limit($perPage + 1);
|
||||
|
||||
return $this->cursorPaginator($this->get($columns), $perPage, $cursor, [
|
||||
'path' => Paginator::resolveCurrentPath(),
|
||||
'cursorName' => $cursorName,
|
||||
'parameters' => $orders->pluck('column')->toArray(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback's query changes if the given "value" is false.
|
||||
* Get the original column name of the given column, without any aliasing.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param callable|null $default
|
||||
* @return mixed|$this
|
||||
* @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param string $parameter
|
||||
* @return string
|
||||
*/
|
||||
public function unless($value, $callback, $default = null)
|
||||
protected function getOriginalColumnNameForCursorPagination($builder, string $parameter)
|
||||
{
|
||||
if (! $value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
} elseif ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
$columns = $builder instanceof Builder ? $builder->getQuery()->columns : $builder->columns;
|
||||
|
||||
if (! is_null($columns)) {
|
||||
foreach ($columns as $column) {
|
||||
if (($position = stripos($column, ' as ')) !== false) {
|
||||
$as = substr($column, $position, 4);
|
||||
|
||||
[$original, $alias] = explode($as, $column);
|
||||
|
||||
if ($parameter === $alias) {
|
||||
return $original;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,4 +466,31 @@ trait BuildsQueries
|
||||
'items', 'perPage', 'currentPage', 'options'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new cursor paginator instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $items
|
||||
* @param int $perPage
|
||||
* @param \Illuminate\Pagination\Cursor $cursor
|
||||
* @param array $options
|
||||
* @return \Illuminate\Pagination\CursorPaginator
|
||||
*/
|
||||
protected function cursorPaginator($items, $perPage, $cursor, $options)
|
||||
{
|
||||
return Container::getInstance()->makeWith(CursorPaginator::class, compact(
|
||||
'items', 'perPage', 'cursor', 'options'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the query to a given callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this|mixed
|
||||
*/
|
||||
public function tap($callback)
|
||||
{
|
||||
return $this->when(true, $callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Illuminate\Database\Concerns;
|
||||
|
||||
use Closure;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
trait ManagesTransactions
|
||||
@@ -45,6 +46,10 @@ trait ManagesTransactions
|
||||
}
|
||||
|
||||
$this->transactions = max(0, $this->transactions - 1);
|
||||
|
||||
if ($this->transactions == 0) {
|
||||
optional($this->transactionsManager)->commit($this->getName());
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$this->handleCommitTransactionException(
|
||||
$e, $currentAttempt, $attempts
|
||||
@@ -78,6 +83,10 @@ trait ManagesTransactions
|
||||
$this->transactions > 1) {
|
||||
$this->transactions--;
|
||||
|
||||
optional($this->transactionsManager)->rollback(
|
||||
$this->getName(), $this->transactions
|
||||
);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@@ -107,6 +116,10 @@ trait ManagesTransactions
|
||||
|
||||
$this->transactions++;
|
||||
|
||||
optional($this->transactionsManager)->begin(
|
||||
$this->getName(), $this->transactions
|
||||
);
|
||||
|
||||
$this->fireConnectionEvent('beganTransaction');
|
||||
}
|
||||
|
||||
@@ -180,6 +193,10 @@ trait ManagesTransactions
|
||||
|
||||
$this->transactions = max(0, $this->transactions - 1);
|
||||
|
||||
if ($this->transactions == 0) {
|
||||
optional($this->transactionsManager)->commit($this->getName());
|
||||
}
|
||||
|
||||
$this->fireConnectionEvent('committed');
|
||||
}
|
||||
|
||||
@@ -241,6 +258,10 @@ trait ManagesTransactions
|
||||
|
||||
$this->transactions = $toLevel;
|
||||
|
||||
optional($this->transactionsManager)->rollback(
|
||||
$this->getName(), $this->transactions
|
||||
);
|
||||
|
||||
$this->fireConnectionEvent('rollingBack');
|
||||
}
|
||||
|
||||
@@ -275,6 +296,10 @@ trait ManagesTransactions
|
||||
{
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
$this->transactions = 0;
|
||||
|
||||
optional($this->transactionsManager)->rollback(
|
||||
$this->getName(), $this->transactions
|
||||
);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
@@ -289,4 +314,21 @@ trait ManagesTransactions
|
||||
{
|
||||
return $this->transactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the callback after a transaction commits.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function afterCommit($callback)
|
||||
{
|
||||
if ($this->transactionsManager) {
|
||||
return $this->transactionsManager->addCallback($callback);
|
||||
}
|
||||
|
||||
throw new RuntimeException('Transactions Manager has not been set.');
|
||||
}
|
||||
}
|
||||
|
||||
199
vendor/laravel/framework/src/Illuminate/Database/Connection.php
vendored
Normal file → Executable file
199
vendor/laravel/framework/src/Illuminate/Database/Connection.php
vendored
Normal file → Executable file
@@ -5,6 +5,7 @@ namespace Illuminate\Database;
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\DBAL\Connection as DoctrineConnection;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Events\QueryExecuted;
|
||||
@@ -21,6 +22,7 @@ use Illuminate\Support\Arr;
|
||||
use LogicException;
|
||||
use PDO;
|
||||
use PDOStatement;
|
||||
use RuntimeException;
|
||||
|
||||
class Connection implements ConnectionInterface
|
||||
{
|
||||
@@ -49,6 +51,13 @@ class Connection implements ConnectionInterface
|
||||
*/
|
||||
protected $database;
|
||||
|
||||
/**
|
||||
* The type of the connection.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $readWriteType;
|
||||
|
||||
/**
|
||||
* The table prefix for the connection.
|
||||
*
|
||||
@@ -112,13 +121,27 @@ class Connection implements ConnectionInterface
|
||||
*/
|
||||
protected $transactions = 0;
|
||||
|
||||
/**
|
||||
* The transaction manager instance.
|
||||
*
|
||||
* @var \Illuminate\Database\DatabaseTransactionsManager
|
||||
*/
|
||||
protected $transactionsManager;
|
||||
|
||||
/**
|
||||
* Indicates if changes have been made to the database.
|
||||
*
|
||||
* @var int
|
||||
* @var bool
|
||||
*/
|
||||
protected $recordsModified = false;
|
||||
|
||||
/**
|
||||
* Indicates if the connection should use the "write" PDO connection.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $readOnWriteConnection = false;
|
||||
|
||||
/**
|
||||
* All of the queries run against the connection.
|
||||
*
|
||||
@@ -140,6 +163,13 @@ class Connection implements ConnectionInterface
|
||||
*/
|
||||
protected $pretending = false;
|
||||
|
||||
/**
|
||||
* All of the callbacks that should be invoked before a query is executed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $beforeExecutingCallbacks = [];
|
||||
|
||||
/**
|
||||
* The instance of Doctrine connection.
|
||||
*
|
||||
@@ -147,6 +177,13 @@ class Connection implements ConnectionInterface
|
||||
*/
|
||||
protected $doctrineConnection;
|
||||
|
||||
/**
|
||||
* Type mappings that should be registered with new Doctrine connections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $doctrineTypeMappings = [];
|
||||
|
||||
/**
|
||||
* The connection resolvers.
|
||||
*
|
||||
@@ -620,6 +657,10 @@ class Connection implements ConnectionInterface
|
||||
*/
|
||||
protected function run($query, $bindings, Closure $callback)
|
||||
{
|
||||
foreach ($this->beforeExecutingCallbacks as $beforeExecutingCallback) {
|
||||
$beforeExecutingCallback($query, $bindings, $this);
|
||||
}
|
||||
|
||||
$this->reconnectIfMissingConnection();
|
||||
|
||||
$start = microtime(true);
|
||||
@@ -661,7 +702,7 @@ class Connection implements ConnectionInterface
|
||||
// run the SQL against the PDO connection. Then we can calculate the time it
|
||||
// took to execute and log the query SQL, bindings and time in our memory.
|
||||
try {
|
||||
$result = $callback($query, $bindings);
|
||||
return $callback($query, $bindings);
|
||||
}
|
||||
|
||||
// If an exception occurs when attempting to run a query, we'll format the error
|
||||
@@ -672,8 +713,6 @@ class Connection implements ConnectionInterface
|
||||
$query, $this->prepareBindings($bindings), $e
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -786,6 +825,21 @@ class Connection implements ConnectionInterface
|
||||
public function disconnect()
|
||||
{
|
||||
$this->setPdo(null)->setReadPdo(null);
|
||||
|
||||
$this->doctrineConnection = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a hook to be run just before a database query is executed.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function beforeExecuting(Closure $callback)
|
||||
{
|
||||
$this->beforeExecutingCallbacks[] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -847,6 +901,16 @@ class Connection implements ConnectionInterface
|
||||
return new Expression($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the database connection has modified any database records.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasModifiedRecords()
|
||||
{
|
||||
return $this->recordsModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if any records have been modified.
|
||||
*
|
||||
@@ -860,6 +924,42 @@ class Connection implements ConnectionInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the record modification state.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setRecordModificationState(bool $value)
|
||||
{
|
||||
$this->recordsModified = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the record modification state.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function forgetRecordModificationState()
|
||||
{
|
||||
$this->recordsModified = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the connection should use the write PDO connection for reads.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return $this
|
||||
*/
|
||||
public function useWriteConnectionWhenReading($value = true)
|
||||
{
|
||||
$this->readOnWriteConnection = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Doctrine available?
|
||||
*
|
||||
@@ -891,7 +991,13 @@ class Connection implements ConnectionInterface
|
||||
*/
|
||||
public function getDoctrineSchemaManager()
|
||||
{
|
||||
return $this->getDoctrineDriver()->getSchemaManager($this->getDoctrineConnection());
|
||||
$connection = $this->getDoctrineConnection();
|
||||
|
||||
// Doctrine v2 expects one parameter while v3 expects two. 2nd will be ignored on v2...
|
||||
return $this->getDoctrineDriver()->getSchemaManager(
|
||||
$connection,
|
||||
$connection->getDatabasePlatform()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -907,14 +1013,46 @@ class Connection implements ConnectionInterface
|
||||
$this->doctrineConnection = new DoctrineConnection(array_filter([
|
||||
'pdo' => $this->getPdo(),
|
||||
'dbname' => $this->getDatabaseName(),
|
||||
'driver' => $driver->getName(),
|
||||
'driver' => method_exists($driver, 'getName') ? $driver->getName() : null,
|
||||
'serverVersion' => $this->getConfig('server_version'),
|
||||
]), $driver);
|
||||
|
||||
foreach ($this->doctrineTypeMappings as $name => $type) {
|
||||
$this->doctrineConnection
|
||||
->getDatabasePlatform()
|
||||
->registerDoctrineTypeMapping($type, $name);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->doctrineConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom Doctrine mapping type.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return void
|
||||
*
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function registerDoctrineType(string $class, string $name, string $type): void
|
||||
{
|
||||
if (! $this->isDoctrineAvailable()) {
|
||||
throw new RuntimeException(
|
||||
'Registering a custom Doctrine type requires Doctrine DBAL (doctrine/dbal).'
|
||||
);
|
||||
}
|
||||
|
||||
if (! Type::hasType($name)) {
|
||||
Type::addType($name, $class);
|
||||
}
|
||||
|
||||
$this->doctrineTypeMappings[$name] = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current PDO connection.
|
||||
*
|
||||
@@ -950,7 +1088,8 @@ class Connection implements ConnectionInterface
|
||||
return $this->getPdo();
|
||||
}
|
||||
|
||||
if ($this->recordsModified && $this->getConfig('sticky')) {
|
||||
if ($this->readOnWriteConnection ||
|
||||
($this->recordsModified && $this->getConfig('sticky'))) {
|
||||
return $this->getPdo();
|
||||
}
|
||||
|
||||
@@ -1022,6 +1161,16 @@ class Connection implements ConnectionInterface
|
||||
return $this->getConfig('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database connection full name.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getNameWithReadWriteType()
|
||||
{
|
||||
return $this->getName().($this->readWriteType ? '::'.$this->readWriteType : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an option from the configuration options.
|
||||
*
|
||||
@@ -1145,6 +1294,29 @@ class Connection implements ConnectionInterface
|
||||
$this->events = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the transaction manager instance on the connection.
|
||||
*
|
||||
* @param \Illuminate\Database\DatabaseTransactionsManager $manager
|
||||
* @return $this
|
||||
*/
|
||||
public function setTransactionManager($manager)
|
||||
{
|
||||
$this->transactionsManager = $manager;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the transaction manager for this connection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unsetTransactionManager()
|
||||
{
|
||||
$this->transactionsManager = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the connection is in a "dry run".
|
||||
*
|
||||
@@ -1228,6 +1400,19 @@ class Connection implements ConnectionInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the read / write type of the connection.
|
||||
*
|
||||
* @param string|null $readWriteType
|
||||
* @return $this
|
||||
*/
|
||||
public function setReadWriteType($readWriteType)
|
||||
{
|
||||
$this->readWriteType = $readWriteType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table prefix for the connection.
|
||||
*
|
||||
|
||||
7
vendor/laravel/framework/src/Illuminate/Database/ConnectionInterface.php
vendored
Normal file → Executable file
7
vendor/laravel/framework/src/Illuminate/Database/ConnectionInterface.php
vendored
Normal file → Executable file
@@ -160,4 +160,11 @@ interface ConnectionInterface
|
||||
* @return array
|
||||
*/
|
||||
public function pretend(Closure $callback);
|
||||
|
||||
/**
|
||||
* Get the name of the connected database.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDatabaseName();
|
||||
}
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolver.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolver.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolverInterface.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolverInterface.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectorInterface.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectorInterface.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php
vendored
Normal file → Executable file
18
vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php
vendored
Normal file → Executable file
18
vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php
vendored
Normal file → Executable file
@@ -33,6 +33,8 @@ class PostgresConnector extends Connector implements ConnectorInterface
|
||||
$this->getDsn($config), $config, $this->getOptions($config)
|
||||
);
|
||||
|
||||
$this->configureIsolationLevel($connection, $config);
|
||||
|
||||
$this->configureEncoding($connection, $config);
|
||||
|
||||
// Next, we will check to see if a timezone has been specified in this config
|
||||
@@ -52,6 +54,20 @@ class PostgresConnector extends Connector implements ConnectorInterface
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection transaction isolation level.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureIsolationLevel($connection, array $config)
|
||||
{
|
||||
if (isset($config['isolation_level'])) {
|
||||
$connection->prepare("set session characteristics as transaction isolation level {$config['isolation_level']}")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection character set and collation.
|
||||
*
|
||||
@@ -146,7 +162,7 @@ class PostgresConnector extends Connector implements ConnectorInterface
|
||||
|
||||
$host = isset($host) ? "host={$host};" : '';
|
||||
|
||||
$dsn = "pgsql:{$host}dbname={$database}";
|
||||
$dsn = "pgsql:{$host}dbname='{$database}'";
|
||||
|
||||
// If a port was specified, we will add it to this Postgres DSN connections
|
||||
// format. Once we have done that we are ready to return this connection
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/SQLiteConnector.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/SQLiteConnector.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/SqlServerConnector.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Connectors/SqlServerConnector.php
vendored
Normal file → Executable file
@@ -3,6 +3,7 @@
|
||||
namespace Illuminate\Database\Console\Factories;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class FactoryMakeCommand extends GeneratorCommand
|
||||
@@ -59,19 +60,30 @@ class FactoryMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function buildClass($name)
|
||||
{
|
||||
$factory = class_basename(Str::ucfirst(str_replace('Factory', '', $name)));
|
||||
|
||||
$namespaceModel = $this->option('model')
|
||||
? $this->qualifyClass($this->option('model'))
|
||||
: trim($this->rootNamespace(), '\\').'\\Model';
|
||||
? $this->qualifyModel($this->option('model'))
|
||||
: $this->qualifyModel($this->guessModelName($name));
|
||||
|
||||
$model = class_basename($namespaceModel);
|
||||
|
||||
if (Str::startsWith($namespaceModel, $this->rootNamespace().'Models')) {
|
||||
$namespace = Str::beforeLast('Database\\Factories\\'.Str::after($namespaceModel, $this->rootNamespace().'Models\\'), '\\');
|
||||
} else {
|
||||
$namespace = 'Database\\Factories';
|
||||
}
|
||||
|
||||
$replace = [
|
||||
'{{ factoryNamespace }}' => $namespace,
|
||||
'NamespacedDummyModel' => $namespaceModel,
|
||||
'{{ namespacedModel }}' => $namespaceModel,
|
||||
'{{namespacedModel}}' => $namespaceModel,
|
||||
'DummyModel' => $model,
|
||||
'{{ model }}' => $model,
|
||||
'{{model}}' => $model,
|
||||
'{{ factory }}' => $factory,
|
||||
'{{factory}}' => $factory,
|
||||
];
|
||||
|
||||
return str_replace(
|
||||
@@ -87,11 +99,34 @@ class FactoryMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
$name = str_replace(
|
||||
['\\', '/'], '', $this->argument('name')
|
||||
);
|
||||
$name = (string) Str::of($name)->replaceFirst($this->rootNamespace(), '')->finish('Factory');
|
||||
|
||||
return $this->laravel->databasePath()."/factories/{$name}.php";
|
||||
return $this->laravel->databasePath().'/factories/'.str_replace('\\', '/', $name).'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the model name from the Factory name or return a default model name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function guessModelName($name)
|
||||
{
|
||||
if (Str::endsWith($name, 'Factory')) {
|
||||
$name = substr($name, 0, -7);
|
||||
}
|
||||
|
||||
$modelName = $this->qualifyModel(Str::after($name, $this->rootNamespace()));
|
||||
|
||||
if (class_exists($modelName)) {
|
||||
return $modelName;
|
||||
}
|
||||
|
||||
if (is_dir(app_path('Models/'))) {
|
||||
return $this->rootNamespace().'Models\Model';
|
||||
}
|
||||
|
||||
return $this->rootNamespace().'Model';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
<?php
|
||||
|
||||
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||
namespace {{ factoryNamespace }};
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
use {{ namespacedModel }};
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
$factory->define({{ model }}::class, function (Faker $faker) {
|
||||
return [
|
||||
//
|
||||
];
|
||||
});
|
||||
class {{ factory }}Factory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/BaseCommand.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/BaseCommand.php
vendored
Normal file → Executable file
@@ -4,6 +4,8 @@ namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Events\DatabaseRefreshed;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class FreshCommand extends Command
|
||||
@@ -48,10 +50,17 @@ class FreshCommand extends Command
|
||||
'--database' => $database,
|
||||
'--path' => $this->input->getOption('path'),
|
||||
'--realpath' => $this->input->getOption('realpath'),
|
||||
'--schema-path' => $this->input->getOption('schema-path'),
|
||||
'--force' => true,
|
||||
'--step' => $this->option('step'),
|
||||
]));
|
||||
|
||||
if ($this->laravel->bound(Dispatcher::class)) {
|
||||
$this->laravel[Dispatcher::class]->dispatch(
|
||||
new DatabaseRefreshed
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->needsSeeding()) {
|
||||
$this->runSeeder($database);
|
||||
}
|
||||
@@ -79,7 +88,7 @@ class FreshCommand extends Command
|
||||
{
|
||||
$this->call('db:seed', array_filter([
|
||||
'--database' => $database,
|
||||
'--class' => $this->option('seeder') ?: 'DatabaseSeeder',
|
||||
'--class' => $this->option('seeder') ?: 'Database\\Seeders\\DatabaseSeeder',
|
||||
'--force' => true,
|
||||
]));
|
||||
}
|
||||
@@ -98,6 +107,7 @@ class FreshCommand extends Command
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
['path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The path(s) to the migrations files to be executed'],
|
||||
['realpath', null, InputOption::VALUE_NONE, 'Indicate any provided migration file paths are pre-resolved absolute paths'],
|
||||
['schema-path', null, InputOption::VALUE_OPTIONAL, 'The path to a schema dump file'],
|
||||
['seed', null, InputOption::VALUE_NONE, 'Indicates if the seed task should be re-run'],
|
||||
['seeder', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder'],
|
||||
['step', null, InputOption::VALUE_NONE, 'Force the migrations to be run so they can be rolled back individually'],
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/InstallCommand.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/InstallCommand.php
vendored
Normal file → Executable file
86
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php
vendored
Normal file → Executable file
86
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php
vendored
Normal file → Executable file
@@ -3,7 +3,10 @@
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Events\SchemaLoaded;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Illuminate\Database\SqlServerConnection;
|
||||
|
||||
class MigrateCommand extends BaseCommand
|
||||
{
|
||||
@@ -18,8 +21,10 @@ class MigrateCommand extends BaseCommand
|
||||
{--force : Force the operation to run when in production}
|
||||
{--path=* : The path(s) to the migrations files to be executed}
|
||||
{--realpath : Indicate any provided migration file paths are pre-resolved absolute paths}
|
||||
{--schema-path= : The path to a schema dump file}
|
||||
{--pretend : Dump the SQL queries that would be run}
|
||||
{--seed : Indicates if the seed task should be re-run}
|
||||
{--seeder= : The class name of the root seeder}
|
||||
{--step : Force the migrations to be run so they can be rolled back individually}';
|
||||
|
||||
/**
|
||||
@@ -36,17 +41,26 @@ class MigrateCommand extends BaseCommand
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* The event dispatcher instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
protected $dispatcher;
|
||||
|
||||
/**
|
||||
* Create a new migration command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
public function __construct(Migrator $migrator, Dispatcher $dispatcher)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
$this->dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +90,10 @@ class MigrateCommand extends BaseCommand
|
||||
// seed task to re-populate the database, which is convenient when adding
|
||||
// a migration and a seed at the same time, as it is only this command.
|
||||
if ($this->option('seed') && ! $this->option('pretend')) {
|
||||
$this->call('db:seed', ['--force' => true]);
|
||||
$this->call('db:seed', [
|
||||
'--class' => $this->option('seeder') ?: 'Database\\Seeders\\DatabaseSeeder',
|
||||
'--force' => true,
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -95,5 +112,70 @@ class MigrateCommand extends BaseCommand
|
||||
'--database' => $this->option('database'),
|
||||
]));
|
||||
}
|
||||
|
||||
if (! $this->migrator->hasRunAnyMigrations() && ! $this->option('pretend')) {
|
||||
$this->loadSchemaState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the schema state to seed the initial database schema structure.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function loadSchemaState()
|
||||
{
|
||||
$connection = $this->migrator->resolveConnection($this->option('database'));
|
||||
|
||||
// First, we will make sure that the connection supports schema loading and that
|
||||
// the schema file exists before we proceed any further. If not, we will just
|
||||
// continue with the standard migration operation as normal without errors.
|
||||
if ($connection instanceof SqlServerConnection ||
|
||||
! is_file($path = $this->schemaPath($connection))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->line('<info>Loading stored database schema:</info> '.$path);
|
||||
|
||||
$startTime = microtime(true);
|
||||
|
||||
// Since the schema file will create the "migrations" table and reload it to its
|
||||
// proper state, we need to delete it here so we don't get an error that this
|
||||
// table already exists when the stored database schema file gets executed.
|
||||
$this->migrator->deleteRepository();
|
||||
|
||||
$connection->getSchemaState()->handleOutputUsing(function ($type, $buffer) {
|
||||
$this->output->write($buffer);
|
||||
})->load($path);
|
||||
|
||||
$runTime = number_format((microtime(true) - $startTime) * 1000, 2);
|
||||
|
||||
// Finally, we will fire an event that this schema has been loaded so developers
|
||||
// can perform any post schema load tasks that are necessary in listeners for
|
||||
// this event, which may seed the database tables with some necessary data.
|
||||
$this->dispatcher->dispatch(
|
||||
new SchemaLoaded($connection, $path)
|
||||
);
|
||||
|
||||
$this->line('<info>Loaded stored database schema.</info> ('.$runTime.'ms)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the stored schema for the given connection.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return string
|
||||
*/
|
||||
protected function schemaPath($connection)
|
||||
{
|
||||
if ($this->option('schema-path')) {
|
||||
return $this->option('schema-path');
|
||||
}
|
||||
|
||||
if (file_exists($path = database_path('schema/'.$connection->getName().'-schema.dump'))) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
return database_path('schema/'.$connection->getName().'-schema.sql');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,14 +132,4 @@ class MigrateMakeCommand extends BaseCommand
|
||||
|
||||
return parent::getMigrationPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given path(s) are pre-resolved "real" paths.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function usingRealPath()
|
||||
{
|
||||
return $this->input->hasOption('realpath') && $this->option('realpath');
|
||||
}
|
||||
}
|
||||
|
||||
10
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RefreshCommand.php
vendored
Normal file → Executable file
10
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RefreshCommand.php
vendored
Normal file → Executable file
@@ -4,6 +4,8 @@ namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Events\DatabaseRefreshed;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class RefreshCommand extends Command
|
||||
@@ -63,6 +65,12 @@ class RefreshCommand extends Command
|
||||
'--force' => true,
|
||||
]));
|
||||
|
||||
if ($this->laravel->bound(Dispatcher::class)) {
|
||||
$this->laravel[Dispatcher::class]->dispatch(
|
||||
new DatabaseRefreshed
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->needsSeeding()) {
|
||||
$this->runSeeder($database);
|
||||
}
|
||||
@@ -126,7 +134,7 @@ class RefreshCommand extends Command
|
||||
{
|
||||
$this->call('db:seed', array_filter([
|
||||
'--database' => $database,
|
||||
'--class' => $this->option('seeder') ?: 'DatabaseSeeder',
|
||||
'--class' => $this->option('seeder') ?: 'Database\\Seeders\\DatabaseSeeder',
|
||||
'--force' => true,
|
||||
]));
|
||||
}
|
||||
|
||||
2
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/ResetCommand.php
vendored
Normal file → Executable file
2
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/ResetCommand.php
vendored
Normal file → Executable file
@@ -67,8 +67,6 @@ class ResetCommand extends BaseCommand
|
||||
$this->getMigrationPaths(), $this->option('pretend')
|
||||
);
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RollbackCommand.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RollbackCommand.php
vendored
Normal file → Executable file
@@ -6,6 +6,7 @@ use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class SeedCommand extends Command
|
||||
@@ -81,9 +82,20 @@ class SeedCommand extends Command
|
||||
*/
|
||||
protected function getSeeder()
|
||||
{
|
||||
$class = $this->laravel->make($this->input->getOption('class'));
|
||||
$class = $this->input->getArgument('class') ?? $this->input->getOption('class');
|
||||
|
||||
return $class->setContainer($this->laravel)->setCommand($this);
|
||||
if (strpos($class, '\\') === false) {
|
||||
$class = 'Database\\Seeders\\'.$class;
|
||||
}
|
||||
|
||||
if ($class === 'Database\\Seeders\\DatabaseSeeder' &&
|
||||
! class_exists($class)) {
|
||||
$class = 'DatabaseSeeder';
|
||||
}
|
||||
|
||||
return $this->laravel->make($class)
|
||||
->setContainer($this->laravel)
|
||||
->setCommand($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,6 +110,18 @@ class SeedCommand extends Command
|
||||
return $database ?: $this->laravel['config']['database.default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getArguments()
|
||||
{
|
||||
return [
|
||||
['class', InputArgument::OPTIONAL, 'The class name of the root seeder', null],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
@@ -106,10 +130,8 @@ class SeedCommand extends Command
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['class', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder', 'DatabaseSeeder'],
|
||||
|
||||
['class', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder', 'Database\\Seeders\\DatabaseSeeder'],
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to seed'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production'],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
namespace Illuminate\Database\Console\Seeds;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Composer;
|
||||
|
||||
class SeederMakeCommand extends GeneratorCommand
|
||||
{
|
||||
@@ -29,27 +27,6 @@ class SeederMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected $type = 'Seeder';
|
||||
|
||||
/**
|
||||
* The Composer instance.
|
||||
*
|
||||
* @var \Illuminate\Support\Composer
|
||||
*/
|
||||
protected $composer;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @param \Illuminate\Support\Composer $composer
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Filesystem $files, Composer $composer)
|
||||
{
|
||||
parent::__construct($files);
|
||||
|
||||
$this->composer = $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
@@ -58,8 +35,6 @@ class SeederMakeCommand extends GeneratorCommand
|
||||
public function handle()
|
||||
{
|
||||
parent::handle();
|
||||
|
||||
$this->composer->dumpAutoloads();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,7 +55,7 @@ class SeederMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function resolveStubPath($stub)
|
||||
{
|
||||
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||||
return is_file($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||||
? $customPath
|
||||
: __DIR__.$stub;
|
||||
}
|
||||
@@ -93,7 +68,11 @@ class SeederMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
return $this->laravel->databasePath().'/seeds/'.$name.'.php';
|
||||
if (is_dir($this->laravel->databasePath().'/seeds')) {
|
||||
return $this->laravel->databasePath().'/seeds/'.$name.'.php';
|
||||
} else {
|
||||
return $this->laravel->databasePath().'/seeders/'.$name.'.php';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class {{ class }} extends Seeder
|
||||
|
||||
85
vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php
vendored
Normal file → Executable file
85
vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php
vendored
Normal file → Executable file
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\ConfigurationUrlParser;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use PDO;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Database\Connection
|
||||
@@ -49,6 +51,13 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
*/
|
||||
protected $reconnector;
|
||||
|
||||
/**
|
||||
* The custom Doctrine column types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $doctrineTypes = [];
|
||||
|
||||
/**
|
||||
* Create a new database manager instance.
|
||||
*
|
||||
@@ -62,7 +71,7 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
$this->factory = $factory;
|
||||
|
||||
$this->reconnector = function ($connection) {
|
||||
$this->reconnect($connection->getName());
|
||||
$this->reconnect($connection->getNameWithReadWriteType());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -165,7 +174,7 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
*/
|
||||
protected function configure(Connection $connection, $type)
|
||||
{
|
||||
$connection = $this->setPdoForType($connection, $type);
|
||||
$connection = $this->setPdoForType($connection, $type)->setReadWriteType($type);
|
||||
|
||||
// First we'll set the fetch mode and a few other dependencies of the database
|
||||
// connection. This method basically just configures and prepares it to get
|
||||
@@ -174,11 +183,17 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
$connection->setEventDispatcher($this->app['events']);
|
||||
}
|
||||
|
||||
if ($this->app->bound('db.transactions')) {
|
||||
$connection->setTransactionManager($this->app['db.transactions']);
|
||||
}
|
||||
|
||||
// Here we'll set a reconnector callback. This reconnector can be any callable
|
||||
// so we will set a Closure to reconnect from this manager with the name of
|
||||
// the connection, which will allow us to reconnect from the connections.
|
||||
$connection->setReconnector($this->reconnector);
|
||||
|
||||
$this->registerConfiguredDoctrineTypes($connection);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
@@ -200,6 +215,49 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register custom Doctrine types with the connection.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*/
|
||||
protected function registerConfiguredDoctrineTypes(Connection $connection): void
|
||||
{
|
||||
foreach ($this->app['config']->get('database.dbal.types', []) as $name => $class) {
|
||||
$this->registerDoctrineType($class, $name, $name);
|
||||
}
|
||||
|
||||
foreach ($this->doctrineTypes as $name => [$type, $class]) {
|
||||
$connection->registerDoctrineType($class, $name, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom Doctrine type.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return void
|
||||
*
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function registerDoctrineType(string $class, string $name, string $type): void
|
||||
{
|
||||
if (! class_exists('Doctrine\DBAL\Connection')) {
|
||||
throw new RuntimeException(
|
||||
'Registering a custom Doctrine type requires Doctrine DBAL (doctrine/dbal).'
|
||||
);
|
||||
}
|
||||
|
||||
if (! Type::hasType($name)) {
|
||||
Type::addType($name, $class);
|
||||
}
|
||||
|
||||
$this->doctrineTypes[$name] = [$type, $class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the given database and remove from local cache.
|
||||
*
|
||||
@@ -271,11 +329,15 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
*/
|
||||
protected function refreshPdoConnections($name)
|
||||
{
|
||||
$fresh = $this->makeConnection($name);
|
||||
[$database, $type] = $this->parseConnectionName($name);
|
||||
|
||||
$fresh = $this->configure(
|
||||
$this->makeConnection($database), $type
|
||||
);
|
||||
|
||||
return $this->connections[$name]
|
||||
->setPdo($fresh->getRawPdo())
|
||||
->setReadPdo($fresh->getRawReadPdo());
|
||||
->setPdo($fresh->getRawPdo())
|
||||
->setReadPdo($fresh->getRawReadPdo());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,6 +417,19 @@ class DatabaseManager implements ConnectionResolverInterface
|
||||
$this->reconnector = $reconnector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the application instance used by the manager.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Foundation\Application $app
|
||||
* @return $this
|
||||
*/
|
||||
public function setApplication($app)
|
||||
{
|
||||
$this->app = $app;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass methods to the default connection.
|
||||
*
|
||||
|
||||
13
vendor/laravel/framework/src/Illuminate/Database/DatabaseServiceProvider.php
vendored
Normal file → Executable file
13
vendor/laravel/framework/src/Illuminate/Database/DatabaseServiceProvider.php
vendored
Normal file → Executable file
@@ -6,7 +6,6 @@ use Faker\Factory as FakerFactory;
|
||||
use Faker\Generator as FakerGenerator;
|
||||
use Illuminate\Contracts\Queue\EntityResolver;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\QueueEntityResolver;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
@@ -42,9 +41,7 @@ class DatabaseServiceProvider extends ServiceProvider
|
||||
Model::clearBootedModels();
|
||||
|
||||
$this->registerConnectionServices();
|
||||
|
||||
$this->registerEloquentFactory();
|
||||
|
||||
$this->registerQueueableEntityResolver();
|
||||
}
|
||||
|
||||
@@ -72,6 +69,10 @@ class DatabaseServiceProvider extends ServiceProvider
|
||||
$this->app->bind('db.connection', function ($app) {
|
||||
return $app['db']->connection();
|
||||
});
|
||||
|
||||
$this->app->singleton('db.transactions', function ($app) {
|
||||
return new DatabaseTransactionsManager;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,12 +93,6 @@ class DatabaseServiceProvider extends ServiceProvider
|
||||
|
||||
return static::$fakers[$locale];
|
||||
});
|
||||
|
||||
$this->app->singleton(EloquentFactory::class, function ($app) {
|
||||
return EloquentFactory::construct(
|
||||
$app->make(FakerGenerator::class), $this->app->databasePath('factories')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,7 @@ trait DetectsConcurrencyErrors
|
||||
*/
|
||||
protected function causedByConcurrencyError(Throwable $e)
|
||||
{
|
||||
if ($e instanceof PDOException && $e->getCode() === '40001') {
|
||||
if ($e instanceof PDOException && ($e->getCode() === 40001 || $e->getCode() === '40001')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,13 @@ trait DetectsLostConnections
|
||||
'SSL: Connection timed out',
|
||||
'SQLSTATE[HY000]: General error: 1105 The last transaction was aborted due to Seamless Scaling. Please retry.',
|
||||
'Temporary failure in name resolution',
|
||||
'SSL: Broken pipe',
|
||||
'SQLSTATE[08S01]: Communication link failure',
|
||||
'SQLSTATE[08006] [7] could not connect to server: Connection refused Is the server running on host',
|
||||
'SQLSTATE[HY000]: General error: 7 SSL SYSCALL error: No route to host',
|
||||
'The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.',
|
||||
'SQLSTATE[08006] [7] could not translate host name',
|
||||
'TCP Provider: Error code 0x274C',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
279
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
vendored
Normal file → Executable file
279
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
vendored
Normal file → Executable file
@@ -10,6 +10,7 @@ use Illuminate\Database\Concerns\BuildsQueries;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Database\RecordsNotFoundException;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
@@ -24,7 +25,10 @@ use ReflectionMethod;
|
||||
*/
|
||||
class Builder
|
||||
{
|
||||
use BuildsQueries, Concerns\QueriesRelationships, ForwardsCalls;
|
||||
use Concerns\QueriesRelationships, ForwardsCalls;
|
||||
use BuildsQueries {
|
||||
sole as baseSole;
|
||||
}
|
||||
|
||||
/**
|
||||
* The base query builder instance.
|
||||
@@ -68,14 +72,42 @@ class Builder
|
||||
*/
|
||||
protected $onDelete;
|
||||
|
||||
/**
|
||||
* The properties that should be returned from query builder.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $propertyPassthru = [
|
||||
'from',
|
||||
];
|
||||
|
||||
/**
|
||||
* The methods that should be returned from query builder.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $passthru = [
|
||||
'insert', 'insertOrIgnore', 'insertGetId', 'insertUsing', 'getBindings', 'toSql', 'dump', 'dd',
|
||||
'exists', 'doesntExist', 'count', 'min', 'max', 'avg', 'average', 'sum', 'getConnection', 'raw', 'getGrammar',
|
||||
'aggregate',
|
||||
'average',
|
||||
'avg',
|
||||
'count',
|
||||
'dd',
|
||||
'doesntExist',
|
||||
'dump',
|
||||
'exists',
|
||||
'explain',
|
||||
'getBindings',
|
||||
'getConnection',
|
||||
'getGrammar',
|
||||
'insert',
|
||||
'insertGetId',
|
||||
'insertOrIgnore',
|
||||
'insertUsing',
|
||||
'max',
|
||||
'min',
|
||||
'raw',
|
||||
'sum',
|
||||
'toSql',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -188,6 +220,10 @@ class Builder
|
||||
*/
|
||||
public function whereKey($id)
|
||||
{
|
||||
if ($id instanceof Model) {
|
||||
$id = $id->getKey();
|
||||
}
|
||||
|
||||
if (is_array($id) || $id instanceof Arrayable) {
|
||||
$this->query->whereIn($this->model->getQualifiedKeyName(), $id);
|
||||
|
||||
@@ -209,6 +245,10 @@ class Builder
|
||||
*/
|
||||
public function whereKeyNot($id)
|
||||
{
|
||||
if ($id instanceof Model) {
|
||||
$id = $id->getKey();
|
||||
}
|
||||
|
||||
if (is_array($id) || $id instanceof Arrayable) {
|
||||
$this->query->whereNotIn($this->model->getQualifiedKeyName(), $id);
|
||||
|
||||
@@ -251,7 +291,7 @@ class Builder
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @param string $boolean
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
* @return \Illuminate\Database\Eloquent\Model|static|null
|
||||
*/
|
||||
public function firstWhere($column, $operator = null, $value = null, $boolean = 'and')
|
||||
{
|
||||
@@ -319,8 +359,14 @@ class Builder
|
||||
{
|
||||
$instance = $this->newModelInstance();
|
||||
|
||||
return $instance->newCollection(array_map(function ($item) use ($instance) {
|
||||
return $instance->newFromBuilder($item);
|
||||
return $instance->newCollection(array_map(function ($item) use ($items, $instance) {
|
||||
$model = $instance->newFromBuilder($item);
|
||||
|
||||
if (count($items) > 1) {
|
||||
$model->preventsLazyLoading = Model::preventsLazyLoading();
|
||||
}
|
||||
|
||||
return $model;
|
||||
}, $items));
|
||||
}
|
||||
|
||||
@@ -429,7 +475,7 @@ class Builder
|
||||
return $instance;
|
||||
}
|
||||
|
||||
return $this->newModelInstance($attributes + $values);
|
||||
return $this->newModelInstance(array_merge($attributes, $values));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -439,13 +485,13 @@ class Builder
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
*/
|
||||
public function firstOrCreate(array $attributes, array $values = [])
|
||||
public function firstOrCreate(array $attributes = [], array $values = [])
|
||||
{
|
||||
if (! is_null($instance = $this->where($attributes)->first())) {
|
||||
return $instance;
|
||||
}
|
||||
|
||||
return tap($this->newModelInstance($attributes + $values), function ($instance) {
|
||||
return tap($this->newModelInstance(array_merge($attributes, $values)), function ($instance) {
|
||||
$instance->save();
|
||||
});
|
||||
}
|
||||
@@ -503,6 +549,24 @@ class Builder
|
||||
return $callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result if it's the sole matching record.
|
||||
*
|
||||
* @param array|string $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
* @throws \Illuminate\Database\MultipleRecordsFoundException
|
||||
*/
|
||||
public function sole($columns = ['*'])
|
||||
{
|
||||
try {
|
||||
return $this->baseSole($columns);
|
||||
} catch (RecordsNotFoundException $exception) {
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->model));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single column's value from the first result of a query.
|
||||
*
|
||||
@@ -516,6 +580,19 @@ class Builder
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single column's value from the first result of the query or throw an exception.
|
||||
*
|
||||
* @param string|\Illuminate\Database\Query\Expression $column
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function valueOrFail($column)
|
||||
{
|
||||
return $this->firstOrFail([$column])->{Str::afterLast($column, '.')};
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a "select" statement.
|
||||
*
|
||||
@@ -764,6 +841,49 @@ class Builder
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the given query into a cursor paginator.
|
||||
*
|
||||
* @param int|null $perPage
|
||||
* @param array $columns
|
||||
* @param string $cursorName
|
||||
* @param \Illuminate\Pagination\Cursor|string|null $cursor
|
||||
* @return \Illuminate\Contracts\Pagination\CursorPaginator
|
||||
*/
|
||||
public function cursorPaginate($perPage = null, $columns = ['*'], $cursorName = 'cursor', $cursor = null)
|
||||
{
|
||||
$perPage = $perPage ?: $this->model->getPerPage();
|
||||
|
||||
return $this->paginateUsingCursor($perPage, $columns, $cursorName, $cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the proper order by required for cursor pagination.
|
||||
*
|
||||
* @param bool $shouldReverse
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function ensureOrderForCursorPagination($shouldReverse = false)
|
||||
{
|
||||
if (empty($this->query->orders) && empty($this->query->unionOrders)) {
|
||||
$this->enforceOrderBy();
|
||||
}
|
||||
|
||||
if ($shouldReverse) {
|
||||
$this->query->orders = collect($this->query->orders)->map(function ($order) {
|
||||
$order['direction'] = $order['direction'] === 'asc' ? 'desc' : 'asc';
|
||||
|
||||
return $order;
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
if ($this->query->unionOrders) {
|
||||
return collect($this->query->unionOrders);
|
||||
}
|
||||
|
||||
return collect($this->query->orders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a new model and return the instance.
|
||||
*
|
||||
@@ -791,7 +911,7 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a record in the database.
|
||||
* Update records in the database.
|
||||
*
|
||||
* @param array $values
|
||||
* @return int
|
||||
@@ -801,6 +921,35 @@ class Builder
|
||||
return $this->toBase()->update($this->addUpdatedAtColumn($values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert new records or update the existing ones.
|
||||
*
|
||||
* @param array $values
|
||||
* @param array|string $uniqueBy
|
||||
* @param array|null $update
|
||||
* @return int
|
||||
*/
|
||||
public function upsert(array $values, $uniqueBy, $update = null)
|
||||
{
|
||||
if (empty($values)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (! is_array(reset($values))) {
|
||||
$values = [$values];
|
||||
}
|
||||
|
||||
if (is_null($update)) {
|
||||
$update = array_keys(reset($values));
|
||||
}
|
||||
|
||||
return $this->toBase()->upsert(
|
||||
$this->addTimestampsToUpsertValues($values),
|
||||
$uniqueBy,
|
||||
$this->addUpdatedAtToUpsertColumns($update)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a column's value by a given amount.
|
||||
*
|
||||
@@ -855,7 +1004,7 @@ class Builder
|
||||
|
||||
$qualifiedColumn = end($segments).'.'.$column;
|
||||
|
||||
$values[$qualifiedColumn] = $values[$column];
|
||||
$values[$qualifiedColumn] = Arr::get($values, $qualifiedColumn, $values[$column]);
|
||||
|
||||
unset($values[$column]);
|
||||
|
||||
@@ -863,7 +1012,58 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a record from the database.
|
||||
* Add timestamps to the inserted values.
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
protected function addTimestampsToUpsertValues(array $values)
|
||||
{
|
||||
if (! $this->model->usesTimestamps()) {
|
||||
return $values;
|
||||
}
|
||||
|
||||
$timestamp = $this->model->freshTimestampString();
|
||||
|
||||
$columns = array_filter([
|
||||
$this->model->getCreatedAtColumn(),
|
||||
$this->model->getUpdatedAtColumn(),
|
||||
]);
|
||||
|
||||
foreach ($columns as $column) {
|
||||
foreach ($values as &$row) {
|
||||
$row = array_merge([$column => $timestamp], $row);
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the "updated at" column to the updated columns.
|
||||
*
|
||||
* @param array $update
|
||||
* @return array
|
||||
*/
|
||||
protected function addUpdatedAtToUpsertColumns(array $update)
|
||||
{
|
||||
if (! $this->model->usesTimestamps()) {
|
||||
return $update;
|
||||
}
|
||||
|
||||
$column = $this->model->getUpdatedAtColumn();
|
||||
|
||||
if (! is_null($column) &&
|
||||
! array_key_exists($column, $update) &&
|
||||
! in_array($column, $update)) {
|
||||
$update[] = $column;
|
||||
}
|
||||
|
||||
return $update;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete records from the database.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -931,7 +1131,9 @@ class Builder
|
||||
// Next we'll pass the scope callback to the callScope method which will take
|
||||
// care of grouping the "wheres" properly so the logical order doesn't get
|
||||
// messed up when adding scopes. Then we'll return back out the builder.
|
||||
$builder = $builder->callNamedScope($scope, (array) $parameters);
|
||||
$builder = $builder->callNamedScope(
|
||||
$scope, Arr::wrap($parameters)
|
||||
);
|
||||
}
|
||||
|
||||
return $builder;
|
||||
@@ -1084,12 +1286,17 @@ class Builder
|
||||
/**
|
||||
* Set the relationships that should be eager loaded.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @param string|array $relations
|
||||
* @param string|\Closure|null $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function with($relations)
|
||||
public function with($relations, $callback = null)
|
||||
{
|
||||
$eagerLoad = $this->parseWithRelations(is_string($relations) ? func_get_args() : $relations);
|
||||
if ($callback instanceof Closure) {
|
||||
$eagerLoad = $this->parseWithRelations([$relations => $callback]);
|
||||
} else {
|
||||
$eagerLoad = $this->parseWithRelations(is_string($relations) ? func_get_args() : $relations);
|
||||
}
|
||||
|
||||
$this->eagerLoad = array_merge($this->eagerLoad, $eagerLoad);
|
||||
|
||||
@@ -1111,6 +1318,19 @@ class Builder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relationships that should be eager loaded while removing any previously added eager loading specifications.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function withOnly($relations)
|
||||
{
|
||||
$this->eagerLoad = [];
|
||||
|
||||
return $this->with($relations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the model being queried.
|
||||
*
|
||||
@@ -1322,6 +1542,17 @@ class Builder
|
||||
return $this->model->qualifyColumn($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Qualify the given columns with the model's table.
|
||||
*
|
||||
* @param array|\Illuminate\Database\Query\Expression $columns
|
||||
* @return array
|
||||
*/
|
||||
public function qualifyColumns($columns)
|
||||
{
|
||||
return $this->model->qualifyColumns($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the given macro by name.
|
||||
*
|
||||
@@ -1380,6 +1611,10 @@ class Builder
|
||||
return new HigherOrderBuilderProxy($this, $key);
|
||||
}
|
||||
|
||||
if (in_array($key, $this->propertyPassthru)) {
|
||||
return $this->toBase()->{$key};
|
||||
}
|
||||
|
||||
throw new Exception("Property [{$key}] does not exist on the Eloquent builder instance.");
|
||||
}
|
||||
|
||||
@@ -1483,6 +1718,16 @@ class Builder
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the Eloquent query builder.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function clone()
|
||||
{
|
||||
return clone $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a clone of the underlying query builder when cloning.
|
||||
*
|
||||
|
||||
94
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php
vendored
Normal file → Executable file
94
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php
vendored
Normal file → Executable file
@@ -64,12 +64,14 @@ class Collection extends BaseCollection implements QueueableCollection
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship counts onto the collection.
|
||||
* Load a set of aggregations over relationship's column onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @param string $function
|
||||
* @return $this
|
||||
*/
|
||||
public function loadCount($relations)
|
||||
public function loadAggregate($relations, $column, $function = null)
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return $this;
|
||||
@@ -78,7 +80,7 @@ class Collection extends BaseCollection implements QueueableCollection
|
||||
$models = $this->first()->newModelQuery()
|
||||
->whereKey($this->modelKeys())
|
||||
->select($this->first()->getKeyName())
|
||||
->withCount(...func_get_args())
|
||||
->withAggregate($relations, $column, $function)
|
||||
->get()
|
||||
->keyBy($this->first()->getKeyName());
|
||||
|
||||
@@ -90,12 +92,84 @@ class Collection extends BaseCollection implements QueueableCollection
|
||||
$this->each(function ($model) use ($models, $attributes) {
|
||||
$extraAttributes = Arr::only($models->get($model->getKey())->getAttributes(), $attributes);
|
||||
|
||||
$model->forceFill($extraAttributes)->syncOriginalAttributes($attributes);
|
||||
$model->forceFill($extraAttributes)
|
||||
->syncOriginalAttributes($attributes)
|
||||
->mergeCasts($models->get($model->getKey())->getCasts());
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship counts onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadCount($relations)
|
||||
{
|
||||
return $this->loadAggregate($relations, '*', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship's max column values onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMax($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'max');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship's min column values onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMin($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'min');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship's column summations onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadSum($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'sum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationship's average column values onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadAvg($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'avg');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of related existences onto the collection.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadExists($relations)
|
||||
{
|
||||
return $this->loadAggregate($relations, '*', 'exists');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationships onto the collection if they are not already eager loaded.
|
||||
*
|
||||
@@ -160,7 +234,7 @@ class Collection extends BaseCollection implements QueueableCollection
|
||||
return;
|
||||
}
|
||||
|
||||
$models = $models->pluck($name);
|
||||
$models = $models->pluck($name)->whereNotNull();
|
||||
|
||||
if ($models->first() instanceof BaseCollection) {
|
||||
$models = $models->collapse();
|
||||
@@ -317,9 +391,11 @@ class Collection extends BaseCollection implements QueueableCollection
|
||||
->get()
|
||||
->getDictionary();
|
||||
|
||||
return $this->map(function ($model) use ($freshModels) {
|
||||
return $model->exists && isset($freshModels[$model->getKey()])
|
||||
? $freshModels[$model->getKey()] : null;
|
||||
return $this->filter(function ($model) use ($freshModels) {
|
||||
return $model->exists && isset($freshModels[$model->getKey()]);
|
||||
})
|
||||
->map(function ($model) use ($freshModels) {
|
||||
return $freshModels[$model->getKey()];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -618,7 +694,7 @@ class Collection extends BaseCollection implements QueueableCollection
|
||||
} elseif (count($relations) === 1) {
|
||||
return reset($relations);
|
||||
} else {
|
||||
return array_intersect(...$relations);
|
||||
return array_intersect(...array_values($relations));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ trait GuardsAttributes
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]|bool
|
||||
*/
|
||||
protected $guarded = ['*'];
|
||||
|
||||
@@ -77,7 +77,9 @@ trait GuardsAttributes
|
||||
*/
|
||||
public function getGuarded()
|
||||
{
|
||||
return $this->guarded;
|
||||
return $this->guarded === false
|
||||
? []
|
||||
: $this->guarded;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +130,7 @@ trait GuardsAttributes
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if current state is "unguarded".
|
||||
* Determine if the current state is "unguarded".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
@@ -215,9 +217,14 @@ trait GuardsAttributes
|
||||
protected function isGuardableColumn($key)
|
||||
{
|
||||
if (! isset(static::$guardableColumns[get_class($this)])) {
|
||||
static::$guardableColumns[get_class($this)] = $this->getConnection()
|
||||
$columns = $this->getConnection()
|
||||
->getSchemaBuilder()
|
||||
->getColumnListing($this->getTable());
|
||||
|
||||
if (empty($columns)) {
|
||||
return true;
|
||||
}
|
||||
static::$guardableColumns[get_class($this)] = $columns;
|
||||
}
|
||||
|
||||
return in_array($key, static::$guardableColumns[get_class($this)]);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -147,7 +147,7 @@ trait HasEvents
|
||||
* Register a model event with the dispatcher.
|
||||
*
|
||||
* @param string $event
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
protected static function registerModelEvent($event, $callback)
|
||||
@@ -230,7 +230,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a retrieved model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function retrieved($callback)
|
||||
@@ -241,7 +241,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a saving model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function saving($callback)
|
||||
@@ -252,7 +252,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a saved model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function saved($callback)
|
||||
@@ -263,7 +263,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register an updating model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function updating($callback)
|
||||
@@ -274,7 +274,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register an updated model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function updated($callback)
|
||||
@@ -285,7 +285,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a creating model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function creating($callback)
|
||||
@@ -296,7 +296,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a created model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function created($callback)
|
||||
@@ -307,7 +307,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a replicating model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function replicating($callback)
|
||||
@@ -318,7 +318,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a deleting model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function deleting($callback)
|
||||
@@ -329,7 +329,7 @@ trait HasEvents
|
||||
/**
|
||||
* Register a deleted model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @param \Illuminate\Events\QueuedClosure|\Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function deleted($callback)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\ClassMorphViolationException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
@@ -39,7 +40,7 @@ trait HasRelationships
|
||||
/**
|
||||
* The many to many relationship methods.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
public static $manyMethods = [
|
||||
'belongsToMany', 'morphToMany', 'morphedByMany',
|
||||
@@ -256,7 +257,7 @@ trait HasRelationships
|
||||
// If the type value is null it is probably safe to assume we're eager loading
|
||||
// the relationship. In this case we'll just pass in a dummy query where we
|
||||
// need to remove any eager loads that may already be defined on a model.
|
||||
return is_null($class = $this->{$type}) || $class === ''
|
||||
return is_null($class = $this->getAttributeFromArray($type)) || $class === ''
|
||||
? $this->morphEagerTo($name, $type, $id, $ownerKey)
|
||||
: $this->morphInstanceTo($class, $name, $type, $id, $ownerKey);
|
||||
}
|
||||
@@ -731,6 +732,10 @@ trait HasRelationships
|
||||
return array_search(static::class, $morphMap, true);
|
||||
}
|
||||
|
||||
if (Relation::requiresMorphMap()) {
|
||||
throw new ClassMorphViolationException($this);
|
||||
}
|
||||
|
||||
return static::class;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ trait HasTimestamps
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function updateTimestamps()
|
||||
public function updateTimestamps()
|
||||
{
|
||||
$time = $this->freshTimestamp();
|
||||
|
||||
@@ -130,7 +130,7 @@ trait HasTimestamps
|
||||
/**
|
||||
* Get the fully qualified "created at" column.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getQualifiedCreatedAtColumn()
|
||||
{
|
||||
@@ -140,7 +140,7 @@ trait HasTimestamps
|
||||
/**
|
||||
* Get the fully qualified "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getQualifiedUpdatedAtColumn()
|
||||
{
|
||||
|
||||
@@ -94,9 +94,7 @@ trait HidesAttributes
|
||||
*/
|
||||
public function makeVisibleIf($condition, $attributes)
|
||||
{
|
||||
$condition = $condition instanceof Closure ? $condition($this) : $condition;
|
||||
|
||||
return $condition ? $this->makeVisible($attributes) : $this;
|
||||
return value($condition, $this) ? $this->makeVisible($attributes) : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,8 +121,6 @@ trait HidesAttributes
|
||||
*/
|
||||
public function makeHiddenIf($condition, $attributes)
|
||||
{
|
||||
$condition = $condition instanceof Closure ? $condition($this) : $condition;
|
||||
|
||||
return value($condition) ? $this->makeHidden($attributes) : $this;
|
||||
return value($condition, $this) ? $this->makeHidden($attributes) : $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Closure;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\RelationNotFoundException;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
trait QueriesRelationships
|
||||
{
|
||||
@@ -36,7 +38,7 @@ trait QueriesRelationships
|
||||
}
|
||||
|
||||
if ($relation instanceof MorphTo) {
|
||||
throw new RuntimeException('Please use whereHasMorph() for MorphTo relationships.');
|
||||
return $this->hasMorph($relation, ['*'], $operator, $count, $boolean, $callback);
|
||||
}
|
||||
|
||||
// If we only need to check for the existence of the relation, then we can optimize
|
||||
@@ -189,7 +191,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
@@ -199,7 +201,9 @@ trait QueriesRelationships
|
||||
*/
|
||||
public function hasMorph($relation, $types, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
if (is_string($relation)) {
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
}
|
||||
|
||||
$types = (array) $types;
|
||||
|
||||
@@ -222,7 +226,7 @@ trait QueriesRelationships
|
||||
};
|
||||
}
|
||||
|
||||
$query->where($this->query->from.'.'.$relation->getMorphType(), '=', (new $type)->getMorphClass())
|
||||
$query->where($this->qualifyColumn($relation->getMorphType()), '=', (new $type)->getMorphClass())
|
||||
->whereHas($belongsTo, $callback, $operator, $count);
|
||||
});
|
||||
}
|
||||
@@ -254,7 +258,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
@@ -268,7 +272,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
@@ -282,7 +286,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
@@ -294,7 +298,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
@@ -309,7 +313,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
@@ -324,7 +328,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
@@ -337,7 +341,7 @@ trait QueriesRelationships
|
||||
/**
|
||||
* Add a polymorphic relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
@@ -348,12 +352,171 @@ trait QueriesRelationships
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to count the relations.
|
||||
* Add a basic where clause to a relationship query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|string|array|\Illuminate\Database\Query\Expression $column
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereRelation($relation, $column, $operator = null, $value = null)
|
||||
{
|
||||
return $this->whereHas($relation, function ($query) use ($column, $operator, $value) {
|
||||
$query->where($column, $operator, $value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an "or where" clause to a relationship query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|string|array|\Illuminate\Database\Query\Expression $column
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereRelation($relation, $column, $operator = null, $value = null)
|
||||
{
|
||||
return $this->orWhereHas($relation, function ($query) use ($column, $operator, $value) {
|
||||
$query->where($column, $operator, $value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship condition to the query with a where clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|string|array|\Illuminate\Database\Query\Expression $column
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereMorphRelation($relation, $types, $column, $operator = null, $value = null)
|
||||
{
|
||||
return $this->whereHasMorph($relation, $types, function ($query) use ($column, $operator, $value) {
|
||||
$query->where($column, $operator, $value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a polymorphic relationship condition to the query with an "or where" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param string|array $types
|
||||
* @param \Closure|string|array|\Illuminate\Database\Query\Expression $column
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereMorphRelation($relation, $types, $column, $operator = null, $value = null)
|
||||
{
|
||||
return $this->orWhereHasMorph($relation, $types, function ($query) use ($column, $operator, $value) {
|
||||
$query->where($column, $operator, $value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a morph-to relationship condition to the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Model|string $model
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereMorphedTo($relation, $model, $boolean = 'and')
|
||||
{
|
||||
if (is_string($relation)) {
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
}
|
||||
|
||||
if (is_string($model)) {
|
||||
$morphMap = Relation::morphMap();
|
||||
|
||||
if (! empty($morphMap) && in_array($model, $morphMap)) {
|
||||
$model = array_search($model, $morphMap, true);
|
||||
}
|
||||
|
||||
return $this->where($relation->getMorphType(), $model, null, $boolean);
|
||||
}
|
||||
|
||||
return $this->where(function ($query) use ($relation, $model) {
|
||||
$query->where($relation->getMorphType(), $model->getMorphClass())
|
||||
->where($relation->getForeignKeyName(), $model->getKey());
|
||||
}, null, null, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a morph-to relationship condition to the query with an "or where" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Relations\MorphTo|string $relation
|
||||
* @param \Illuminate\Database\Eloquent\Model|string $model
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereMorphedTo($relation, $model)
|
||||
{
|
||||
return $this->whereMorphedTo($relation, $model, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a "belongs to" relationship where clause to the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $related
|
||||
* @param string $relationship
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function whereBelongsTo($related, $relationshipName = null, $boolean = 'and')
|
||||
{
|
||||
if ($relationshipName === null) {
|
||||
$relationshipName = Str::camel(class_basename($related));
|
||||
}
|
||||
|
||||
try {
|
||||
$relationship = $this->model->{$relationshipName}();
|
||||
} catch (BadMethodCallException $exception) {
|
||||
throw RelationNotFoundException::make($this->model, $relationshipName);
|
||||
}
|
||||
|
||||
if (! $relationship instanceof BelongsTo) {
|
||||
throw RelationNotFoundException::make($this->model, $relationshipName, BelongsTo::class);
|
||||
}
|
||||
|
||||
$this->where(
|
||||
$relationship->getQualifiedForeignKeyName(),
|
||||
'=',
|
||||
$related->getAttributeValue($relationship->getOwnerKeyName()),
|
||||
$boolean,
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an "BelongsTo" relationship with an "or where" clause to the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $related
|
||||
* @param string $relationship
|
||||
* @return $this
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function orWhereBelongsTo($related, $relationshipName = null)
|
||||
{
|
||||
return $this->whereBelongsTo($related, $relationshipName, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to include an aggregate value for a relationship.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @param string $column
|
||||
* @param string $function
|
||||
* @return $this
|
||||
*/
|
||||
public function withCount($relations)
|
||||
public function withAggregate($relations, $column, $function = null)
|
||||
{
|
||||
if (empty($relations)) {
|
||||
return $this;
|
||||
@@ -363,12 +526,12 @@ trait QueriesRelationships
|
||||
$this->query->select([$this->query->from.'.*']);
|
||||
}
|
||||
|
||||
$relations = is_array($relations) ? $relations : func_get_args();
|
||||
$relations = is_array($relations) ? $relations : [$relations];
|
||||
|
||||
foreach ($this->parseWithRelations($relations) as $name => $constraints) {
|
||||
// First we will determine if the name has been aliased using an "as" clause on the name
|
||||
// and if it has we will extract the actual relationship name and the desired name of
|
||||
// the resulting column. This allows multiple counts on the same relationship name.
|
||||
// the resulting column. This allows multiple aggregates on the same relationships.
|
||||
$segments = explode(' ', $name);
|
||||
|
||||
unset($alias);
|
||||
@@ -379,38 +542,135 @@ trait QueriesRelationships
|
||||
|
||||
$relation = $this->getRelationWithoutConstraints($name);
|
||||
|
||||
// Here we will get the relationship count query and prepare to add it to the main query
|
||||
if ($function) {
|
||||
$hashedColumn = $this->getQuery()->from === $relation->getQuery()->getQuery()->from
|
||||
? "{$relation->getRelationCountHash(false)}.$column"
|
||||
: $column;
|
||||
|
||||
$wrappedColumn = $this->getQuery()->getGrammar()->wrap(
|
||||
$column === '*' ? $column : $relation->getRelated()->qualifyColumn($hashedColumn)
|
||||
);
|
||||
|
||||
$expression = $function === 'exists' ? $wrappedColumn : sprintf('%s(%s)', $function, $wrappedColumn);
|
||||
} else {
|
||||
$expression = $column;
|
||||
}
|
||||
|
||||
// Here, we will grab the relationship sub-query and prepare to add it to the main query
|
||||
// as a sub-select. First, we'll get the "has" query and use that to get the relation
|
||||
// count query. We will normalize the relation name then append _count as the name.
|
||||
$query = $relation->getRelationExistenceCountQuery(
|
||||
$relation->getRelated()->newQuery(), $this
|
||||
);
|
||||
// sub-query. We'll format this relationship name and append this column if needed.
|
||||
$query = $relation->getRelationExistenceQuery(
|
||||
$relation->getRelated()->newQuery(), $this, new Expression($expression)
|
||||
)->setBindings([], 'select');
|
||||
|
||||
$query->callScope($constraints);
|
||||
|
||||
$query = $query->mergeConstraintsFrom($relation->getQuery())->toBase();
|
||||
|
||||
// If the query contains certain elements like orderings / more than one column selected
|
||||
// then we will remove those elements from the query so that it will execute properly
|
||||
// when given to the database. Otherwise, we may receive SQL errors or poor syntax.
|
||||
$query->orders = null;
|
||||
|
||||
$query->setBindings([], 'order');
|
||||
|
||||
if (count($query->columns) > 1) {
|
||||
$query->columns = [$query->columns[0]];
|
||||
|
||||
$query->bindings['select'] = [];
|
||||
}
|
||||
|
||||
// Finally we will add the proper result column alias to the query and run the subselect
|
||||
// statement against the query builder. Then we will return the builder instance back
|
||||
// to the developer for further constraint chaining that needs to take place on it.
|
||||
$column = $alias ?? Str::snake($name.'_count');
|
||||
// Finally, we will make the proper column alias to the query and run this sub-select on
|
||||
// the query builder. Then, we will return the builder instance back to the developer
|
||||
// for further constraint chaining that needs to take place on the query as needed.
|
||||
$alias = $alias ?? Str::snake(
|
||||
preg_replace('/[^[:alnum:][:space:]_]/u', '', "$name $function $column")
|
||||
);
|
||||
|
||||
$this->selectSub($query, $column);
|
||||
if ($function === 'exists') {
|
||||
$this->selectRaw(
|
||||
sprintf('exists(%s) as %s', $query->toSql(), $this->getQuery()->grammar->wrap($alias)),
|
||||
$query->getBindings()
|
||||
)->withCasts([$alias => 'bool']);
|
||||
} else {
|
||||
$this->selectSub(
|
||||
$function ? $query : $query->limit(1),
|
||||
$alias
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to count the relations.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function withCount($relations)
|
||||
{
|
||||
return $this->withAggregate(is_array($relations) ? $relations : func_get_args(), '*', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to include the max of the relation's column.
|
||||
*
|
||||
* @param string|array $relation
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function withMax($relation, $column)
|
||||
{
|
||||
return $this->withAggregate($relation, $column, 'max');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to include the min of the relation's column.
|
||||
*
|
||||
* @param string|array $relation
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function withMin($relation, $column)
|
||||
{
|
||||
return $this->withAggregate($relation, $column, 'min');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to include the sum of the relation's column.
|
||||
*
|
||||
* @param string|array $relation
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function withSum($relation, $column)
|
||||
{
|
||||
return $this->withAggregate($relation, $column, 'sum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to include the average of the relation's column.
|
||||
*
|
||||
* @param string|array $relation
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function withAvg($relation, $column)
|
||||
{
|
||||
return $this->withAggregate($relation, $column, 'avg');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to include the existence of related models.
|
||||
*
|
||||
* @param string|array $relation
|
||||
* @return $this
|
||||
*/
|
||||
public function withExists($relation)
|
||||
{
|
||||
return $this->withAggregate($relation, '*', 'exists');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the "has" condition where clause to the query.
|
||||
*
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use ArrayAccess;
|
||||
use Faker\Generator as Faker;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class Factory implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The model definitions in the container.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definitions = [];
|
||||
|
||||
/**
|
||||
* The registered model states.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $states = [];
|
||||
|
||||
/**
|
||||
* The registered after making callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterMaking = [];
|
||||
|
||||
/**
|
||||
* The registered after creating callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterCreating = [];
|
||||
|
||||
/**
|
||||
* The Faker instance for the builder.
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
protected $faker;
|
||||
|
||||
/**
|
||||
* Create a new factory instance.
|
||||
*
|
||||
* @param \Faker\Generator $faker
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Faker $faker)
|
||||
{
|
||||
$this->faker = $faker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new factory container.
|
||||
*
|
||||
* @param \Faker\Generator $faker
|
||||
* @param string|null $pathToFactories
|
||||
* @return static
|
||||
*/
|
||||
public static function construct(Faker $faker, $pathToFactories = null)
|
||||
{
|
||||
$pathToFactories = $pathToFactories ?: database_path('factories');
|
||||
|
||||
return (new static($faker))->load($pathToFactories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a class with a given set of attributes.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function define($class, callable $attributes)
|
||||
{
|
||||
$this->definitions[$class] = $attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a state with a given set of attributes.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable|array $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function state($class, $state, $attributes)
|
||||
{
|
||||
$this->states[$class][$state] = $attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after making a model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $callback
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function afterMaking($class, callable $callback, $name = 'default')
|
||||
{
|
||||
$this->afterMaking[$class][$name][] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after making a model with given state.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function afterMakingState($class, $state, callable $callback)
|
||||
{
|
||||
return $this->afterMaking($class, $callback, $state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after creating a model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $callback
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function afterCreating($class, callable $callback, $name = 'default')
|
||||
{
|
||||
$this->afterCreating[$class][$name][] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a callback to run after creating a model with given state.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function afterCreatingState($class, $state, callable $callback)
|
||||
{
|
||||
return $this->afterCreating($class, $callback, $state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the given model and persist it to the database.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function create($class, array $attributes = [])
|
||||
{
|
||||
return $this->of($class)->create($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function make($class, array $attributes = [])
|
||||
{
|
||||
return $this->of($class)->make($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw attribute array for a given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
public function raw($class, array $attributes = [])
|
||||
{
|
||||
return array_merge(
|
||||
call_user_func($this->definitions[$class], $this->faker), $attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder for the given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @return \Illuminate\Database\Eloquent\FactoryBuilder
|
||||
*/
|
||||
public function of($class)
|
||||
{
|
||||
return new FactoryBuilder(
|
||||
$class, $this->definitions, $this->states,
|
||||
$this->afterMaking, $this->afterCreating, $this->faker
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load factories from path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function load($path)
|
||||
{
|
||||
$factory = $this;
|
||||
|
||||
if (is_dir($path)) {
|
||||
foreach (Finder::create()->files()->name('*.php')->in($path) as $file) {
|
||||
require $file->getRealPath();
|
||||
}
|
||||
}
|
||||
|
||||
return $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given offset exists.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->definitions[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->make($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given offset to the given value.
|
||||
*
|
||||
* @param string $offset
|
||||
* @param callable $value
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->define($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return void
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->definitions[$offset]);
|
||||
}
|
||||
}
|
||||
@@ -1,449 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class FactoryBuilder
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The model definitions in the container.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definitions;
|
||||
|
||||
/**
|
||||
* The model being built.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
/**
|
||||
* The database connection on which the model instance should be persisted.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The model states.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $states;
|
||||
|
||||
/**
|
||||
* The model after making callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterMaking = [];
|
||||
|
||||
/**
|
||||
* The model after creating callbacks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $afterCreating = [];
|
||||
|
||||
/**
|
||||
* The states to apply.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $activeStates = [];
|
||||
|
||||
/**
|
||||
* The Faker instance for the builder.
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
protected $faker;
|
||||
|
||||
/**
|
||||
* The number of models to build.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $amount = null;
|
||||
|
||||
/**
|
||||
* Create an new builder instance.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $definitions
|
||||
* @param array $states
|
||||
* @param array $afterMaking
|
||||
* @param array $afterCreating
|
||||
* @param \Faker\Generator $faker
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($class, array $definitions, array $states,
|
||||
array $afterMaking, array $afterCreating, Faker $faker)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->faker = $faker;
|
||||
$this->states = $states;
|
||||
$this->definitions = $definitions;
|
||||
$this->afterMaking = $afterMaking;
|
||||
$this->afterCreating = $afterCreating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of models you wish to create / make.
|
||||
*
|
||||
* @param int $amount
|
||||
* @return $this
|
||||
*/
|
||||
public function times($amount)
|
||||
{
|
||||
$this->amount = $amount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the state to be applied to the model.
|
||||
*
|
||||
* @param string $state
|
||||
* @return $this
|
||||
*/
|
||||
public function state($state)
|
||||
{
|
||||
return $this->states([$state]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the states to be applied to the model.
|
||||
*
|
||||
* @param array|mixed $states
|
||||
* @return $this
|
||||
*/
|
||||
public function states($states)
|
||||
{
|
||||
$this->activeStates = is_array($states) ? $states : func_get_args();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database connection on which the model instance should be persisted.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function connection($name)
|
||||
{
|
||||
$this->connection = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a model and persist it in the database if requested.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Closure
|
||||
*/
|
||||
public function lazy(array $attributes = [])
|
||||
{
|
||||
return function () use ($attributes) {
|
||||
return $this->create($attributes);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models and persist them to the database.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|mixed
|
||||
*/
|
||||
public function create(array $attributes = [])
|
||||
{
|
||||
$results = $this->make($attributes);
|
||||
|
||||
if ($results instanceof Model) {
|
||||
$this->store(collect([$results]));
|
||||
|
||||
$this->callAfterCreating(collect([$results]));
|
||||
} else {
|
||||
$this->store($results);
|
||||
|
||||
$this->callAfterCreating($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models and persist them to the database.
|
||||
*
|
||||
* @param iterable $records
|
||||
* @return \Illuminate\Database\Eloquent\Collection|mixed
|
||||
*/
|
||||
public function createMany(iterable $records)
|
||||
{
|
||||
return (new $this->class)->newCollection(array_map(function ($attribute) {
|
||||
return $this->create($attribute);
|
||||
}, $records));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection name on the results and store them.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $results
|
||||
* @return void
|
||||
*/
|
||||
protected function store($results)
|
||||
{
|
||||
$results->each(function ($model) {
|
||||
if (! isset($this->connection)) {
|
||||
$model->setConnection($model->newQueryWithoutScopes()->getConnection()->getName());
|
||||
}
|
||||
|
||||
$model->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Eloquent\Model|mixed
|
||||
*/
|
||||
public function make(array $attributes = [])
|
||||
{
|
||||
if ($this->amount === null) {
|
||||
return tap($this->makeInstance($attributes), function ($instance) {
|
||||
$this->callAfterMaking(collect([$instance]));
|
||||
});
|
||||
}
|
||||
|
||||
if ($this->amount < 1) {
|
||||
return (new $this->class)->newCollection();
|
||||
}
|
||||
|
||||
$instances = (new $this->class)->newCollection(array_map(function () use ($attributes) {
|
||||
return $this->makeInstance($attributes);
|
||||
}, range(1, $this->amount)));
|
||||
|
||||
$this->callAfterMaking($instances);
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of raw attribute arrays.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function raw(array $attributes = [])
|
||||
{
|
||||
if ($this->amount === null) {
|
||||
return $this->getRawAttributes($attributes);
|
||||
}
|
||||
|
||||
if ($this->amount < 1) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_map(function () use ($attributes) {
|
||||
return $this->getRawAttributes($attributes);
|
||||
}, range(1, $this->amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a raw attributes array for the model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function getRawAttributes(array $attributes = [])
|
||||
{
|
||||
if (! isset($this->definitions[$this->class])) {
|
||||
throw new InvalidArgumentException("Unable to locate factory for [{$this->class}].");
|
||||
}
|
||||
|
||||
$definition = call_user_func(
|
||||
$this->definitions[$this->class],
|
||||
$this->faker, $attributes
|
||||
);
|
||||
|
||||
return $this->expandAttributes(
|
||||
array_merge($this->applyStates($definition, $attributes), $attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an instance of the model with the given attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected function makeInstance(array $attributes = [])
|
||||
{
|
||||
return Model::unguarded(function () use ($attributes) {
|
||||
$instance = new $this->class(
|
||||
$this->getRawAttributes($attributes)
|
||||
);
|
||||
|
||||
if (isset($this->connection)) {
|
||||
$instance->setConnection($this->connection);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the active states to the model definition array.
|
||||
*
|
||||
* @param array $definition
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function applyStates(array $definition, array $attributes = [])
|
||||
{
|
||||
foreach ($this->activeStates as $state) {
|
||||
if (! isset($this->states[$this->class][$state])) {
|
||||
if ($this->stateHasAfterCallback($state)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unable to locate [{$state}] state for [{$this->class}].");
|
||||
}
|
||||
|
||||
$definition = array_merge(
|
||||
$definition,
|
||||
$this->stateAttributes($state, $attributes)
|
||||
);
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state attributes.
|
||||
*
|
||||
* @param string $state
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function stateAttributes($state, array $attributes)
|
||||
{
|
||||
$stateAttributes = $this->states[$this->class][$state];
|
||||
|
||||
if (! is_callable($stateAttributes)) {
|
||||
return $stateAttributes;
|
||||
}
|
||||
|
||||
return $stateAttributes($this->faker, $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand all attributes to their underlying values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function expandAttributes(array $attributes)
|
||||
{
|
||||
foreach ($attributes as &$attribute) {
|
||||
if (is_callable($attribute) && ! is_string($attribute) && ! is_array($attribute)) {
|
||||
$attribute = $attribute($attributes);
|
||||
}
|
||||
|
||||
if ($attribute instanceof static) {
|
||||
$attribute = $attribute->create()->getKey();
|
||||
}
|
||||
|
||||
if ($attribute instanceof Model) {
|
||||
$attribute = $attribute->getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run after making callbacks on a collection of models.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
public function callAfterMaking($models)
|
||||
{
|
||||
$this->callAfter($this->afterMaking, $models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run after creating callbacks on a collection of models.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
public function callAfterCreating($models)
|
||||
{
|
||||
$this->callAfter($this->afterCreating, $models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call after callbacks for each model and state.
|
||||
*
|
||||
* @param array $afterCallbacks
|
||||
* @param \Illuminate\Support\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
protected function callAfter(array $afterCallbacks, $models)
|
||||
{
|
||||
$states = array_merge(['default'], $this->activeStates);
|
||||
|
||||
$models->each(function ($model) use ($states, $afterCallbacks) {
|
||||
foreach ($states as $state) {
|
||||
$this->callAfterCallbacks($afterCallbacks, $model, $state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Call after callbacks for each model and state.
|
||||
*
|
||||
* @param array $afterCallbacks
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param string $state
|
||||
* @return void
|
||||
*/
|
||||
protected function callAfterCallbacks(array $afterCallbacks, $model, $state)
|
||||
{
|
||||
if (! isset($afterCallbacks[$this->class][$state])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($afterCallbacks[$this->class][$state] as $callback) {
|
||||
$callback($model, $this->faker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given state has an "after" callback.
|
||||
*
|
||||
* @param string $state
|
||||
* @return bool
|
||||
*/
|
||||
protected function stateHasAfterCallback($state)
|
||||
{
|
||||
return isset($this->afterMaking[$this->class][$state]) ||
|
||||
isset($this->afterCreating[$this->class][$state]);
|
||||
}
|
||||
}
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Eloquent/MassAssignmentException.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Eloquent/MassAssignmentException.php
vendored
Normal file → Executable file
@@ -3,13 +3,15 @@
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use ArrayAccess;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Broadcasting\HasBroadcastChannel;
|
||||
use Illuminate\Contracts\Queue\QueueableCollection;
|
||||
use Illuminate\Contracts\Queue\QueueableEntity;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\CanBeEscapedWhenCastToString;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\AsPivot;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
@@ -19,8 +21,9 @@ use Illuminate\Support\Collection as BaseCollection;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\ForwardsCalls;
|
||||
use JsonSerializable;
|
||||
use LogicException;
|
||||
|
||||
abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
|
||||
abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToString, HasBroadcastChannel, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
|
||||
{
|
||||
use Concerns\HasAttributes,
|
||||
Concerns\HasEvents,
|
||||
@@ -80,6 +83,13 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
protected $withCount = [];
|
||||
|
||||
/**
|
||||
* Indicates whether lazy loading will be prevented on this model.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $preventsLazyLoading = false;
|
||||
|
||||
/**
|
||||
* The number of models to return for pagination.
|
||||
*
|
||||
@@ -101,6 +111,13 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public $wasRecentlyCreated = false;
|
||||
|
||||
/**
|
||||
* Indicates that the object's string representation should be escaped when __toString is invoked.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $escapeWhenCastingToString = false;
|
||||
|
||||
/**
|
||||
* The connection resolver instance.
|
||||
*
|
||||
@@ -143,6 +160,27 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
protected static $ignoreOnTouch = [];
|
||||
|
||||
/**
|
||||
* Indicates whether lazy loading should be restricted on all models.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $modelsShouldPreventLazyLoading = false;
|
||||
|
||||
/**
|
||||
* The callback that is responsible for handling lazy loading violations.
|
||||
*
|
||||
* @var callable|null
|
||||
*/
|
||||
protected static $lazyLoadingViolationCallback;
|
||||
|
||||
/**
|
||||
* Indicates if broadcasting is currently enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $isBroadcasting = true;
|
||||
|
||||
/**
|
||||
* The name of the "created at" column.
|
||||
*
|
||||
@@ -332,6 +370,47 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent model relationships from being lazy loaded.
|
||||
*
|
||||
* @param bool $value
|
||||
* @return void
|
||||
*/
|
||||
public static function preventLazyLoading($value = true)
|
||||
{
|
||||
static::$modelsShouldPreventLazyLoading = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback that is responsible for handling lazy loading violations.
|
||||
*
|
||||
* @param callable|null $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function handleLazyLoadingViolationUsing(?callable $callback)
|
||||
{
|
||||
static::$lazyLoadingViolationCallback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback without broadcasting any model events for all model types.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function withoutBroadcasting(callable $callback)
|
||||
{
|
||||
$isBroadcasting = static::$isBroadcasting;
|
||||
|
||||
static::$isBroadcasting = false;
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
static::$isBroadcasting = $isBroadcasting;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the model with an array of attributes.
|
||||
*
|
||||
@@ -345,8 +424,6 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
$totallyGuarded = $this->totallyGuarded();
|
||||
|
||||
foreach ($this->fillableFromArray($attributes) as $key => $value) {
|
||||
$key = $this->removeTableFromKey($key);
|
||||
|
||||
// The developers may choose to place some attributes in the "fillable" array
|
||||
// which means only those attributes may be set through mass assignment to
|
||||
// the model, and all others will just get ignored for security reasons.
|
||||
@@ -392,16 +469,16 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the table name from a given key.
|
||||
* Qualify the given columns with the model's table.
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*
|
||||
* @deprecated This method is deprecated and will be removed in a future Laravel version.
|
||||
* @param array $columns
|
||||
* @return array
|
||||
*/
|
||||
protected function removeTableFromKey($key)
|
||||
public function qualifyColumns($columns)
|
||||
{
|
||||
return $key;
|
||||
return collect($columns)->map(function ($column) {
|
||||
return $this->qualifyColumn($column);
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,6 +608,10 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public function loadMorph($relation, $relations)
|
||||
{
|
||||
if (! $this->{$relation}) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$className = get_class($this->{$relation});
|
||||
|
||||
$this->{$relation}->load($relations[$className] ?? []);
|
||||
@@ -553,6 +634,21 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relation's column aggregations on the model.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @param string $function
|
||||
* @return $this
|
||||
*/
|
||||
public function loadAggregate($relations, $column, $function = null)
|
||||
{
|
||||
$this->newCollection([$this])->loadAggregate($relations, $column, $function);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relation counts on the model.
|
||||
*
|
||||
@@ -563,7 +659,86 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
{
|
||||
$relations = is_string($relations) ? func_get_args() : $relations;
|
||||
|
||||
$this->newCollection([$this])->loadCount($relations);
|
||||
return $this->loadAggregate($relations, '*', 'count');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relation max column values on the model.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMax($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'max');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relation min column values on the model.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMin($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'min');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relation's column summations on the model.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadSum($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'sum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relation average column values on the model.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadAvg($relations, $column)
|
||||
{
|
||||
return $this->loadAggregate($relations, $column, 'avg');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load related model existence values on the model.
|
||||
*
|
||||
* @param array|string $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function loadExists($relations)
|
||||
{
|
||||
return $this->loadAggregate($relations, '*', 'exists');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relationship column aggregation on the polymorphic relation of a model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @param string $column
|
||||
* @param string $function
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorphAggregate($relation, $relations, $column, $function = null)
|
||||
{
|
||||
if (! $this->{$relation}) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$className = get_class($this->{$relation});
|
||||
|
||||
$this->{$relation}->loadAggregate($relations[$className] ?? [], $column, $function);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -577,11 +752,59 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public function loadMorphCount($relation, $relations)
|
||||
{
|
||||
$className = get_class($this->{$relation});
|
||||
return $this->loadMorphAggregate($relation, $relations, '*', 'count');
|
||||
}
|
||||
|
||||
$this->{$relation}->loadCount($relations[$className] ?? []);
|
||||
/**
|
||||
* Eager load relationship max column values on the polymorphic relation of a model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorphMax($relation, $relations, $column)
|
||||
{
|
||||
return $this->loadMorphAggregate($relation, $relations, $column, 'max');
|
||||
}
|
||||
|
||||
return $this;
|
||||
/**
|
||||
* Eager load relationship min column values on the polymorphic relation of a model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorphMin($relation, $relations, $column)
|
||||
{
|
||||
return $this->loadMorphAggregate($relation, $relations, $column, 'min');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relationship column summations on the polymorphic relation of a model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorphSum($relation, $relations, $column)
|
||||
{
|
||||
return $this->loadMorphAggregate($relation, $relations, $column, 'sum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Eager load relationship average column values on the polymorphic relation of a model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param array $relations
|
||||
* @param string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function loadMorphAvg($relation, $relations, $column)
|
||||
{
|
||||
return $this->loadMorphAggregate($relation, $relations, $column, 'avg');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,29 +850,23 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return $query->{$method}($column, $amount, $extra);
|
||||
}
|
||||
|
||||
$this->incrementOrDecrementAttributeValue($column, $amount, $extra, $method);
|
||||
|
||||
return $query->where(
|
||||
$this->getKeyName(), $this->getKey()
|
||||
)->{$method}($column, $amount, $extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the underlying attribute value and sync with original.
|
||||
*
|
||||
* @param string $column
|
||||
* @param float|int $amount
|
||||
* @param array $extra
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
protected function incrementOrDecrementAttributeValue($column, $amount, $extra, $method)
|
||||
{
|
||||
$this->{$column} = $this->{$column} + ($method === 'increment' ? $amount : $amount * -1);
|
||||
$this->{$column} = $this->isClassDeviable($column)
|
||||
? $this->deviateClassCastableAttribute($method, $column, $amount)
|
||||
: $this->{$column} + ($method === 'increment' ? $amount : $amount * -1);
|
||||
|
||||
$this->forceFill($extra);
|
||||
|
||||
$this->syncOriginalAttribute($column);
|
||||
if ($this->fireModelEvent('updating') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return tap($this->setKeysForSaveQuery($query)->{$method}($column, $amount, $extra), function () use ($column) {
|
||||
$this->syncChanges();
|
||||
|
||||
$this->fireModelEvent('updated', false);
|
||||
|
||||
$this->syncOriginalAttribute($column);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -668,6 +885,40 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return $this->fill($attributes)->save($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the model in the database within a transaction.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function updateOrFail(array $attributes = [], array $options = [])
|
||||
{
|
||||
if (! $this->exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->fill($attributes)->saveOrFail($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the model in the database without raising any events.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*/
|
||||
public function updateQuietly(array $attributes = [], array $options = [])
|
||||
{
|
||||
if (! $this->exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->fill($attributes)->saveQuietly($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model and all of its relationships.
|
||||
*
|
||||
@@ -696,6 +947,19 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model to the database without raising any events.
|
||||
*
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*/
|
||||
public function saveQuietly(array $options = [])
|
||||
{
|
||||
return static::withoutEvents(function () use ($options) {
|
||||
return $this->save($options);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model to the database.
|
||||
*
|
||||
@@ -704,7 +968,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public function save(array $options = [])
|
||||
{
|
||||
$this->mergeAttributesFromClassCasts();
|
||||
$this->mergeAttributesFromCachedCasts();
|
||||
|
||||
$query = $this->newModelQuery();
|
||||
|
||||
@@ -746,7 +1010,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the model to the database using transaction.
|
||||
* Save the model to the database within a transaction.
|
||||
*
|
||||
* @param array $options
|
||||
* @return bool
|
||||
@@ -815,13 +1079,36 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a select query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSelectQuery($query)
|
||||
{
|
||||
$query->where($this->getKeyName(), '=', $this->getKeyForSelectQuery());
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the primary key value for a select query.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getKeyForSelectQuery()
|
||||
{
|
||||
return $this->original[$this->getKeyName()] ?? $this->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
protected function setKeysForSaveQuery($query)
|
||||
{
|
||||
$query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery());
|
||||
|
||||
@@ -835,8 +1122,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
protected function getKeyForSaveQuery()
|
||||
{
|
||||
return $this->original[$this->getKeyName()]
|
||||
?? $this->getKey();
|
||||
return $this->original[$this->getKeyName()] ?? $this->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -861,7 +1147,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
// If the model has an incrementing key, we can use the "insertGetId" method on
|
||||
// the query builder, which will give us back the final inserted ID for this
|
||||
// table from the database. Not all tables have to be incrementing though.
|
||||
$attributes = $this->getAttributes();
|
||||
$attributes = $this->getAttributesForInsert();
|
||||
|
||||
if ($this->getIncrementing()) {
|
||||
$this->insertAndSetId($query, $attributes);
|
||||
@@ -912,10 +1198,9 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public static function destroy($ids)
|
||||
{
|
||||
// We'll initialize a count here so we will return the total number of deletes
|
||||
// for the operation. The developers can then check this number as a boolean
|
||||
// type value or get this total count of records deleted for logging, etc.
|
||||
$count = 0;
|
||||
if ($ids instanceof EloquentCollection) {
|
||||
$ids = $ids->modelKeys();
|
||||
}
|
||||
|
||||
if ($ids instanceof BaseCollection) {
|
||||
$ids = $ids->all();
|
||||
@@ -923,11 +1208,17 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
|
||||
$ids = is_array($ids) ? $ids : func_get_args();
|
||||
|
||||
if (count($ids) === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We will actually pull the models from the database table and call delete on
|
||||
// each of them individually so that their events get fired properly with a
|
||||
// correct set of attributes in case the developers wants to check these.
|
||||
$key = ($instance = new static)->getKeyName();
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($instance->whereIn($key, $ids)->get() as $model) {
|
||||
if ($model->delete()) {
|
||||
$count++;
|
||||
@@ -942,14 +1233,14 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*
|
||||
* @return bool|null
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->mergeAttributesFromClassCasts();
|
||||
$this->mergeAttributesFromCachedCasts();
|
||||
|
||||
if (is_null($this->getKeyName())) {
|
||||
throw new Exception('No primary key defined on model.');
|
||||
throw new LogicException('No primary key defined on model.');
|
||||
}
|
||||
|
||||
// If the model doesn't exist, there is nothing to delete so we'll just return
|
||||
@@ -978,10 +1269,28 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the model from the database within a transaction.
|
||||
*
|
||||
* @return bool|null
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function deleteOrFail()
|
||||
{
|
||||
if (! $this->exists) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getConnection()->transaction(function () {
|
||||
return $this->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a hard delete on a soft deleted model.
|
||||
*
|
||||
* This method protects developers from running forceDelete when trait is missing.
|
||||
* This method protects developers from running forceDelete when the trait is missing.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
@@ -1200,6 +1509,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->toArray();
|
||||
@@ -1217,9 +1527,8 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return;
|
||||
}
|
||||
|
||||
return static::newQueryWithoutScopes()
|
||||
return $this->setKeysForSelectQuery($this->newQueryWithoutScopes())
|
||||
->with(is_string($with) ? func_get_args() : $with)
|
||||
->where($this->getKeyName(), $this->getKey())
|
||||
->first();
|
||||
}
|
||||
|
||||
@@ -1235,7 +1544,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
}
|
||||
|
||||
$this->setRawAttributes(
|
||||
static::newQueryWithoutScopes()->findOrFail($this->getKey())->attributes
|
||||
$this->setKeysForSelectQuery($this->newQueryWithoutScopes())->firstOrFail()->attributes
|
||||
);
|
||||
|
||||
$this->load(collect($this->relations)->reject(function ($relation) {
|
||||
@@ -1568,7 +1877,19 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public function resolveRouteBinding($value, $field = null)
|
||||
{
|
||||
return $this->where($field ?? $this->getRouteKeyName(), $value)->first();
|
||||
return $this->resolveRouteBindingQuery($this, $value, $field)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the model for a bound value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string|null $field
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public function resolveSoftDeletableRouteBinding($value, $field = null)
|
||||
{
|
||||
return $this->resolveRouteBindingQuery($this, $value, $field)->withTrashed()->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1580,6 +1901,32 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public function resolveChildRouteBinding($childType, $value, $field)
|
||||
{
|
||||
return $this->resolveChildRouteBindingQuery($childType, $value, $field)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the child model for a bound value.
|
||||
*
|
||||
* @param string $childType
|
||||
* @param mixed $value
|
||||
* @param string|null $field
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
public function resolveSoftDeletableChildRouteBinding($childType, $value, $field)
|
||||
{
|
||||
return $this->resolveChildRouteBindingQuery($childType, $value, $field)->withTrashed()->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the child model query for a bound value.
|
||||
*
|
||||
* @param string $childType
|
||||
* @param mixed $value
|
||||
* @param string|null $field
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
protected function resolveChildRouteBindingQuery($childType, $value, $field)
|
||||
{
|
||||
$relationship = $this->{Str::plural(Str::camel($childType))}();
|
||||
|
||||
@@ -1587,10 +1934,25 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
|
||||
if ($relationship instanceof HasManyThrough ||
|
||||
$relationship instanceof BelongsToMany) {
|
||||
return $relationship->where($relationship->getRelated()->getTable().'.'.$field, $value)->first();
|
||||
} else {
|
||||
return $relationship->where($field, $value)->first();
|
||||
$field = $relationship->getRelated()->getTable().'.'.$field;
|
||||
}
|
||||
|
||||
return $relationship instanceof Model
|
||||
? $relationship->resolveRouteBindingQuery($relationship, $value, $field)
|
||||
: $relationship->getRelated()->resolveRouteBindingQuery($relationship, $value, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the model for a bound value.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model|Illuminate\Database\Eloquent\Relations\Relation $query
|
||||
* @param mixed $value
|
||||
* @param string|null $field
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function resolveRouteBindingQuery($query, $value, $field = null)
|
||||
{
|
||||
return $query->where($field ?? $this->getRouteKeyName(), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1626,6 +1988,36 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if lazy loading is disabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function preventsLazyLoading()
|
||||
{
|
||||
return static::$modelsShouldPreventLazyLoading;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the broadcast channel route definition that is associated with the given entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function broadcastChannelRoute()
|
||||
{
|
||||
return str_replace('\\', '.', get_class($this)).'.{'.Str::camel(class_basename($this)).'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the broadcast channel name that is associated with the given entity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function broadcastChannel()
|
||||
{
|
||||
return str_replace('\\', '.', get_class($this)).'.'.$this->getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically retrieve attributes on the model.
|
||||
*
|
||||
@@ -1655,6 +2047,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return ! is_null($this->getAttribute($offset));
|
||||
@@ -1666,6 +2059,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
* @param mixed $offset
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->getAttribute($offset);
|
||||
@@ -1678,6 +2072,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
$this->setAttribute($offset, $value);
|
||||
@@ -1689,6 +2084,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
* @param mixed $offset
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->attributes[$offset], $this->relations[$offset]);
|
||||
@@ -1755,7 +2151,22 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toJson();
|
||||
return $this->escapeWhenCastingToString
|
||||
? e($this->toJson())
|
||||
: $this->toJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the object's string representation should be escaped when __toString is invoked.
|
||||
*
|
||||
* @param bool $escape
|
||||
* @return $this
|
||||
*/
|
||||
public function escapeWhenCastingToString($escape = true)
|
||||
{
|
||||
$this->escapeWhenCastingToString = $escape;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1765,9 +2176,10 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
$this->mergeAttributesFromClassCasts();
|
||||
$this->mergeAttributesFromCachedCasts();
|
||||
|
||||
$this->classCastCache = [];
|
||||
$this->attributeCastCache = [];
|
||||
|
||||
return array_keys(get_object_vars($this));
|
||||
}
|
||||
@@ -1780,5 +2192,7 @@ abstract class Model implements Arrayable, ArrayAccess, Jsonable, JsonSerializab
|
||||
public function __wakeup()
|
||||
{
|
||||
$this->bootIfNotBooted();
|
||||
|
||||
$this->initializeTraits();
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/laravel/framework/src/Illuminate/Database/Eloquent/ModelNotFoundException.php
vendored
Normal file → Executable file
4
vendor/laravel/framework/src/Illuminate/Database/Eloquent/ModelNotFoundException.php
vendored
Normal file → Executable file
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Illuminate\Database\RecordsNotFoundException;
|
||||
use Illuminate\Support\Arr;
|
||||
use RuntimeException;
|
||||
|
||||
class ModelNotFoundException extends RuntimeException
|
||||
class ModelNotFoundException extends RecordsNotFoundException
|
||||
{
|
||||
/**
|
||||
* Name of the affected Eloquent model.
|
||||
|
||||
9
vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php
vendored
Normal file → Executable file
9
vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php
vendored
Normal file → Executable file
@@ -25,13 +25,18 @@ class RelationNotFoundException extends RuntimeException
|
||||
*
|
||||
* @param object $model
|
||||
* @param string $relation
|
||||
* @param string|null $type
|
||||
* @return static
|
||||
*/
|
||||
public static function make($model, $relation)
|
||||
public static function make($model, $relation, $type = null)
|
||||
{
|
||||
$class = get_class($model);
|
||||
|
||||
$instance = new static("Call to undefined relationship [{$relation}] on model [{$class}].");
|
||||
$instance = new static(
|
||||
is_null($type)
|
||||
? "Call to undefined relationship [{$relation}] on model [{$class}]."
|
||||
: "Call to undefined relationship [{$relation}] on model [{$class}] of type [{$type}].",
|
||||
);
|
||||
|
||||
$instance->model = $class;
|
||||
$instance->relation = $relation;
|
||||
|
||||
66
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php
vendored
Normal file → Executable file
66
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php
vendored
Normal file → Executable file
@@ -5,11 +5,15 @@ namespace Illuminate\Database\Eloquent\Relations;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\ComparesRelatedModels;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class BelongsTo extends Relation
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
use ComparesRelatedModels,
|
||||
InteractsWithDictionary,
|
||||
SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* The child model instance of the relation.
|
||||
@@ -39,13 +43,6 @@ class BelongsTo extends Relation
|
||||
*/
|
||||
protected $relationName;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new belongs to relationship instance.
|
||||
*
|
||||
@@ -179,15 +176,19 @@ class BelongsTo extends Relation
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->getAttribute($owner)] = $result;
|
||||
$attribute = $this->getDictionaryKey($result->getAttribute($owner));
|
||||
|
||||
$dictionary[$attribute] = $result;
|
||||
}
|
||||
|
||||
// Once we have the dictionary constructed, we can loop through all the parents
|
||||
// and match back onto their children using these keys of the dictionary and
|
||||
// the primary key of the children to map them onto the correct instances.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$model->{$foreign}])) {
|
||||
$model->setRelation($relation, $dictionary[$model->{$foreign}]);
|
||||
$attribute = $this->getDictionaryKey($model->{$foreign});
|
||||
|
||||
if (isset($dictionary[$attribute])) {
|
||||
$model->setRelation($relation, $dictionary[$attribute]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +198,7 @@ class BelongsTo extends Relation
|
||||
/**
|
||||
* Associate the model instance to the given parent.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model|int|string $model
|
||||
* @param \Illuminate\Database\Eloquent\Model|int|string|null $model
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function associate($model)
|
||||
@@ -227,6 +228,16 @@ class BelongsTo extends Relation
|
||||
return $this->child->setRelation($this->relationName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of "dissociate" method.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function disassociate()
|
||||
{
|
||||
return $this->dissociate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query.
|
||||
*
|
||||
@@ -267,16 +278,6 @@ class BelongsTo extends Relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the related model has an auto-incrementing ID.
|
||||
*
|
||||
@@ -329,6 +330,16 @@ class BelongsTo extends Relation
|
||||
return $this->child->qualifyColumn($this->foreignKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key value of the child's foreign key.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParentKey()
|
||||
{
|
||||
return $this->child->{$this->foreignKey};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated key of the relationship.
|
||||
*
|
||||
@@ -349,6 +360,17 @@ class BelongsTo extends Relation
|
||||
return $this->related->qualifyColumn($this->ownerKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the model's associated key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRelatedKeyFrom(Model $model)
|
||||
{
|
||||
return $model->{$this->ownerKey};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the relationship.
|
||||
*
|
||||
|
||||
199
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
vendored
Normal file → Executable file
199
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
vendored
Normal file → Executable file
@@ -2,17 +2,21 @@
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\AsPivot;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithPivotTable;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class BelongsToMany extends Relation
|
||||
{
|
||||
use Concerns\InteractsWithPivotTable;
|
||||
use InteractsWithDictionary, InteractsWithPivotTable;
|
||||
|
||||
/**
|
||||
* The intermediate table for the relation.
|
||||
@@ -126,13 +130,6 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
protected $accessor = 'pivot';
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new belongs to many relationship instance.
|
||||
*
|
||||
@@ -177,7 +174,7 @@ class BelongsToMany extends Relation
|
||||
return $table;
|
||||
}
|
||||
|
||||
if ($model instanceof Pivot) {
|
||||
if (in_array(AsPivot::class, class_uses_recursive($model))) {
|
||||
$this->using($table);
|
||||
}
|
||||
|
||||
@@ -211,11 +208,12 @@ class BelongsToMany extends Relation
|
||||
// We need to join to the intermediate table on the related model's primary
|
||||
// key column with the intermediate table's foreign key for the related
|
||||
// model instance. Then we can set the "where" for the parent models.
|
||||
$baseTable = $this->related->getTable();
|
||||
|
||||
$key = $baseTable.'.'.$this->relatedKey;
|
||||
|
||||
$query->join($this->table, $key, '=', $this->getQualifiedRelatedPivotKeyName());
|
||||
$query->join(
|
||||
$this->table,
|
||||
$this->getQualifiedRelatedKeyName(),
|
||||
'=',
|
||||
$this->getQualifiedRelatedPivotKeyName()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -280,9 +278,11 @@ class BelongsToMany extends Relation
|
||||
|
||||
// Once we have an array dictionary of child objects we can easily match the
|
||||
// children back to their parent using the dictionary and the keys on the
|
||||
// the parent models. Then we will return the hydrated models back out.
|
||||
// parent models. Then we should return these hydrated models back out.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->{$this->parentKey}])) {
|
||||
$key = $this->getDictionaryKey($model->{$this->parentKey});
|
||||
|
||||
if (isset($dictionary[$key])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->related->newCollection($dictionary[$key])
|
||||
);
|
||||
@@ -306,7 +306,9 @@ class BelongsToMany extends Relation
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->{$this->accessor}->{$this->foreignPivotKey}][] = $result;
|
||||
$value = $this->getDictionaryKey($result->{$this->accessor}->{$this->foreignPivotKey});
|
||||
|
||||
$dictionary[$value][] = $result;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
@@ -361,7 +363,7 @@ class BelongsToMany extends Relation
|
||||
{
|
||||
$this->pivotWheres[] = func_get_args();
|
||||
|
||||
return $this->where($this->table.'.'.$column, $operator, $value, $boolean);
|
||||
return $this->where($this->qualifyPivotColumn($column), $operator, $value, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,7 +377,7 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function wherePivotBetween($column, array $values, $boolean = 'and', $not = false)
|
||||
{
|
||||
return $this->whereBetween($this->table.'.'.$column, $values, $boolean, $not);
|
||||
return $this->whereBetween($this->qualifyPivotColumn($column), $values, $boolean, $not);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,7 +430,7 @@ class BelongsToMany extends Relation
|
||||
{
|
||||
$this->pivotWhereIns[] = func_get_args();
|
||||
|
||||
return $this->whereIn($this->table.'.'.$column, $values, $boolean, $not);
|
||||
return $this->whereIn($this->qualifyPivotColumn($column), $values, $boolean, $not);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,7 +525,7 @@ class BelongsToMany extends Relation
|
||||
{
|
||||
$this->pivotWhereNulls[] = func_get_args();
|
||||
|
||||
return $this->whereNull($this->table.'.'.$column, $boolean, $not);
|
||||
return $this->whereNull($this->qualifyPivotColumn($column), $boolean, $not);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,7 +564,19 @@ class BelongsToMany extends Relation
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or return new instance of the related model.
|
||||
* Add an "order by" clause for a pivot table column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $direction
|
||||
* @return $this
|
||||
*/
|
||||
public function orderByPivot($column, $direction = 'asc')
|
||||
{
|
||||
return $this->orderBy($this->qualifyPivotColumn($column), $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or return a new instance of the related model.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
@@ -739,6 +753,28 @@ class BelongsToMany extends Relation
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result or call a callback.
|
||||
*
|
||||
* @param \Closure|array $columns
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Model|static|mixed
|
||||
*/
|
||||
public function firstOr($columns = ['*'], Closure $callback = null)
|
||||
{
|
||||
if ($columns instanceof Closure) {
|
||||
$callback = $columns;
|
||||
|
||||
$columns = ['*'];
|
||||
}
|
||||
|
||||
if (! is_null($model = $this->first($columns))) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
return $callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
@@ -760,7 +796,7 @@ class BelongsToMany extends Relation
|
||||
public function get($columns = ['*'])
|
||||
{
|
||||
// First we'll add the proper select columns onto the query so it is run with
|
||||
// the proper columns. Then, we will get the results and hydrate out pivot
|
||||
// the proper columns. Then, we will get the results and hydrate our pivot
|
||||
// models with the result of those columns as a separate model relation.
|
||||
$builder = $this->query->applyScopes();
|
||||
|
||||
@@ -809,7 +845,7 @@ class BelongsToMany extends Relation
|
||||
$defaults = [$this->foreignPivotKey, $this->relatedPivotKey];
|
||||
|
||||
return collect(array_merge($defaults, $this->pivotColumns))->map(function ($column) {
|
||||
return $this->table.'.'.$column.' as pivot_'.$column;
|
||||
return $this->qualifyPivotColumn($column).' as pivot_'.$column;
|
||||
})->unique()->all();
|
||||
}
|
||||
|
||||
@@ -849,6 +885,24 @@ class BelongsToMany extends Relation
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the given query into a cursor paginator.
|
||||
*
|
||||
* @param int|null $perPage
|
||||
* @param array $columns
|
||||
* @param string $cursorName
|
||||
* @param string|null $cursor
|
||||
* @return \Illuminate\Contracts\Pagination\CursorPaginator
|
||||
*/
|
||||
public function cursorPaginate($perPage = null, $columns = ['*'], $cursorName = 'cursor', $cursor = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return tap($this->query->cursorPaginate($perPage, $columns, $cursorName, $cursor), function ($paginator) {
|
||||
$this->hydratePivotRelation($paginator->items());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the results of the query.
|
||||
*
|
||||
@@ -858,12 +912,10 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function chunk($count, callable $callback)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect());
|
||||
|
||||
return $this->query->chunk($count, function ($results) use ($callback) {
|
||||
return $this->prepareQueryBuilder()->chunk($count, function ($results, $page) use ($callback) {
|
||||
$this->hydratePivotRelation($results->all());
|
||||
|
||||
return $callback($results);
|
||||
return $callback($results, $page);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -878,7 +930,7 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function chunkById($count, callable $callback, $column = null, $alias = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect());
|
||||
$this->prepareQueryBuilder();
|
||||
|
||||
$column = $column ?? $this->getRelated()->qualifyColumn(
|
||||
$this->getRelatedKeyName()
|
||||
@@ -911,6 +963,44 @@ class BelongsToMany extends Relation
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunks of the given size.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*/
|
||||
public function lazy($chunkSize = 1000)
|
||||
{
|
||||
return $this->prepareQueryBuilder()->lazy($chunkSize)->map(function ($model) {
|
||||
$this->hydratePivotRelation([$model]);
|
||||
|
||||
return $model;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunking the results of a query by comparing IDs.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*/
|
||||
public function lazyById($chunkSize = 1000, $column = null, $alias = null)
|
||||
{
|
||||
$column = $column ?? $this->getRelated()->qualifyColumn(
|
||||
$this->getRelatedKeyName()
|
||||
);
|
||||
|
||||
$alias = $alias ?? $this->getRelatedKeyName();
|
||||
|
||||
return $this->prepareQueryBuilder()->lazyById($chunkSize, $column, $alias)->map(function ($model) {
|
||||
$this->hydratePivotRelation([$model]);
|
||||
|
||||
return $model;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lazy collection for the given query.
|
||||
*
|
||||
@@ -918,15 +1008,23 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function cursor()
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect());
|
||||
|
||||
return $this->query->cursor()->map(function ($model) {
|
||||
return $this->prepareQueryBuilder()->cursor()->map(function ($model) {
|
||||
$this->hydratePivotRelation([$model]);
|
||||
|
||||
return $model;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the query builder for query execution.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function prepareQueryBuilder()
|
||||
{
|
||||
return $this->query->addSelect($this->shouldSelect());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate the pivot table relationship on the models.
|
||||
*
|
||||
@@ -1165,16 +1263,6 @@ class BelongsToMany extends Relation
|
||||
return $this->getQualifiedForeignPivotKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the pivot table has creation and update timestamps.
|
||||
*
|
||||
@@ -1229,7 +1317,7 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function getQualifiedForeignPivotKeyName()
|
||||
{
|
||||
return $this->table.'.'.$this->foreignPivotKey;
|
||||
return $this->qualifyPivotColumn($this->foreignPivotKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1249,7 +1337,7 @@ class BelongsToMany extends Relation
|
||||
*/
|
||||
public function getQualifiedRelatedPivotKeyName()
|
||||
{
|
||||
return $this->table.'.'.$this->relatedPivotKey;
|
||||
return $this->qualifyPivotColumn($this->relatedPivotKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1282,6 +1370,16 @@ class BelongsToMany extends Relation
|
||||
return $this->relatedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified related key name for the relation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedRelatedKeyName()
|
||||
{
|
||||
return $this->related->qualifyColumn($this->relatedKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the intermediate table for the relationship.
|
||||
*
|
||||
@@ -1321,4 +1419,17 @@ class BelongsToMany extends Relation
|
||||
{
|
||||
return $this->pivotColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Qualify the given column name by the pivot table.
|
||||
*
|
||||
* @param string $column
|
||||
* @return string
|
||||
*/
|
||||
public function qualifyPivotColumn($column)
|
||||
{
|
||||
return Str::contains($column, '.')
|
||||
? $column
|
||||
: $this->table.'.'.$column;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,15 +83,15 @@ trait AsPivot
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
* Set the keys for a select query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
protected function setKeysForSelectQuery($query)
|
||||
{
|
||||
if (isset($this->attributes[$this->getKeyName()])) {
|
||||
return parent::setKeysForSaveQuery($query);
|
||||
return parent::setKeysForSelectQuery($query);
|
||||
}
|
||||
|
||||
$query->where($this->foreignKey, $this->getOriginal(
|
||||
@@ -103,6 +103,17 @@ trait AsPivot
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery($query)
|
||||
{
|
||||
return $this->setKeysForSelectQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot model record from the database.
|
||||
*
|
||||
|
||||
@@ -116,13 +116,29 @@ trait InteractsWithPivotTable
|
||||
// have done any attaching or detaching, and if we have we will touch these
|
||||
// relationships if they are configured to touch on any database updates.
|
||||
if (count($changes['attached']) ||
|
||||
count($changes['updated'])) {
|
||||
count($changes['updated']) ||
|
||||
count($changes['detached'])) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the intermediate tables with a list of IDs or collection of models with the given pivot values.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model|array $ids
|
||||
* @param array $values
|
||||
* @param bool $detaching
|
||||
* @return array
|
||||
*/
|
||||
public function syncWithPivotValues($ids, array $values, bool $detaching = true)
|
||||
{
|
||||
return $this->sync(collect($this->parseIds($ids))->mapWithKeys(function ($id) use ($values) {
|
||||
return [$id => $values];
|
||||
}), $detaching);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the sync / toggle record list so that it is keyed by ID.
|
||||
*
|
||||
@@ -431,7 +447,7 @@ trait InteractsWithPivotTable
|
||||
return 0;
|
||||
}
|
||||
|
||||
$query->whereIn($this->relatedPivotKey, (array) $ids);
|
||||
$query->whereIn($this->getQualifiedRelatedPivotKeyName(), (array) $ids);
|
||||
}
|
||||
|
||||
// Once we have all of the conditions set on the statement, we are ready
|
||||
@@ -475,7 +491,7 @@ trait InteractsWithPivotTable
|
||||
protected function getCurrentlyAttachedPivots()
|
||||
{
|
||||
return $this->newPivotQuery()->get()->map(function ($record) {
|
||||
$class = $this->using ? $this->using : Pivot::class;
|
||||
$class = $this->using ?: Pivot::class;
|
||||
|
||||
$pivot = $class::fromRawAttributes($this->parent, (array) $record, $this->getTable(), true);
|
||||
|
||||
@@ -552,7 +568,7 @@ trait InteractsWithPivotTable
|
||||
$query->whereNull(...$arguments);
|
||||
}
|
||||
|
||||
return $query->where($this->foreignPivotKey, $this->parent->{$this->parentKey});
|
||||
return $query->where($this->getQualifiedForeignPivotKeyName(), $this->parent->{$this->parentKey});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasMany.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasMany.php
vendored
Normal file → Executable file
@@ -7,10 +7,13 @@ use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class HasManyThrough extends Relation
|
||||
{
|
||||
use InteractsWithDictionary;
|
||||
|
||||
/**
|
||||
* The "through" parent model instance.
|
||||
*
|
||||
@@ -53,13 +56,6 @@ class HasManyThrough extends Relation
|
||||
*/
|
||||
protected $secondLocalKey;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new has many through relationship instance.
|
||||
*
|
||||
@@ -200,7 +196,7 @@ class HasManyThrough extends Relation
|
||||
// link them up with their children using the keyed dictionary to make the
|
||||
// matching very convenient and easy work. Then we'll just return them.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getAttribute($this->localKey)])) {
|
||||
if (isset($dictionary[$key = $this->getDictionaryKey($model->getAttribute($this->localKey))])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->related->newCollection($dictionary[$key])
|
||||
);
|
||||
@@ -435,6 +431,22 @@ class HasManyThrough extends Relation
|
||||
return $this->query->simplePaginate($perPage, $columns, $pageName, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the given query into a cursor paginator.
|
||||
*
|
||||
* @param int|null $perPage
|
||||
* @param array $columns
|
||||
* @param string $cursorName
|
||||
* @param string|null $cursor
|
||||
* @return \Illuminate\Contracts\Pagination\CursorPaginator
|
||||
*/
|
||||
public function cursorPaginate($perPage = null, $columns = ['*'], $cursorName = 'cursor', $cursor = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return $this->query->cursorPaginate($perPage, $columns, $cursorName, $cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the select clause for the relation query.
|
||||
*
|
||||
@@ -508,6 +520,34 @@ class HasManyThrough extends Relation
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunks of the given size.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*/
|
||||
public function lazy($chunkSize = 1000)
|
||||
{
|
||||
return $this->prepareQueryBuilder()->lazy($chunkSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query lazily, by chunking the results of a query by comparing IDs.
|
||||
*
|
||||
* @param int $chunkSize
|
||||
* @param string|null $column
|
||||
* @param string|null $alias
|
||||
* @return \Illuminate\Support\LazyCollection
|
||||
*/
|
||||
public function lazyById($chunkSize = 1000, $column = null, $alias = null)
|
||||
{
|
||||
$column = $column ?? $this->getRelated()->getQualifiedKeyName();
|
||||
|
||||
$alias = $alias ?? $this->getRelated()->getKeyName();
|
||||
|
||||
return $this->prepareQueryBuilder()->lazyById($chunkSize, $column, $alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the query builder for query execution.
|
||||
*
|
||||
@@ -596,16 +636,6 @@ class HasManyThrough extends Relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the related model.
|
||||
*
|
||||
|
||||
73
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOne.php
vendored
Normal file → Executable file
73
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOne.php
vendored
Normal file → Executable file
@@ -2,13 +2,18 @@
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Contracts\Database\Eloquent\SupportsPartialRelations;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\CanBeOneOfMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\ComparesRelatedModels;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
|
||||
class HasOne extends HasOneOrMany
|
||||
class HasOne extends HasOneOrMany implements SupportsPartialRelations
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
use ComparesRelatedModels, CanBeOneOfMany, SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
@@ -53,6 +58,59 @@ class HasOne extends HasOneOrMany
|
||||
return $this->matchOne($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for an internal relationship existence query.
|
||||
*
|
||||
* Essentially, these queries compare on column names like "whereColumn".
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
if ($this->isOneOfMany()) {
|
||||
$this->mergeOneOfManyJoinsTo($query);
|
||||
}
|
||||
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add constraints for inner join subselect for one of many relationships.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string|null $column
|
||||
* @param string|null $aggregate
|
||||
* @return void
|
||||
*/
|
||||
public function addOneOfManySubQueryConstraints(Builder $query, $column = null, $aggregate = null)
|
||||
{
|
||||
$query->addSelect($this->foreignKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns that should be selected by the one of many subquery.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function getOneOfManySubQuerySelectColumns()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add join query constraints for one of many relationships.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\JoinClause $join
|
||||
* @return void
|
||||
*/
|
||||
public function addOneOfManyJoinSubQueryConstraints(JoinClause $join)
|
||||
{
|
||||
$join->on($this->qualifySubSelectColumn($this->foreignKey), '=', $this->qualifyRelatedColumn($this->foreignKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
@@ -65,4 +123,15 @@ class HasOne extends HasOneOrMany
|
||||
$this->getForeignKeyName(), $parent->{$this->localKey}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the model's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRelatedKeyFrom(Model $model)
|
||||
{
|
||||
return $model->getAttribute($this->getForeignKeyName());
|
||||
}
|
||||
}
|
||||
|
||||
57
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php
vendored
Normal file → Executable file
57
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php
vendored
Normal file → Executable file
@@ -5,9 +5,12 @@ namespace Illuminate\Database\Eloquent\Relations;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
|
||||
|
||||
abstract class HasOneOrMany extends Relation
|
||||
{
|
||||
use InteractsWithDictionary;
|
||||
|
||||
/**
|
||||
* The foreign key of the parent model.
|
||||
*
|
||||
@@ -22,13 +25,6 @@ abstract class HasOneOrMany extends Relation
|
||||
*/
|
||||
protected $localKey;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new has one or many relationship instance.
|
||||
*
|
||||
@@ -60,7 +56,7 @@ abstract class HasOneOrMany extends Relation
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an un-saved instances of the related models.
|
||||
* Create and return an un-saved instance of the related models.
|
||||
*
|
||||
* @param iterable $records
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
@@ -84,9 +80,11 @@ abstract class HasOneOrMany extends Relation
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
$this->query->where($this->foreignKey, '=', $this->getParentKey());
|
||||
$query = $this->getRelationQuery();
|
||||
|
||||
$this->query->whereNotNull($this->foreignKey);
|
||||
$query->where($this->foreignKey, '=', $this->getParentKey());
|
||||
|
||||
$query->whereNotNull($this->foreignKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +98,7 @@ abstract class HasOneOrMany extends Relation
|
||||
{
|
||||
$whereIn = $this->whereInMethod($this->parent, $this->localKey);
|
||||
|
||||
$this->query->{$whereIn}(
|
||||
$this->getRelationQuery()->{$whereIn}(
|
||||
$this->foreignKey, $this->getKeys($models, $this->localKey)
|
||||
);
|
||||
}
|
||||
@@ -148,7 +146,7 @@ abstract class HasOneOrMany extends Relation
|
||||
// link them up with their children using the keyed dictionary to make the
|
||||
// matching very convenient and easy work. Then we'll just return them.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getAttribute($this->localKey)])) {
|
||||
if (isset($dictionary[$key = $this->getDictionaryKey($model->getAttribute($this->localKey))])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->getRelationValue($dictionary, $key, $type)
|
||||
);
|
||||
@@ -184,12 +182,12 @@ abstract class HasOneOrMany extends Relation
|
||||
$foreign = $this->getForeignKeyName();
|
||||
|
||||
return $results->mapToDictionary(function ($result) use ($foreign) {
|
||||
return [$result->{$foreign} => $result];
|
||||
return [$this->getDictionaryKey($result->{$foreign}) => $result];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a model by its primary key or return new instance of the related model.
|
||||
* Find a model by its primary key or return a new instance of the related model.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
@@ -213,10 +211,10 @@ abstract class HasOneOrMany extends Relation
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes, array $values = [])
|
||||
public function firstOrNew(array $attributes = [], array $values = [])
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes + $values);
|
||||
$instance = $this->related->newInstance(array_merge($attributes, $values));
|
||||
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
}
|
||||
@@ -231,10 +229,10 @@ abstract class HasOneOrMany extends Relation
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrCreate(array $attributes, array $values = [])
|
||||
public function firstOrCreate(array $attributes = [], array $values = [])
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->create($attributes + $values);
|
||||
$instance = $this->create(array_merge($attributes, $values));
|
||||
}
|
||||
|
||||
return $instance;
|
||||
@@ -299,6 +297,19 @@ abstract class HasOneOrMany extends Relation
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the related model. Allow mass-assignment.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function forceCreate(array $attributes = [])
|
||||
{
|
||||
$attributes[$this->getForeignKeyName()] = $this->getParentKey();
|
||||
|
||||
return $this->related->forceCreate($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Collection of new instances of the related model.
|
||||
*
|
||||
@@ -363,16 +374,6 @@ abstract class HasOneOrMany extends Relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash()
|
||||
{
|
||||
return 'laravel_reserved_'.static::$selfJoinCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for comparing against the parent key in "has" query.
|
||||
*
|
||||
|
||||
@@ -4,11 +4,12 @@ namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class HasOneThrough extends HasManyThrough
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
use InteractsWithDictionary, SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
@@ -52,7 +53,7 @@ class HasOneThrough extends HasManyThrough
|
||||
// link them up with their children using the keyed dictionary to make the
|
||||
// matching very convenient and easy work. Then we'll just return them.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getAttribute($this->localKey)])) {
|
||||
if (isset($dictionary[$key = $this->getDictionaryKey($model->getAttribute($this->localKey))])) {
|
||||
$value = $dictionary[$key];
|
||||
$model->setRelation(
|
||||
$relation, reset($value)
|
||||
|
||||
13
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphMany.php
vendored
Normal file → Executable file
13
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphMany.php
vendored
Normal file → Executable file
@@ -46,4 +46,17 @@ class MorphMany extends MorphOneOrMany
|
||||
{
|
||||
return $this->matchMany($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the related model. Allow mass-assignment.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function forceCreate(array $attributes = [])
|
||||
{
|
||||
$attributes[$this->getMorphType()] = $this->morphClass;
|
||||
|
||||
return parent::forceCreate($attributes);
|
||||
}
|
||||
}
|
||||
|
||||
73
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOne.php
vendored
Normal file → Executable file
73
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOne.php
vendored
Normal file → Executable file
@@ -2,13 +2,18 @@
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Contracts\Database\Eloquent\SupportsPartialRelations;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\CanBeOneOfMany;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\ComparesRelatedModels;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
|
||||
class MorphOne extends MorphOneOrMany
|
||||
class MorphOne extends MorphOneOrMany implements SupportsPartialRelations
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
use CanBeOneOfMany, ComparesRelatedModels, SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
@@ -53,6 +58,59 @@ class MorphOne extends MorphOneOrMany
|
||||
return $this->matchOne($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
if ($this->isOneOfMany()) {
|
||||
$this->mergeOneOfManyJoinsTo($query);
|
||||
}
|
||||
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add constraints for inner join subselect for one of many relationships.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param string|null $column
|
||||
* @param string|null $aggregate
|
||||
* @return void
|
||||
*/
|
||||
public function addOneOfManySubQueryConstraints(Builder $query, $column = null, $aggregate = null)
|
||||
{
|
||||
$query->addSelect($this->foreignKey, $this->morphType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the columns that should be selected by the one of many subquery.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function getOneOfManySubQuerySelectColumns()
|
||||
{
|
||||
return [$this->foreignKey, $this->morphType];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add join query constraints for one of many relationships.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\JoinClause $join
|
||||
* @return void
|
||||
*/
|
||||
public function addOneOfManyJoinSubQueryConstraints(JoinClause $join)
|
||||
{
|
||||
$join
|
||||
->on($this->qualifySubSelectColumn($this->morphType), '=', $this->qualifyRelatedColumn($this->morphType))
|
||||
->on($this->qualifySubSelectColumn($this->foreignKey), '=', $this->qualifyRelatedColumn($this->foreignKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
@@ -65,4 +123,15 @@ class MorphOne extends MorphOneOrMany
|
||||
->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey})
|
||||
->setAttribute($this->getMorphType(), $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the model's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRelatedKeyFrom(Model $model)
|
||||
{
|
||||
return $model->getAttribute($this->getForeignKeyName());
|
||||
}
|
||||
}
|
||||
|
||||
6
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php
vendored
Normal file → Executable file
6
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php
vendored
Normal file → Executable file
@@ -48,9 +48,9 @@ abstract class MorphOneOrMany extends HasOneOrMany
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
parent::addConstraints();
|
||||
$this->getRelationQuery()->where($this->morphType, $this->morphClass);
|
||||
|
||||
$this->query->where($this->morphType, $this->morphClass);
|
||||
parent::addConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ abstract class MorphOneOrMany extends HasOneOrMany
|
||||
{
|
||||
parent::addEagerConstraints($models);
|
||||
|
||||
$this->query->where($this->morphType, $this->morphClass);
|
||||
$this->getRelationQuery()->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MorphPivot extends Pivot
|
||||
@@ -31,13 +30,26 @@ class MorphPivot extends Pivot
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
protected function setKeysForSaveQuery($query)
|
||||
{
|
||||
$query->where($this->morphType, $this->morphClass);
|
||||
|
||||
return parent::setKeysForSaveQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a select query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSelectQuery($query)
|
||||
{
|
||||
$query->where($this->morphType, $this->morphClass);
|
||||
|
||||
return parent::setKeysForSelectQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot model record from the database.
|
||||
*
|
||||
@@ -62,6 +74,16 @@ class MorphPivot extends Pivot
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the morph type for the pivot.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the morph type for the pivot.
|
||||
*
|
||||
|
||||
@@ -6,9 +6,12 @@ use BadMethodCallException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\InteractsWithDictionary;
|
||||
|
||||
class MorphTo extends BelongsTo
|
||||
{
|
||||
use InteractsWithDictionary;
|
||||
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
@@ -51,6 +54,13 @@ class MorphTo extends BelongsTo
|
||||
*/
|
||||
protected $morphableEagerLoadCounts = [];
|
||||
|
||||
/**
|
||||
* A map of constraints to apply for each individual morph type.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $morphableConstraints = [];
|
||||
|
||||
/**
|
||||
* Create a new morph to relationship instance.
|
||||
*
|
||||
@@ -90,7 +100,10 @@ class MorphTo extends BelongsTo
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
if ($model->{$this->morphType}) {
|
||||
$this->dictionary[$model->{$this->morphType}][$model->{$this->foreignKey}][] = $model;
|
||||
$morphTypeKey = $this->getDictionaryKey($model->{$this->morphType});
|
||||
$foreignKeyKey = $this->getDictionaryKey($model->{$this->foreignKey});
|
||||
|
||||
$this->dictionary[$morphTypeKey][$foreignKeyKey][] = $model;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,10 +146,14 @@ class MorphTo extends BelongsTo
|
||||
(array) ($this->morphableEagerLoadCounts[get_class($instance)] ?? [])
|
||||
);
|
||||
|
||||
if ($callback = ($this->morphableConstraints[get_class($instance)] ?? null)) {
|
||||
$callback($query);
|
||||
}
|
||||
|
||||
$whereIn = $this->whereInMethod($instance, $ownerKey);
|
||||
|
||||
return $query->{$whereIn}(
|
||||
$instance->getTable().'.'.$ownerKey, $this->gatherKeysByType($type)
|
||||
$instance->getTable().'.'.$ownerKey, $this->gatherKeysByType($type, $instance->getKeyType())
|
||||
)->get();
|
||||
}
|
||||
|
||||
@@ -144,11 +161,16 @@ class MorphTo extends BelongsTo
|
||||
* Gather all of the foreign keys for a given type.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $keyType
|
||||
* @return array
|
||||
*/
|
||||
protected function gatherKeysByType($type)
|
||||
protected function gatherKeysByType($type, $keyType)
|
||||
{
|
||||
return array_keys($this->dictionary[$type]);
|
||||
return $keyType !== 'string'
|
||||
? array_keys($this->dictionary[$type])
|
||||
: array_map(function ($modelId) {
|
||||
return (string) $modelId;
|
||||
}, array_filter(array_keys($this->dictionary[$type])));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +213,7 @@ class MorphTo extends BelongsTo
|
||||
protected function matchToMorphParents($type, Collection $results)
|
||||
{
|
||||
foreach ($results as $result) {
|
||||
$ownerKey = ! is_null($this->ownerKey) ? $result->{$this->ownerKey} : $result->getKey();
|
||||
$ownerKey = ! is_null($this->ownerKey) ? $this->getDictionaryKey($result->{$this->ownerKey}) : $result->getKey();
|
||||
|
||||
if (isset($this->dictionary[$type][$ownerKey])) {
|
||||
foreach ($this->dictionary[$type][$ownerKey] as $model) {
|
||||
@@ -209,8 +231,14 @@ class MorphTo extends BelongsTo
|
||||
*/
|
||||
public function associate($model)
|
||||
{
|
||||
if ($model instanceof Model) {
|
||||
$foreignKey = $this->ownerKey && $model->{$this->ownerKey}
|
||||
? $this->ownerKey
|
||||
: $model->getKeyName();
|
||||
}
|
||||
|
||||
$this->parent->setAttribute(
|
||||
$this->foreignKey, $model instanceof Model ? $model->getKey() : null
|
||||
$this->foreignKey, $model instanceof Model ? $model->{$foreignKey} : null
|
||||
);
|
||||
|
||||
$this->parent->setAttribute(
|
||||
@@ -307,6 +335,21 @@ class MorphTo extends BelongsTo
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify constraints on the query for a given morph type.
|
||||
*
|
||||
* @param array $callbacks
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function constrain(array $callbacks)
|
||||
{
|
||||
$this->morphableConstraints = array_merge(
|
||||
$this->morphableConstraints, $callbacks
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replay stored macro calls on the actual related instance.
|
||||
*
|
||||
|
||||
@@ -68,7 +68,7 @@ class MorphToMany extends BelongsToMany
|
||||
{
|
||||
parent::addWhereConstraints();
|
||||
|
||||
$this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
|
||||
$this->query->where($this->qualifyPivotColumn($this->morphType), $this->morphClass);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class MorphToMany extends BelongsToMany
|
||||
{
|
||||
parent::addEagerConstraints($models);
|
||||
|
||||
$this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
|
||||
$this->query->where($this->qualifyPivotColumn($this->morphType), $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +111,7 @@ class MorphToMany extends BelongsToMany
|
||||
public function getRelationExistenceQuery(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns)->where(
|
||||
$this->table.'.'.$this->morphType, $this->morphClass
|
||||
$this->qualifyPivotColumn($this->morphType), $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ class MorphToMany extends BelongsToMany
|
||||
$defaults = [$this->foreignPivotKey, $this->relatedPivotKey, $this->morphType];
|
||||
|
||||
return collect(array_merge($defaults, $this->pivotColumns))->map(function ($column) {
|
||||
return $this->table.'.'.$column.' as pivot_'.$column;
|
||||
return $this->qualifyPivotColumn($column).' as pivot_'.$column;
|
||||
})->unique()->all();
|
||||
}
|
||||
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Pivot.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Pivot.php
vendored
Normal file → Executable file
106
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php
vendored
Normal file → Executable file
106
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php
vendored
Normal file → Executable file
@@ -6,6 +6,8 @@ use Closure;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Database\MultipleRecordsFoundException;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Traits\ForwardsCalls;
|
||||
@@ -49,12 +51,26 @@ abstract class Relation
|
||||
protected static $constraints = true;
|
||||
|
||||
/**
|
||||
* An array to map class names to their morph names in database.
|
||||
* An array to map class names to their morph names in the database.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $morphMap = [];
|
||||
|
||||
/**
|
||||
* Prevents morph relationships without a morph map.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $requireMorphMap = false;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new relation instance.
|
||||
*
|
||||
@@ -144,6 +160,30 @@ abstract class Relation
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result if it's the sole matching record.
|
||||
*
|
||||
* @param array|string $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
* @throws \Illuminate\Database\MultipleRecordsFoundException
|
||||
*/
|
||||
public function sole($columns = ['*'])
|
||||
{
|
||||
$result = $this->take(2)->get($columns);
|
||||
|
||||
if ($result->isEmpty()) {
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
if ($result->count() > 1) {
|
||||
throw new MultipleRecordsFoundException;
|
||||
}
|
||||
|
||||
return $result->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a "select" statement.
|
||||
*
|
||||
@@ -213,6 +253,17 @@ abstract class Relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship join table hash.
|
||||
*
|
||||
* @param bool $incrementJoinCount
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationCountHash($incrementJoinCount = true)
|
||||
{
|
||||
return 'laravel_reserved_'.($incrementJoinCount ? static::$selfJoinCount++ : static::$selfJoinCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the primary keys for an array of models.
|
||||
*
|
||||
@@ -227,6 +278,16 @@ abstract class Relation
|
||||
})->values()->unique(null, true)->sort()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query builder that will contain the relationship constraints.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function getRelationQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying query for the relation.
|
||||
*
|
||||
@@ -322,6 +383,41 @@ abstract class Relation
|
||||
: 'whereIn';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent polymorphic relationships from being used without model mappings.
|
||||
*
|
||||
* @param bool $requireMorphMap
|
||||
* @return void
|
||||
*/
|
||||
public static function requireMorphMap($requireMorphMap = true)
|
||||
{
|
||||
static::$requireMorphMap = $requireMorphMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if polymorphic relationships require explicit model mapping.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function requiresMorphMap()
|
||||
{
|
||||
return static::$requireMorphMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the morph map for polymorphic relations and require all morphed models to be explicitly mapped.
|
||||
*
|
||||
* @param array $map
|
||||
* @param bool $merge
|
||||
* @return array
|
||||
*/
|
||||
public static function enforceMorphMap(array $map, $merge = true)
|
||||
{
|
||||
static::requireMorphMap();
|
||||
|
||||
return static::morphMap($map, $merge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or get the morph map for polymorphic relations.
|
||||
*
|
||||
@@ -382,13 +478,7 @@ abstract class Relation
|
||||
return $this->macroCall($method, $parameters);
|
||||
}
|
||||
|
||||
$result = $this->forwardCallTo($this->query, $method, $parameters);
|
||||
|
||||
if ($result === $this->query) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $this->forwardDecoratedCallTo($this->query, $method, $parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
/**
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withTrashed()
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withTrashed(bool $withTrashed = true)
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder onlyTrashed()
|
||||
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withoutTrashed()
|
||||
*/
|
||||
@@ -33,7 +33,9 @@ trait SoftDeletes
|
||||
*/
|
||||
public function initializeSoftDeletes()
|
||||
{
|
||||
$this->dates[] = $this->getDeletedAtColumn();
|
||||
if (! isset($this->casts[$this->getDeletedAtColumn()])) {
|
||||
$this->casts[$this->getDeletedAtColumn()] = 'datetime';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,9 +64,9 @@ trait SoftDeletes
|
||||
protected function performDeleteOnModel()
|
||||
{
|
||||
if ($this->forceDeleting) {
|
||||
$this->exists = false;
|
||||
|
||||
return $this->setKeysForSaveQuery($this->newModelQuery())->forceDelete();
|
||||
return tap($this->setKeysForSaveQuery($this->newModelQuery())->forceDelete(), function () {
|
||||
$this->exists = false;
|
||||
});
|
||||
}
|
||||
|
||||
return $this->runSoftDelete();
|
||||
@@ -94,6 +96,8 @@ trait SoftDeletes
|
||||
$query->update($columns);
|
||||
|
||||
$this->syncOriginalAttributes(array_keys($columns));
|
||||
|
||||
$this->fireModelEvent('trashed', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,6 +138,17 @@ trait SoftDeletes
|
||||
return ! is_null($this->{$this->getDeletedAtColumn()});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "softDeleted" model event callback with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function softDeleted($callback)
|
||||
{
|
||||
static::registerModelEvent('trashed', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a "restoring" model event callback with the dispatcher.
|
||||
*
|
||||
|
||||
@@ -7,7 +7,7 @@ class SoftDeletingScope implements Scope
|
||||
/**
|
||||
* All of the extensions to be added to the builder.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $extensions = ['Restore', 'WithTrashed', 'WithoutTrashed', 'OnlyTrashed'];
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use Illuminate\Database\Migrations\Migration;
|
||||
abstract class MigrationEvent implements MigrationEventContract
|
||||
{
|
||||
/**
|
||||
* An migration instance.
|
||||
* A migration instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migration
|
||||
*/
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
use Illuminate\Contracts\Database\Events\MigrationEvent as MigrationEventContract;
|
||||
|
||||
class MigrationsEnded implements MigrationEventContract
|
||||
class MigrationsEnded extends MigrationsEvent
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
use Illuminate\Contracts\Database\Events\MigrationEvent as MigrationEventContract;
|
||||
|
||||
class MigrationsStarted implements MigrationEventContract
|
||||
class MigrationsStarted extends MigrationsEvent
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
2
vendor/laravel/framework/src/Illuminate/Database/Grammar.php
vendored
Normal file → Executable file
2
vendor/laravel/framework/src/Illuminate/Database/Grammar.php
vendored
Normal file → Executable file
@@ -179,7 +179,7 @@ abstract class Grammar
|
||||
* Get the value of a raw expression.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression $expression
|
||||
* @return string
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue($expression)
|
||||
{
|
||||
|
||||
3
vendor/laravel/framework/src/Illuminate/Database/MigrationServiceProvider.php
vendored
Normal file → Executable file
3
vendor/laravel/framework/src/Illuminate/Database/MigrationServiceProvider.php
vendored
Normal file → Executable file
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\Support\DeferrableProvider;
|
||||
use Illuminate\Database\Console\Migrations\FreshCommand;
|
||||
use Illuminate\Database\Console\Migrations\InstallCommand;
|
||||
@@ -116,7 +117,7 @@ class MigrationServiceProvider extends ServiceProvider implements DeferrableProv
|
||||
protected function registerMigrateCommand()
|
||||
{
|
||||
$this->app->singleton('command.migrate', function ($app) {
|
||||
return new MigrateCommand($app['migrator']);
|
||||
return new MigrateCommand($app['migrator'], $app[Dispatcher::class]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
12
vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php
vendored
Normal file → Executable file
12
vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php
vendored
Normal file → Executable file
@@ -169,6 +169,18 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface
|
||||
return $schema->hasTable($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteRepository()
|
||||
{
|
||||
$schema = $this->getConnection()->getSchemaBuilder();
|
||||
|
||||
$schema->drop($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a query builder for the migration table.
|
||||
*
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migration.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migration.php
vendored
Normal file → Executable file
7
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationCreator.php
vendored
Normal file → Executable file
7
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationCreator.php
vendored
Normal file → Executable file
@@ -63,9 +63,12 @@ class MigrationCreator
|
||||
// various place-holders, save the file, and run the post create event.
|
||||
$stub = $this->getStub($table, $create);
|
||||
|
||||
$path = $this->getPath($name, $path);
|
||||
|
||||
$this->files->ensureDirectoryExists(dirname($path));
|
||||
|
||||
$this->files->put(
|
||||
$path = $this->getPath($name, $path),
|
||||
$this->populateStub($name, $stub, $table)
|
||||
$path, $this->populateStub($name, $stub, $table)
|
||||
);
|
||||
|
||||
// Next, we will fire any hooks that are supposed to fire after a migration is
|
||||
|
||||
9
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php
vendored
Normal file → Executable file
9
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php
vendored
Normal file → Executable file
@@ -12,7 +12,7 @@ interface MigrationRepositoryInterface
|
||||
public function getRan();
|
||||
|
||||
/**
|
||||
* Get list of migrations.
|
||||
* Get the list of migrations.
|
||||
*
|
||||
* @param int $steps
|
||||
* @return array
|
||||
@@ -71,6 +71,13 @@ interface MigrationRepositoryInterface
|
||||
*/
|
||||
public function repositoryExists();
|
||||
|
||||
/**
|
||||
* Delete the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteRepository();
|
||||
|
||||
/**
|
||||
* Set the information source to gather data.
|
||||
*
|
||||
|
||||
127
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php
vendored
Normal file → Executable file
127
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php
vendored
Normal file → Executable file
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\SchemaException;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
use Illuminate\Database\Events\MigrationEnded;
|
||||
@@ -13,6 +14,7 @@ use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use ReflectionClass;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class Migrator
|
||||
@@ -156,7 +158,7 @@ class Migrator
|
||||
|
||||
$step = $options['step'] ?? false;
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsStarted);
|
||||
$this->fireMigrationEvent(new MigrationsStarted('up'));
|
||||
|
||||
// Once we have the array of migrations, we will spin through them and run the
|
||||
// migrations "up" so the changes are made to the databases. We'll then log
|
||||
@@ -169,7 +171,7 @@ class Migrator
|
||||
}
|
||||
}
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsEnded);
|
||||
$this->fireMigrationEvent(new MigrationsEnded('up'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,9 +187,9 @@ class Migrator
|
||||
// First we will resolve a "real" instance of the migration class from this
|
||||
// migration file name. Once we have the instances we can run the actual
|
||||
// command such as "up" or "down", or we can just simulate the action.
|
||||
$migration = $this->resolve(
|
||||
$name = $this->getMigrationName($file)
|
||||
);
|
||||
$migration = $this->resolvePath($file);
|
||||
|
||||
$name = $this->getMigrationName($file);
|
||||
|
||||
if ($pretend) {
|
||||
return $this->pretendToRun($migration, 'up');
|
||||
@@ -199,14 +201,14 @@ class Migrator
|
||||
|
||||
$this->runMigration($migration, 'up');
|
||||
|
||||
$runTime = round(microtime(true) - $startTime, 2);
|
||||
$runTime = number_format((microtime(true) - $startTime) * 1000, 2);
|
||||
|
||||
// Once we have run a migrations class, we will log that it was run in this
|
||||
// repository so that we don't try to run it next time we do a migration
|
||||
// in the application. A migration repository keeps the migrate order.
|
||||
$this->repository->log($name, $batch);
|
||||
|
||||
$this->note("<info>Migrated:</info> {$name} ({$runTime} seconds)");
|
||||
$this->note("<info>Migrated:</info> {$name} ({$runTime}ms)");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,7 +265,7 @@ class Migrator
|
||||
|
||||
$this->requireFiles($files = $this->getMigrationFiles($paths));
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsStarted);
|
||||
$this->fireMigrationEvent(new MigrationsStarted('down'));
|
||||
|
||||
// Next we will run through all of the migrations and call the "down" method
|
||||
// which will reverse each migration in order. This getLast method on the
|
||||
@@ -285,7 +287,7 @@ class Migrator
|
||||
);
|
||||
}
|
||||
|
||||
$this->fireMigrationEvent(new MigrationsEnded);
|
||||
$this->fireMigrationEvent(new MigrationsEnded('down'));
|
||||
|
||||
return $rolledBack;
|
||||
}
|
||||
@@ -348,9 +350,9 @@ class Migrator
|
||||
// First we will get the file name of the migration so we can resolve out an
|
||||
// instance of the migration. Once we get an instance we can either run a
|
||||
// pretend execution of the migration or we can run the real migration.
|
||||
$instance = $this->resolve(
|
||||
$name = $this->getMigrationName($file)
|
||||
);
|
||||
$instance = $this->resolvePath($file);
|
||||
|
||||
$name = $this->getMigrationName($file);
|
||||
|
||||
$this->note("<comment>Rolling back:</comment> {$name}");
|
||||
|
||||
@@ -362,14 +364,14 @@ class Migrator
|
||||
|
||||
$this->runMigration($instance, 'down');
|
||||
|
||||
$runTime = round(microtime(true) - $startTime, 2);
|
||||
$runTime = number_format((microtime(true) - $startTime) * 1000, 2);
|
||||
|
||||
// Once we have successfully run the migration "down" we will remove it from
|
||||
// the migration repository so it will be considered to have not been run
|
||||
// by the application then will be able to fire by any later operation.
|
||||
$this->repository->delete($migration);
|
||||
|
||||
$this->note("<info>Rolled back:</info> {$name} ({$runTime} seconds)");
|
||||
$this->note("<info>Rolled back:</info> {$name} ({$runTime}ms)");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,11 +387,11 @@ class Migrator
|
||||
$migration->getConnection()
|
||||
);
|
||||
|
||||
$callback = function () use ($migration, $method) {
|
||||
$callback = function () use ($connection, $migration, $method) {
|
||||
if (method_exists($migration, $method)) {
|
||||
$this->fireMigrationEvent(new MigrationStarted($migration, $method));
|
||||
|
||||
$migration->{$method}();
|
||||
$this->runMethod($connection, $migration, $method);
|
||||
|
||||
$this->fireMigrationEvent(new MigrationEnded($migration, $method));
|
||||
}
|
||||
@@ -410,10 +412,22 @@ class Migrator
|
||||
*/
|
||||
protected function pretendToRun($migration, $method)
|
||||
{
|
||||
foreach ($this->getQueries($migration, $method) as $query) {
|
||||
try {
|
||||
foreach ($this->getQueries($migration, $method) as $query) {
|
||||
$name = get_class($migration);
|
||||
|
||||
$reflectionClass = new ReflectionClass($migration);
|
||||
|
||||
if ($reflectionClass->isAnonymous()) {
|
||||
$name = $this->getMigrationName($reflectionClass->getFileName());
|
||||
}
|
||||
|
||||
$this->note("<info>{$name}:</info> {$query['query']}");
|
||||
}
|
||||
} catch (SchemaException $e) {
|
||||
$name = get_class($migration);
|
||||
|
||||
$this->note("<info>{$name}:</info> {$query['query']}");
|
||||
$this->note("<info>{$name}:</info> failed to dump queries. This may be due to changing database columns using Doctrine, which is not supported while pretending to run migrations.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,13 +447,34 @@ class Migrator
|
||||
$migration->getConnection()
|
||||
);
|
||||
|
||||
return $db->pretend(function () use ($migration, $method) {
|
||||
return $db->pretend(function () use ($db, $migration, $method) {
|
||||
if (method_exists($migration, $method)) {
|
||||
$migration->{$method}();
|
||||
$this->runMethod($db, $migration, $method);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a migration method on the given connection.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
protected function runMethod($connection, $migration, $method)
|
||||
{
|
||||
$previousConnection = $this->resolver->getDefaultConnection();
|
||||
|
||||
try {
|
||||
$this->resolver->setDefaultConnection($connection->getName());
|
||||
|
||||
$migration->{$method}();
|
||||
} finally {
|
||||
$this->resolver->setDefaultConnection($previousConnection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a migration instance from a file.
|
||||
*
|
||||
@@ -448,11 +483,41 @@ class Migrator
|
||||
*/
|
||||
public function resolve($file)
|
||||
{
|
||||
$class = Str::studly(implode('_', array_slice(explode('_', $file), 4)));
|
||||
$class = $this->getMigrationClass($file);
|
||||
|
||||
return new $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a migration instance from a migration path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return object
|
||||
*/
|
||||
protected function resolvePath(string $path)
|
||||
{
|
||||
$class = $this->getMigrationClass($this->getMigrationName($path));
|
||||
|
||||
if (class_exists($class) && realpath($path) == (new ReflectionClass($class))->getFileName()) {
|
||||
return new $class;
|
||||
}
|
||||
|
||||
$migration = $this->files->getRequire($path);
|
||||
|
||||
return is_object($migration) ? $migration : new $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a migration class name based on the migration file name.
|
||||
*
|
||||
* @param string $migrationName
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationClass(string $migrationName): string
|
||||
{
|
||||
return Str::studly(implode('_', array_slice(explode('_', $migrationName), 4)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the migration files in a given path.
|
||||
*
|
||||
@@ -608,6 +673,26 @@ class Migrator
|
||||
return $this->repository->repositoryExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if any migrations have been run.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRunAnyMigrations()
|
||||
{
|
||||
return $this->repositoryExists() && count($this->repository->getRan()) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteRepository()
|
||||
{
|
||||
return $this->repository->deleteRepository();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file system instance.
|
||||
*
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/migration.create.stub
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/migration.create.stub
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/migration.stub
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/migration.stub
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/migration.update.stub
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/migration.update.stub
vendored
Normal file → Executable file
31
vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php
vendored
Normal file → Executable file
31
vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php
vendored
Normal file → Executable file
@@ -3,13 +3,28 @@
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Doctrine\DBAL\Driver\PDOMySql\Driver as DoctrineDriver;
|
||||
use Doctrine\DBAL\Version;
|
||||
use Illuminate\Database\PDO\MySqlDriver;
|
||||
use Illuminate\Database\Query\Grammars\MySqlGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Query\Processors\MySqlProcessor;
|
||||
use Illuminate\Database\Schema\Grammars\MySqlGrammar as SchemaGrammar;
|
||||
use Illuminate\Database\Schema\MySqlBuilder;
|
||||
use Illuminate\Database\Schema\MySqlSchemaState;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use PDO;
|
||||
|
||||
class MySqlConnection extends Connection
|
||||
{
|
||||
/**
|
||||
* Determine if the connected database is a MariaDB database.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMaria()
|
||||
{
|
||||
return strpos($this->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION), 'MariaDB') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default query grammar instance.
|
||||
*
|
||||
@@ -44,6 +59,18 @@ class MySqlConnection extends Connection
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema state for the connection.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem|null $files
|
||||
* @param callable|null $processFactory
|
||||
* @return \Illuminate\Database\Schema\MySqlSchemaState
|
||||
*/
|
||||
public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
|
||||
{
|
||||
return new MySqlSchemaState($this, $files, $processFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
@@ -57,10 +84,10 @@ class MySqlConnection extends Connection
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOMySql\Driver
|
||||
* @return \Doctrine\DBAL\Driver\PDOMySql\Driver|\Illuminate\Database\PDO\MySqlDriver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
return class_exists(Version::class) ? new DoctrineDriver : new MySqlDriver;
|
||||
}
|
||||
}
|
||||
|
||||
20
vendor/laravel/framework/src/Illuminate/Database/PostgresConnection.php
vendored
Normal file → Executable file
20
vendor/laravel/framework/src/Illuminate/Database/PostgresConnection.php
vendored
Normal file → Executable file
@@ -3,10 +3,14 @@
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Doctrine\DBAL\Driver\PDOPgSql\Driver as DoctrineDriver;
|
||||
use Doctrine\DBAL\Version;
|
||||
use Illuminate\Database\PDO\PostgresDriver;
|
||||
use Illuminate\Database\Query\Grammars\PostgresGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Query\Processors\PostgresProcessor;
|
||||
use Illuminate\Database\Schema\Grammars\PostgresGrammar as SchemaGrammar;
|
||||
use Illuminate\Database\Schema\PostgresBuilder;
|
||||
use Illuminate\Database\Schema\PostgresSchemaState;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use PDO;
|
||||
|
||||
class PostgresConnection extends Connection
|
||||
@@ -71,6 +75,18 @@ class PostgresConnection extends Connection
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema state for the connection.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem|null $files
|
||||
* @param callable|null $processFactory
|
||||
* @return \Illuminate\Database\Schema\PostgresSchemaState
|
||||
*/
|
||||
public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
|
||||
{
|
||||
return new PostgresSchemaState($this, $files, $processFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
@@ -84,10 +100,10 @@ class PostgresConnection extends Connection
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOPgSql\Driver
|
||||
* @return \Doctrine\DBAL\Driver\PDOPgSql\Driver|\Illuminate\Database\PDO\PostgresDriver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
return class_exists(Version::class) ? new DoctrineDriver : new PostgresDriver;
|
||||
}
|
||||
}
|
||||
|
||||
363
vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
vendored
Normal file → Executable file
363
vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
vendored
Normal file → Executable file
@@ -2,10 +2,12 @@
|
||||
|
||||
namespace Illuminate\Database\Query;
|
||||
|
||||
use BackedEnum;
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Database\Concerns\BuildsQueries;
|
||||
use Illuminate\Database\Concerns\ExplainsQueries;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
@@ -19,11 +21,12 @@ use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\ForwardsCalls;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use RuntimeException;
|
||||
|
||||
class Builder
|
||||
{
|
||||
use BuildsQueries, ForwardsCalls, Macroable {
|
||||
use BuildsQueries, ExplainsQueries, ForwardsCalls, Macroable {
|
||||
__call as macroCall;
|
||||
}
|
||||
|
||||
@@ -180,21 +183,37 @@ class Builder
|
||||
public $lock;
|
||||
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
* The callbacks that should be invoked before the query is executed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $beforeQueryCallbacks = [];
|
||||
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $operators = [
|
||||
'=', '<', '>', '<=', '>=', '<>', '!=', '<=>',
|
||||
'like', 'like binary', 'not like', 'ilike',
|
||||
'&', '|', '^', '<<', '>>',
|
||||
'&', '|', '^', '<<', '>>', '&~',
|
||||
'rlike', 'not rlike', 'regexp', 'not regexp',
|
||||
'~', '~*', '!~', '!~*', 'similar to',
|
||||
'not similar to', 'not ilike', '~~*', '!~~*',
|
||||
];
|
||||
|
||||
/**
|
||||
* Whether use write pdo for select.
|
||||
* All of the available bitwise operators.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $bitwiseOperators = [
|
||||
'&', '|', '^', '<<', '>>', '&~',
|
||||
];
|
||||
|
||||
/**
|
||||
* Whether to use write pdo for the select.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
@@ -243,7 +262,7 @@ class Builder
|
||||
/**
|
||||
* Add a subselect expression to the query.
|
||||
*
|
||||
* @param \Closure|$this|string $query
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query
|
||||
* @param string $as
|
||||
* @return $this
|
||||
*
|
||||
@@ -339,6 +358,8 @@ class Builder
|
||||
protected function parseSub($query)
|
||||
{
|
||||
if ($query instanceof self || $query instanceof EloquentBuilder || $query instanceof Relation) {
|
||||
$query = $this->prependDatabaseNameIfCrossDatabaseQuery($query);
|
||||
|
||||
return [$query->toSql(), $query->getBindings()];
|
||||
} elseif (is_string($query)) {
|
||||
return [$query, []];
|
||||
@@ -349,6 +370,26 @@ class Builder
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend the database name if the given query is on another database.
|
||||
*
|
||||
* @param mixed $query
|
||||
* @return mixed
|
||||
*/
|
||||
protected function prependDatabaseNameIfCrossDatabaseQuery($query)
|
||||
{
|
||||
if ($query->getConnection()->getDatabaseName() !==
|
||||
$this->getConnection()->getDatabaseName()) {
|
||||
$databaseName = $query->getConnection()->getDatabaseName();
|
||||
|
||||
if (strpos($query->from, $databaseName) !== 0 && strpos($query->from, '.') === false) {
|
||||
$query->from($databaseName.'.'.$query->from);
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new select column to the query.
|
||||
*
|
||||
@@ -377,6 +418,7 @@ class Builder
|
||||
/**
|
||||
* Force the query to only return distinct results.
|
||||
*
|
||||
* @param mixed ...$distinct
|
||||
* @return $this
|
||||
*/
|
||||
public function distinct()
|
||||
@@ -468,7 +510,7 @@ class Builder
|
||||
/**
|
||||
* Add a subquery join clause to the query.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|string $query
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query
|
||||
* @param string $as
|
||||
* @param \Closure|string $first
|
||||
* @param string|null $operator
|
||||
@@ -521,7 +563,7 @@ class Builder
|
||||
/**
|
||||
* Add a subquery left join to the query.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|string $query
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query
|
||||
* @param string $as
|
||||
* @param \Closure|string $first
|
||||
* @param string|null $operator
|
||||
@@ -564,7 +606,7 @@ class Builder
|
||||
/**
|
||||
* Add a subquery right join to the query.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|string $query
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|string $query
|
||||
* @param string $as
|
||||
* @param \Closure|string $first
|
||||
* @param string|null $operator
|
||||
@@ -596,6 +638,26 @@ class Builder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subquery cross join to the query.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|string $query
|
||||
* @param string $as
|
||||
* @return $this
|
||||
*/
|
||||
public function crossJoinSub($query, $as)
|
||||
{
|
||||
[$query, $bindings] = $this->createSub($query);
|
||||
|
||||
$expression = '('.$query.') as '.$this->grammar->wrapTable($as);
|
||||
|
||||
$this->addBinding($bindings, 'join');
|
||||
|
||||
$this->joins[] = $this->newJoinClause($this, 'cross', new Expression($expression));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new join clause.
|
||||
*
|
||||
@@ -701,6 +763,10 @@ class Builder
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isBitwiseOperator($operator)) {
|
||||
$type = 'Bitwise';
|
||||
}
|
||||
|
||||
// Now that we are working with just a simple query we can put the elements
|
||||
// in our array and add the query binding to our array of bindings that
|
||||
// will be bound to each SQL statements when it is finally executed.
|
||||
@@ -780,8 +846,20 @@ class Builder
|
||||
*/
|
||||
protected function invalidOperator($operator)
|
||||
{
|
||||
return ! in_array(strtolower($operator), $this->operators, true) &&
|
||||
! in_array(strtolower($operator), $this->grammar->getOperators(), true);
|
||||
return ! is_string($operator) || (! in_array(strtolower($operator), $this->operators, true) &&
|
||||
! in_array(strtolower($operator), $this->grammar->getOperators(), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operator is a bitwise operator.
|
||||
*
|
||||
* @param string $operator
|
||||
* @return bool
|
||||
*/
|
||||
protected function isBitwiseOperator($operator)
|
||||
{
|
||||
return in_array(strtolower($operator), $this->bitwiseOperators, true) ||
|
||||
in_array(strtolower($operator), $this->grammar->getBitwiseOperators(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1043,7 +1121,7 @@ class Builder
|
||||
/**
|
||||
* Add an "or where null" clause to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string|array $column
|
||||
* @return $this
|
||||
*/
|
||||
public function orWhereNull($column)
|
||||
@@ -1066,7 +1144,7 @@ class Builder
|
||||
/**
|
||||
* Add a where between statement to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string|\Illuminate\Database\Query\Expression $column
|
||||
* @param array $values
|
||||
* @param string $boolean
|
||||
* @param bool $not
|
||||
@@ -1189,7 +1267,7 @@ class Builder
|
||||
/**
|
||||
* Add a "where date" statement to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param \Illuminate\Database\Query\Expression|string $column
|
||||
* @param string $operator
|
||||
* @param \DateTimeInterface|string|null $value
|
||||
* @param string $boolean
|
||||
@@ -1768,6 +1846,39 @@ class Builder
|
||||
$this->where(Str::snake($segment), '=', $parameters[$index], $bool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a "where fulltext" clause to the query.
|
||||
*
|
||||
* @param string|string[] $columns
|
||||
* @param string $value
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
*/
|
||||
public function whereFullText($columns, $value, array $options = [], $boolean = 'and')
|
||||
{
|
||||
$type = 'Fulltext';
|
||||
|
||||
$columns = (array) $columns;
|
||||
|
||||
$this->wheres[] = compact('type', 'columns', 'value', 'options', 'boolean');
|
||||
|
||||
$this->addBinding($value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a "or where fulltext" clause to the query.
|
||||
*
|
||||
* @param string|string[] $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function orWhereFullText($columns, $value, array $options = [])
|
||||
{
|
||||
return $this->whereFulltext($columns, $value, $options, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a "group by" clause to the query.
|
||||
*
|
||||
@@ -1829,6 +1940,10 @@ class Builder
|
||||
[$value, $operator] = [$operator, '='];
|
||||
}
|
||||
|
||||
if ($this->isBitwiseOperator($operator)) {
|
||||
$type = 'Bitwise';
|
||||
}
|
||||
|
||||
$this->havings[] = compact('type', 'column', 'operator', 'value', 'boolean');
|
||||
|
||||
if (! $value instanceof Expression) {
|
||||
@@ -1909,7 +2024,7 @@ class Builder
|
||||
/**
|
||||
* Add an "order by" clause to the query.
|
||||
*
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
|
||||
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
|
||||
* @param string $direction
|
||||
* @return $this
|
||||
*
|
||||
@@ -1942,7 +2057,7 @@ class Builder
|
||||
/**
|
||||
* Add a descending "order by" clause to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function orderByDesc($column)
|
||||
@@ -1953,7 +2068,7 @@ class Builder
|
||||
/**
|
||||
* Add an "order by" clause for a timestamp to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function latest($column = 'created_at')
|
||||
@@ -1964,7 +2079,7 @@ class Builder
|
||||
/**
|
||||
* Add an "order by" clause for a timestamp to the query.
|
||||
*
|
||||
* @param string $column
|
||||
* @param \Closure|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string $column
|
||||
* @return $this
|
||||
*/
|
||||
public function oldest($column = 'created_at')
|
||||
@@ -2110,7 +2225,7 @@ class Builder
|
||||
/**
|
||||
* Remove all existing orders and optionally add a new order.
|
||||
*
|
||||
* @param string|null $column
|
||||
* @param \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Query\Expression|string|null $column
|
||||
* @param string $direction
|
||||
* @return $this
|
||||
*/
|
||||
@@ -2211,6 +2326,33 @@ class Builder
|
||||
return $this->lock(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a closure to be invoked before the query is executed.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function beforeQuery(callable $callback)
|
||||
{
|
||||
$this->beforeQueryCallbacks[] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the "before query" modification callbacks.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function applyBeforeQueryCallbacks()
|
||||
{
|
||||
foreach ($this->beforeQueryCallbacks as $callback) {
|
||||
$callback($this);
|
||||
}
|
||||
|
||||
$this->beforeQueryCallbacks = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL representation of the query.
|
||||
*
|
||||
@@ -2218,6 +2360,8 @@ class Builder
|
||||
*/
|
||||
public function toSql()
|
||||
{
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
return $this->grammar->compileSelect($this);
|
||||
}
|
||||
|
||||
@@ -2317,6 +2461,43 @@ class Builder
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginator only supporting simple next and previous links.
|
||||
*
|
||||
* This is more efficient on larger data-sets, etc.
|
||||
*
|
||||
* @param int|null $perPage
|
||||
* @param array $columns
|
||||
* @param string $cursorName
|
||||
* @param \Illuminate\Pagination\Cursor|string|null $cursor
|
||||
* @return \Illuminate\Contracts\Pagination\CursorPaginator
|
||||
*/
|
||||
public function cursorPaginate($perPage = 15, $columns = ['*'], $cursorName = 'cursor', $cursor = null)
|
||||
{
|
||||
return $this->paginateUsingCursor($perPage, $columns, $cursorName, $cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the proper order by required for cursor pagination.
|
||||
*
|
||||
* @param bool $shouldReverse
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function ensureOrderForCursorPagination($shouldReverse = false)
|
||||
{
|
||||
$this->enforceOrderBy();
|
||||
|
||||
return collect($this->orders ?? $this->unionOrders ?? [])->filter(function ($order) {
|
||||
return Arr::has($order, 'direction');
|
||||
})->when($shouldReverse, function (Collection $orders) {
|
||||
return $orders->map(function ($order) {
|
||||
$order['direction'] = $order['direction'] === 'asc' ? 'desc' : 'asc';
|
||||
|
||||
return $order;
|
||||
});
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of the total records for the paginator.
|
||||
*
|
||||
@@ -2427,7 +2608,7 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array with the values of a given column.
|
||||
* Get a collection instance containing the values of a given column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string|null $key
|
||||
@@ -2549,6 +2730,8 @@ class Builder
|
||||
*/
|
||||
public function exists()
|
||||
{
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
$results = $this->connection->select(
|
||||
$this->grammar->compileExists($this), $this->getBindings(), ! $this->useWritePdo
|
||||
);
|
||||
@@ -2674,8 +2857,8 @@ class Builder
|
||||
*/
|
||||
public function aggregate($function, $columns = ['*'])
|
||||
{
|
||||
$results = $this->cloneWithout($this->unions ? [] : ['columns'])
|
||||
->cloneWithoutBindings($this->unions ? [] : ['select'])
|
||||
$results = $this->cloneWithout($this->unions || $this->havings ? [] : ['columns'])
|
||||
->cloneWithoutBindings($this->unions || $this->havings ? [] : ['select'])
|
||||
->setAggregate($function, $columns)
|
||||
->get($columns);
|
||||
|
||||
@@ -2758,7 +2941,7 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new record into the database.
|
||||
* Insert new records into the database.
|
||||
*
|
||||
* @param array $values
|
||||
* @return bool
|
||||
@@ -2787,6 +2970,8 @@ class Builder
|
||||
}
|
||||
}
|
||||
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
// Finally, we will run this query against the database connection and return
|
||||
// the results. We will need to also flatten these bindings before running
|
||||
// the query so they are all in one huge, flattened array for execution.
|
||||
@@ -2797,7 +2982,7 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new record into the database while ignoring errors.
|
||||
* Insert new records into the database while ignoring errors.
|
||||
*
|
||||
* @param array $values
|
||||
* @return int
|
||||
@@ -2817,6 +3002,8 @@ class Builder
|
||||
}
|
||||
}
|
||||
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
return $this->connection->affectingStatement(
|
||||
$this->grammar->compileInsertOrIgnore($this, $values),
|
||||
$this->cleanBindings(Arr::flatten($values, 1))
|
||||
@@ -2832,6 +3019,8 @@ class Builder
|
||||
*/
|
||||
public function insertGetId(array $values, $sequence = null)
|
||||
{
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
$sql = $this->grammar->compileInsertGetId($this, $values, $sequence);
|
||||
|
||||
$values = $this->cleanBindings($values);
|
||||
@@ -2848,6 +3037,8 @@ class Builder
|
||||
*/
|
||||
public function insertUsing(array $columns, $query)
|
||||
{
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
[$sql, $bindings] = $this->createSub($query);
|
||||
|
||||
return $this->connection->affectingStatement(
|
||||
@@ -2857,13 +3048,15 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a record in the database.
|
||||
* Update records in the database.
|
||||
*
|
||||
* @param array $values
|
||||
* @return int
|
||||
*/
|
||||
public function update(array $values)
|
||||
{
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
$sql = $this->grammar->compileUpdate($this, $values);
|
||||
|
||||
return $this->connection->update($sql, $this->cleanBindings(
|
||||
@@ -2871,6 +3064,27 @@ class Builder
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update records in a PostgreSQL database using the update from syntax.
|
||||
*
|
||||
* @param array $values
|
||||
* @return int
|
||||
*/
|
||||
public function updateFrom(array $values)
|
||||
{
|
||||
if (! method_exists($this->grammar, 'compileUpdateFrom')) {
|
||||
throw new LogicException('This database engine does not support the updateFrom method.');
|
||||
}
|
||||
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
$sql = $this->grammar->compileUpdateFrom($this, $values);
|
||||
|
||||
return $this->connection->update($sql, $this->cleanBindings(
|
||||
$this->grammar->prepareBindingsForUpdateFrom($this->bindings, $values)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update a record matching the attributes, and fill it with values.
|
||||
*
|
||||
@@ -2891,6 +3105,51 @@ class Builder
|
||||
return (bool) $this->limit(1)->update($values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert new records or update the existing ones.
|
||||
*
|
||||
* @param array $values
|
||||
* @param array|string $uniqueBy
|
||||
* @param array|null $update
|
||||
* @return int
|
||||
*/
|
||||
public function upsert(array $values, $uniqueBy, $update = null)
|
||||
{
|
||||
if (empty($values)) {
|
||||
return 0;
|
||||
} elseif ($update === []) {
|
||||
return (int) $this->insert($values);
|
||||
}
|
||||
|
||||
if (! is_array(reset($values))) {
|
||||
$values = [$values];
|
||||
} else {
|
||||
foreach ($values as $key => $value) {
|
||||
ksort($value);
|
||||
|
||||
$values[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($update)) {
|
||||
$update = array_keys(reset($values));
|
||||
}
|
||||
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
$bindings = $this->cleanBindings(array_merge(
|
||||
Arr::flatten($values, 1),
|
||||
collect($update)->reject(function ($value, $key) {
|
||||
return is_int($key);
|
||||
})->all()
|
||||
));
|
||||
|
||||
return $this->connection->affectingStatement(
|
||||
$this->grammar->compileUpsert($this, $values, (array) $uniqueBy, $update),
|
||||
$bindings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a column's value by a given amount.
|
||||
*
|
||||
@@ -2938,7 +3197,7 @@ class Builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a record from the database.
|
||||
* Delete records from the database.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @return int
|
||||
@@ -2952,6 +3211,8 @@ class Builder
|
||||
$this->where($this->from.'.id', '=', $id);
|
||||
}
|
||||
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
return $this->connection->delete(
|
||||
$this->grammar->compileDelete($this), $this->cleanBindings(
|
||||
$this->grammar->prepareBindingsForDelete($this->bindings)
|
||||
@@ -2966,6 +3227,8 @@ class Builder
|
||||
*/
|
||||
public function truncate()
|
||||
{
|
||||
$this->applyBeforeQueryCallbacks();
|
||||
|
||||
foreach ($this->grammar->compileTruncate($this) as $sql => $bindings) {
|
||||
$this->connection->statement($sql, $bindings);
|
||||
}
|
||||
@@ -3058,14 +3321,32 @@ class Builder
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$this->bindings[$type] = array_values(array_merge($this->bindings[$type], $value));
|
||||
$this->bindings[$type] = array_values(array_map(
|
||||
[$this, 'castBinding'],
|
||||
array_merge($this->bindings[$type], $value),
|
||||
));
|
||||
} else {
|
||||
$this->bindings[$type][] = $value;
|
||||
$this->bindings[$type][] = $this->castBinding($value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given binding value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function castBinding($value)
|
||||
{
|
||||
if (function_exists('enum_exists') && $value instanceof BackedEnum) {
|
||||
return $value->value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge an array of bindings into our bindings.
|
||||
*
|
||||
@@ -3085,11 +3366,15 @@ class Builder
|
||||
* @param array $bindings
|
||||
* @return array
|
||||
*/
|
||||
protected function cleanBindings(array $bindings)
|
||||
public function cleanBindings(array $bindings)
|
||||
{
|
||||
return array_values(array_filter($bindings, function ($binding) {
|
||||
return ! $binding instanceof Expression;
|
||||
}));
|
||||
return collect($bindings)
|
||||
->reject(function ($binding) {
|
||||
return $binding instanceof Expression;
|
||||
})
|
||||
->map([$this, 'castBinding'])
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3169,6 +3454,16 @@ class Builder
|
||||
$value instanceof Closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the query.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function clone()
|
||||
{
|
||||
return clone $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the query without the given properties.
|
||||
*
|
||||
@@ -3177,7 +3472,7 @@ class Builder
|
||||
*/
|
||||
public function cloneWithout(array $properties)
|
||||
{
|
||||
return tap(clone $this, function ($clone) use ($properties) {
|
||||
return tap($this->clone(), function ($clone) use ($properties) {
|
||||
foreach ($properties as $property) {
|
||||
$clone->{$property} = null;
|
||||
}
|
||||
@@ -3192,7 +3487,7 @@ class Builder
|
||||
*/
|
||||
public function cloneWithoutBindings(array $except)
|
||||
{
|
||||
return tap(clone $this, function ($clone) use ($except) {
|
||||
return tap($this->clone(), function ($clone) use ($except) {
|
||||
foreach ($except as $type) {
|
||||
$clone->bindings[$type] = [];
|
||||
}
|
||||
@@ -3214,7 +3509,7 @@ class Builder
|
||||
/**
|
||||
* Die and dump the current SQL and bindings.
|
||||
*
|
||||
* @return void
|
||||
* @return never
|
||||
*/
|
||||
public function dd()
|
||||
{
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Query/Expression.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Query/Expression.php
vendored
Normal file → Executable file
76
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php
vendored
Normal file → Executable file
76
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php
vendored
Normal file → Executable file
@@ -19,10 +19,17 @@ class Grammar extends BaseGrammar
|
||||
protected $operators = [];
|
||||
|
||||
/**
|
||||
* The components that make up a select clause.
|
||||
* The grammar specific bitwise operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bitwiseOperators = [];
|
||||
|
||||
/**
|
||||
* The components that make up a select clause.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $selectComponents = [
|
||||
'aggregate',
|
||||
'columns',
|
||||
@@ -45,7 +52,7 @@ class Grammar extends BaseGrammar
|
||||
*/
|
||||
public function compileSelect(Builder $query)
|
||||
{
|
||||
if ($query->unions && $query->aggregate) {
|
||||
if (($query->unions || $query->havings) && $query->aggregate) {
|
||||
return $this->compileUnionAggregate($query);
|
||||
}
|
||||
|
||||
@@ -181,7 +188,7 @@ class Grammar extends BaseGrammar
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected function compileWheres(Builder $query)
|
||||
public function compileWheres(Builder $query)
|
||||
{
|
||||
// Each type of where clauses has its own compiler function which is responsible
|
||||
// for actually creating the where clauses SQL. This helps keep the code nice
|
||||
@@ -250,7 +257,21 @@ class Grammar extends BaseGrammar
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
return $this->wrap($where['column']).' '.$where['operator'].' '.$value;
|
||||
$operator = str_replace('?', '??', $where['operator']);
|
||||
|
||||
return $this->wrap($where['column']).' '.$operator.' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a bitwise operator where clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereBitwise(Builder $query, $where)
|
||||
{
|
||||
return $this->whereBasic($query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +478,7 @@ class Grammar extends BaseGrammar
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where clause comparing two columns..
|
||||
* Compile a where clause comparing two columns.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
@@ -569,7 +590,8 @@ class Grammar extends BaseGrammar
|
||||
$not = $where['not'] ? 'not ' : '';
|
||||
|
||||
return $not.$this->compileJsonContains(
|
||||
$where['column'], $this->parameter($where['value'])
|
||||
$where['column'],
|
||||
$this->parameter($where['value'])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -608,7 +630,9 @@ class Grammar extends BaseGrammar
|
||||
protected function whereJsonLength(Builder $query, $where)
|
||||
{
|
||||
return $this->compileJsonLength(
|
||||
$where['column'], $where['operator'], $this->parameter($where['value'])
|
||||
$where['column'],
|
||||
$where['operator'],
|
||||
$this->parameter($where['value'])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -627,6 +651,18 @@ class Grammar extends BaseGrammar
|
||||
throw new RuntimeException('This database engine does not support JSON length operations.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where fulltext" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
public function whereFullText(Builder $query, $where)
|
||||
{
|
||||
throw new RuntimeException('This database engine does not support fulltext search operations.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "group by" portions of the query.
|
||||
*
|
||||
@@ -993,6 +1029,22 @@ class Grammar extends BaseGrammar
|
||||
return "update {$table} {$joins} set {$columns} {$where}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an "upsert" statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param array $uniqueBy
|
||||
* @param array $update
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
|
||||
{
|
||||
throw new RuntimeException('This database engine does not support upserts.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the bindings for an update statement.
|
||||
*
|
||||
@@ -1266,4 +1318,14 @@ class Grammar extends BaseGrammar
|
||||
{
|
||||
return $this->operators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grammar specific bitwise operators.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBitwiseOperators()
|
||||
{
|
||||
return $this->bitwiseOperators;
|
||||
}
|
||||
}
|
||||
|
||||
61
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php
vendored
Normal file → Executable file
61
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php
vendored
Normal file → Executable file
@@ -10,17 +10,16 @@ class MySqlGrammar extends Grammar
|
||||
/**
|
||||
* The grammar specific operators.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $operators = ['sounds like'];
|
||||
|
||||
/**
|
||||
* Add a "where null" clause to the query.
|
||||
*
|
||||
* @param string|array $columns
|
||||
* @param string $boolean
|
||||
* @param bool $not
|
||||
* @return $this
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNull(Builder $query, $where)
|
||||
{
|
||||
@@ -36,9 +35,9 @@ class MySqlGrammar extends Grammar
|
||||
/**
|
||||
* Add a "where not null" clause to the query.
|
||||
*
|
||||
* @param string|array $columns
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNotNull(Builder $query, $where)
|
||||
{
|
||||
@@ -51,6 +50,30 @@ class MySqlGrammar extends Grammar
|
||||
return parent::whereNotNull($query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where fulltext" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
public function whereFullText(Builder $query, $where)
|
||||
{
|
||||
$columns = $this->columnize($where['columns']);
|
||||
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
$mode = ($where['options']['mode'] ?? []) === 'boolean'
|
||||
? ' in boolean mode'
|
||||
: ' in natural language mode';
|
||||
|
||||
$expanded = ($where['options']['expanded'] ?? []) && ($where['options']['mode'] ?? []) !== 'boolean'
|
||||
? ' with query expansion'
|
||||
: '';
|
||||
|
||||
return "match ({$columns}) against (".$value."{$mode}{$expanded})";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an insert ignore statement into SQL.
|
||||
*
|
||||
@@ -153,6 +176,28 @@ class MySqlGrammar extends Grammar
|
||||
})->implode(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an "upsert" statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param array $uniqueBy
|
||||
* @param array $update
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
|
||||
{
|
||||
$sql = $this->compileInsert($query, $values).' on duplicate key update ';
|
||||
|
||||
$columns = collect($update)->map(function ($value, $key) {
|
||||
return is_numeric($key)
|
||||
? $this->wrap($value).' = values('.$this->wrap($value).')'
|
||||
: $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
|
||||
return $sql.$columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a JSON column being updated using the JSON_SET function.
|
||||
*
|
||||
|
||||
258
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php
vendored
Normal file → Executable file
258
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php
vendored
Normal file → Executable file
@@ -11,16 +11,25 @@ class PostgresGrammar extends Grammar
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $operators = [
|
||||
'=', '<', '>', '<=', '>=', '<>', '!=',
|
||||
'like', 'not like', 'between', 'ilike', 'not ilike',
|
||||
'~', '&', '|', '#', '<<', '>>', '<<=', '>>=',
|
||||
'&&', '@>', '<@', '?', '?|', '?&', '||', '-', '-', '#-',
|
||||
'&&', '@>', '<@', '?', '?|', '?&', '||', '-', '@?', '@@', '#-',
|
||||
'is distinct from', 'is not distinct from',
|
||||
];
|
||||
|
||||
/**
|
||||
* The grammar specific bitwise operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bitwiseOperators = [
|
||||
'~', '&', '|', '#', '<<', '>>', '<<=', '>>=',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
@@ -42,6 +51,22 @@ class PostgresGrammar extends Grammar
|
||||
return parent::whereBasic($query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereBitwise(Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
$operator = str_replace('?', '??', $where['operator']);
|
||||
|
||||
return '('.$this->wrap($where['column']).' '.$operator.' '.$value.')::bool';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where date" clause.
|
||||
*
|
||||
@@ -85,6 +110,71 @@ class PostgresGrammar extends Grammar
|
||||
return 'extract('.$type.' from '.$this->wrap($where['column']).') '.$where['operator'].' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where fulltext" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
public function whereFullText(Builder $query, $where)
|
||||
{
|
||||
$language = $where['options']['language'] ?? 'english';
|
||||
|
||||
if (! in_array($language, $this->validFullTextLanguages())) {
|
||||
$language = 'english';
|
||||
}
|
||||
|
||||
$columns = collect($where['columns'])->map(function ($column) use ($language) {
|
||||
return "to_tsvector('{$language}', {$this->wrap($column)})";
|
||||
})->implode(' || ');
|
||||
|
||||
$mode = 'plainto_tsquery';
|
||||
|
||||
if (($where['options']['mode'] ?? []) === 'phrase') {
|
||||
$mode = 'phraseto_tsquery';
|
||||
}
|
||||
|
||||
if (($where['options']['mode'] ?? []) === 'websearch') {
|
||||
$mode = 'websearch_to_tsquery';
|
||||
}
|
||||
|
||||
return "({$columns}) @@ {$mode}('{$language}', {$this->parameter($where['value'])})";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of valid full text languages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function validFullTextLanguages()
|
||||
{
|
||||
return [
|
||||
'simple',
|
||||
'arabic',
|
||||
'danish',
|
||||
'dutch',
|
||||
'english',
|
||||
'finnish',
|
||||
'french',
|
||||
'german',
|
||||
'hungarian',
|
||||
'indonesian',
|
||||
'irish',
|
||||
'italian',
|
||||
'lithuanian',
|
||||
'nepali',
|
||||
'norwegian',
|
||||
'portuguese',
|
||||
'romanian',
|
||||
'russian',
|
||||
'spanish',
|
||||
'swedish',
|
||||
'tamil',
|
||||
'turkish',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "select *" portion of the query.
|
||||
*
|
||||
@@ -141,6 +231,36 @@ class PostgresGrammar extends Grammar
|
||||
return 'json_array_length(('.$column.')::json) '.$operator.' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $having
|
||||
* @return string
|
||||
*/
|
||||
protected function compileHaving(array $having)
|
||||
{
|
||||
if ($having['type'] === 'Bitwise') {
|
||||
return $this->compileHavingBitwise($having);
|
||||
}
|
||||
|
||||
return parent::compileHaving($having);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a having clause involving a bitwise operator.
|
||||
*
|
||||
* @param array $having
|
||||
* @return string
|
||||
*/
|
||||
protected function compileHavingBitwise($having)
|
||||
{
|
||||
$column = $this->wrap($having['column']);
|
||||
|
||||
$parameter = $this->parameter($having['value']);
|
||||
|
||||
return $having['boolean'].' ('.$column.' '.$having['operator'].' '.$parameter.')::bool';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the lock into SQL.
|
||||
*
|
||||
@@ -218,6 +338,30 @@ class PostgresGrammar extends Grammar
|
||||
})->implode(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an "upsert" statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param array $uniqueBy
|
||||
* @param array $update
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
|
||||
{
|
||||
$sql = $this->compileInsert($query, $values);
|
||||
|
||||
$sql .= ' on conflict ('.$this->columnize($uniqueBy).') do update set ';
|
||||
|
||||
$columns = collect($update)->map(function ($value, $key) {
|
||||
return is_numeric($key)
|
||||
? $this->wrap($value).' = '.$this->wrapValue('excluded').'.'.$this->wrap($value)
|
||||
: $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
|
||||
return $sql.$columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a JSON column being updated using the JSONB_SET function.
|
||||
*
|
||||
@@ -236,6 +380,114 @@ class PostgresGrammar extends Grammar
|
||||
return "{$field} = jsonb_set({$field}::jsonb, {$path}, {$this->parameter($value)})";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an update from statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpdateFrom(Builder $query, $values)
|
||||
{
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
// Each one of the columns in the update statements needs to be wrapped in the
|
||||
// keyword identifiers, also a place-holder needs to be created for each of
|
||||
// the values in the list of bindings so we can make the sets statements.
|
||||
$columns = $this->compileUpdateColumns($query, $values);
|
||||
|
||||
$from = '';
|
||||
|
||||
if (isset($query->joins)) {
|
||||
// When using Postgres, updates with joins list the joined tables in the from
|
||||
// clause, which is different than other systems like MySQL. Here, we will
|
||||
// compile out the tables that are joined and add them to a from clause.
|
||||
$froms = collect($query->joins)->map(function ($join) {
|
||||
return $this->wrapTable($join->table);
|
||||
})->all();
|
||||
|
||||
if (count($froms) > 0) {
|
||||
$from = ' from '.implode(', ', $froms);
|
||||
}
|
||||
}
|
||||
|
||||
$where = $this->compileUpdateWheres($query);
|
||||
|
||||
return trim("update {$table} set {$columns}{$from} {$where}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the additional where clauses for updates with joins.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUpdateWheres(Builder $query)
|
||||
{
|
||||
$baseWheres = $this->compileWheres($query);
|
||||
|
||||
if (! isset($query->joins)) {
|
||||
return $baseWheres;
|
||||
}
|
||||
|
||||
// Once we compile the join constraints, we will either use them as the where
|
||||
// clause or append them to the existing base where clauses. If we need to
|
||||
// strip the leading boolean we will do so when using as the only where.
|
||||
$joinWheres = $this->compileUpdateJoinWheres($query);
|
||||
|
||||
if (trim($baseWheres) == '') {
|
||||
return 'where '.$this->removeLeadingBoolean($joinWheres);
|
||||
}
|
||||
|
||||
return $baseWheres.' '.$joinWheres;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "join" clause where clauses for an update.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUpdateJoinWheres(Builder $query)
|
||||
{
|
||||
$joinWheres = [];
|
||||
|
||||
// Here we will just loop through all of the join constraints and compile them
|
||||
// all out then implode them. This should give us "where" like syntax after
|
||||
// everything has been built and then we will join it to the real wheres.
|
||||
foreach ($query->joins as $join) {
|
||||
foreach ($join->wheres as $where) {
|
||||
$method = "where{$where['type']}";
|
||||
|
||||
$joinWheres[] = $where['boolean'].' '.$this->$method($query, $where);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(' ', $joinWheres);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the bindings for an update statement.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function prepareBindingsForUpdateFrom(array $bindings, array $values)
|
||||
{
|
||||
$values = collect($values)->map(function ($value, $column) {
|
||||
return is_array($value) || ($this->isJsonSelector($column) && ! $this->isExpression($value))
|
||||
? json_encode($value)
|
||||
: $value;
|
||||
})->all();
|
||||
|
||||
$bindingsWithoutWhere = Arr::except($bindings, ['select', 'where']);
|
||||
|
||||
return array_values(
|
||||
array_merge($values, $bindings['where'], Arr::flatten($bindingsWithoutWhere))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an update statement with joins or limit into SQL.
|
||||
*
|
||||
@@ -345,7 +597,7 @@ class PostgresGrammar extends Grammar
|
||||
}
|
||||
|
||||
/**
|
||||
*Wrap the given JSON selector for boolean values.
|
||||
* Wrap the given JSON selector for boolean values.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
|
||||
26
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php
vendored
Normal file → Executable file
26
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php
vendored
Normal file → Executable file
@@ -11,7 +11,7 @@ class SQLiteGrammar extends Grammar
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $operators = [
|
||||
'=', '<', '>', '<=', '>=', '<>', '!=',
|
||||
@@ -182,6 +182,30 @@ class SQLiteGrammar extends Grammar
|
||||
})->implode(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an "upsert" statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param array $uniqueBy
|
||||
* @param array $update
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
|
||||
{
|
||||
$sql = $this->compileInsert($query, $values);
|
||||
|
||||
$sql .= ' on conflict ('.$this->columnize($uniqueBy).') do update set ';
|
||||
|
||||
$columns = collect($update)->map(function ($value, $key) {
|
||||
return is_numeric($key)
|
||||
? $this->wrap($value).' = '.$this->wrapValue('excluded').'.'.$this->wrap($value)
|
||||
: $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
|
||||
return $sql.$columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group the nested JSON columns.
|
||||
*
|
||||
|
||||
146
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
vendored
Normal file → Executable file
146
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
vendored
Normal file → Executable file
@@ -11,7 +11,7 @@ class SqlServerGrammar extends Grammar
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $operators = [
|
||||
'=', '<', '>', '<=', '>=', '!<', '!>', '<>', '!=',
|
||||
@@ -31,15 +31,21 @@ class SqlServerGrammar extends Grammar
|
||||
return parent::compileSelect($query);
|
||||
}
|
||||
|
||||
// If an offset is present on the query, we will need to wrap the query in
|
||||
// a big "ANSI" offset syntax block. This is very nasty compared to the
|
||||
// other database systems but is necessary for implementing features.
|
||||
if (is_null($query->columns)) {
|
||||
$query->columns = ['*'];
|
||||
}
|
||||
|
||||
$components = $this->compileComponents($query);
|
||||
|
||||
if (! empty($components['orders'])) {
|
||||
return parent::compileSelect($query)." offset {$query->offset} rows fetch next {$query->limit} rows only";
|
||||
}
|
||||
|
||||
// If an offset is present on the query, we will need to wrap the query in
|
||||
// a big "ANSI" offset syntax block. This is very nasty compared to the
|
||||
// other database systems but is necessary for implementing features.
|
||||
return $this->compileAnsiOffset(
|
||||
$query, $this->compileComponents($query)
|
||||
$query, $components
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,8 +67,8 @@ class SqlServerGrammar extends Grammar
|
||||
// If there is a limit on the query, but not an offset, we will add the top
|
||||
// clause to the query, which serves as a "limit" type clause within the
|
||||
// SQL Server system similar to the limit keywords available in MySQL.
|
||||
if ($query->limit > 0 && $query->offset <= 0) {
|
||||
$select .= 'top '.$query->limit.' ';
|
||||
if (is_numeric($query->limit) && $query->limit > 0 && $query->offset <= 0) {
|
||||
$select .= 'top '.((int) $query->limit).' ';
|
||||
}
|
||||
|
||||
return $select.$this->columnize($columns);
|
||||
@@ -90,6 +96,22 @@ class SqlServerGrammar extends Grammar
|
||||
return $from;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereBitwise(Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
$operator = str_replace('?', '??', $where['operator']);
|
||||
|
||||
return '('.$this->wrap($where['column']).' '.$operator.' '.$value.') != 0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where date" clause.
|
||||
*
|
||||
@@ -158,6 +180,36 @@ class SqlServerGrammar extends Grammar
|
||||
return '(select count(*) from openjson('.$field.$path.')) '.$operator.' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param array $having
|
||||
* @return string
|
||||
*/
|
||||
protected function compileHaving(array $having)
|
||||
{
|
||||
if ($having['type'] === 'Bitwise') {
|
||||
return $this->compileHavingBitwise($having);
|
||||
}
|
||||
|
||||
return parent::compileHaving($having);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a having clause involving a bitwise operator.
|
||||
*
|
||||
* @param array $having
|
||||
* @return string
|
||||
*/
|
||||
protected function compileHavingBitwise($having)
|
||||
{
|
||||
$column = $this->wrap($having['column']);
|
||||
|
||||
$parameter = $this->parameter($having['value']);
|
||||
|
||||
return $having['boolean'].' ('.$column.' '.$having['operator'].' '.$parameter.') != 0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full ANSI offset clause for the query.
|
||||
*
|
||||
@@ -181,6 +233,10 @@ class SqlServerGrammar extends Grammar
|
||||
|
||||
unset($components['orders']);
|
||||
|
||||
if ($this->queryOrderContainsSubquery($query)) {
|
||||
$query->bindings = $this->sortBindingsForSubqueryOrderBy($query);
|
||||
}
|
||||
|
||||
// Next we need to calculate the constraints that should be placed on the query
|
||||
// to get the right offset and limit from our query but if there is no limit
|
||||
// set we will just handle the offset only since that is all that matters.
|
||||
@@ -200,6 +256,36 @@ class SqlServerGrammar extends Grammar
|
||||
return ", row_number() over ({$orderings}) as row_num";
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the query's order by clauses contain a subquery.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return bool
|
||||
*/
|
||||
protected function queryOrderContainsSubquery($query)
|
||||
{
|
||||
if (! is_array($query->orders)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Arr::first($query->orders, function ($value) {
|
||||
return $this->isExpression($value['column'] ?? null);
|
||||
}, false) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the order bindings to be after the "select" statement to account for an order by subquery.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
protected function sortBindingsForSubqueryOrderBy($query)
|
||||
{
|
||||
return Arr::sort($query->bindings, function ($bindings, $key) {
|
||||
return array_search($key, ['select', 'order', 'from', 'join', 'where', 'groupBy', 'having', 'union', 'unionOrder']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a common table expression for a query.
|
||||
*
|
||||
@@ -222,10 +308,10 @@ class SqlServerGrammar extends Grammar
|
||||
*/
|
||||
protected function compileRowConstraint($query)
|
||||
{
|
||||
$start = $query->offset + 1;
|
||||
$start = (int) $query->offset + 1;
|
||||
|
||||
if ($query->limit > 0) {
|
||||
$finish = $query->offset + $query->limit;
|
||||
$finish = (int) $query->offset + (int) $query->limit;
|
||||
|
||||
return "between {$start} and {$finish}";
|
||||
}
|
||||
@@ -341,6 +427,48 @@ class SqlServerGrammar extends Grammar
|
||||
return "update {$alias} set {$columns} from {$table} {$joins} {$where}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an "upsert" statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param array $uniqueBy
|
||||
* @param array $update
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpsert(Builder $query, array $values, array $uniqueBy, array $update)
|
||||
{
|
||||
$columns = $this->columnize(array_keys(reset($values)));
|
||||
|
||||
$sql = 'merge '.$this->wrapTable($query->from).' ';
|
||||
|
||||
$parameters = collect($values)->map(function ($record) {
|
||||
return '('.$this->parameterize($record).')';
|
||||
})->implode(', ');
|
||||
|
||||
$sql .= 'using (values '.$parameters.') '.$this->wrapTable('laravel_source').' ('.$columns.') ';
|
||||
|
||||
$on = collect($uniqueBy)->map(function ($column) use ($query) {
|
||||
return $this->wrap('laravel_source.'.$column).' = '.$this->wrap($query->from.'.'.$column);
|
||||
})->implode(' and ');
|
||||
|
||||
$sql .= 'on '.$on.' ';
|
||||
|
||||
if ($update) {
|
||||
$update = collect($update)->map(function ($value, $key) {
|
||||
return is_numeric($key)
|
||||
? $this->wrap($value).' = '.$this->wrap('laravel_source.'.$value)
|
||||
: $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
|
||||
$sql .= 'when matched then update set '.$update.' ';
|
||||
}
|
||||
|
||||
$sql .= 'when not matched then insert ('.$columns.') values ('.$columns.');';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the bindings for an update statement.
|
||||
*
|
||||
|
||||
2
vendor/laravel/framework/src/Illuminate/Database/Query/JoinClause.php
vendored
Normal file → Executable file
2
vendor/laravel/framework/src/Illuminate/Database/Query/JoinClause.php
vendored
Normal file → Executable file
@@ -104,7 +104,7 @@ class JoinClause extends Builder
|
||||
*
|
||||
* @param \Closure|string $first
|
||||
* @param string|null $operator
|
||||
* @param string|null $second
|
||||
* @param \Illuminate\Database\Query\Expression|string|null $second
|
||||
* @return \Illuminate\Database\Query\JoinClause
|
||||
*/
|
||||
public function orOn($first, $operator = null, $second = null)
|
||||
|
||||
0
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/PostgresProcessor.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/PostgresProcessor.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/SqlServerProcessor.php
vendored
Normal file → Executable file
0
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/SqlServerProcessor.php
vendored
Normal file → Executable file
14
vendor/laravel/framework/src/Illuminate/Database/README.md
vendored
Normal file → Executable file
14
vendor/laravel/framework/src/Illuminate/Database/README.md
vendored
Normal file → Executable file
@@ -12,14 +12,14 @@ use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
$capsule = new Capsule;
|
||||
|
||||
$capsule->addConnection([
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => 'database',
|
||||
'username' => 'root',
|
||||
'password' => 'password',
|
||||
'charset' => 'utf8',
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => 'database',
|
||||
'username' => 'root',
|
||||
'password' => 'password',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
'prefix' => '',
|
||||
]);
|
||||
|
||||
// Set the event dispatcher used by Eloquent models... (optional)
|
||||
|
||||
21
vendor/laravel/framework/src/Illuminate/Database/SQLiteConnection.php
vendored
Normal file → Executable file
21
vendor/laravel/framework/src/Illuminate/Database/SQLiteConnection.php
vendored
Normal file → Executable file
@@ -3,10 +3,14 @@
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Doctrine\DBAL\Driver\PDOSqlite\Driver as DoctrineDriver;
|
||||
use Doctrine\DBAL\Version;
|
||||
use Illuminate\Database\PDO\SQLiteDriver;
|
||||
use Illuminate\Database\Query\Grammars\SQLiteGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Query\Processors\SQLiteProcessor;
|
||||
use Illuminate\Database\Schema\Grammars\SQLiteGrammar as SchemaGrammar;
|
||||
use Illuminate\Database\Schema\SQLiteBuilder;
|
||||
use Illuminate\Database\Schema\SqliteSchemaState;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class SQLiteConnection extends Connection
|
||||
{
|
||||
@@ -68,6 +72,19 @@ class SQLiteConnection extends Connection
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema state for the connection.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem|null $files
|
||||
* @param callable|null $processFactory
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function getSchemaState(Filesystem $files = null, callable $processFactory = null)
|
||||
{
|
||||
return new SqliteSchemaState($this, $files, $processFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
@@ -81,11 +98,11 @@ class SQLiteConnection extends Connection
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOSqlite\Driver
|
||||
* @return \Doctrine\DBAL\Driver\PDOSqlite\Driver|\Illuminate\Database\PDO\SQLiteDriver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
return class_exists(Version::class) ? new DoctrineDriver : new SQLiteDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
196
vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php
vendored
Normal file → Executable file
196
vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php
vendored
Normal file → Executable file
@@ -71,6 +71,13 @@ class Blueprint
|
||||
*/
|
||||
public $temporary = false;
|
||||
|
||||
/**
|
||||
* The column to add new columns after.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $after;
|
||||
|
||||
/**
|
||||
* Create a new schema blueprint.
|
||||
*
|
||||
@@ -201,7 +208,7 @@ class Blueprint
|
||||
protected function addFluentIndexes()
|
||||
{
|
||||
foreach ($this->columns as $column) {
|
||||
foreach (['primary', 'unique', 'index', 'spatialIndex'] as $index) {
|
||||
foreach (['primary', 'unique', 'index', 'fulltext', 'fullText', 'spatialIndex'] as $index) {
|
||||
// If the index has been specified on the given column, but is simply equal
|
||||
// to "true" (boolean), no name has been specified for this index so the
|
||||
// index method can be called without a name and it will generate one.
|
||||
@@ -255,7 +262,7 @@ class Blueprint
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function creating()
|
||||
public function creating()
|
||||
{
|
||||
return collect($this->commands)->contains(function ($command) {
|
||||
return $command->name === 'create';
|
||||
@@ -360,6 +367,17 @@ class Blueprint
|
||||
return $this->dropIndexCommand('dropIndex', 'index', $index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the given fulltext index should be dropped.
|
||||
*
|
||||
* @param string|array $index
|
||||
* @return \Illuminate\Support\Fluent
|
||||
*/
|
||||
public function dropFullText($index)
|
||||
{
|
||||
return $this->dropIndexCommand('dropFullText', 'fulltext', $index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the given spatial index should be dropped.
|
||||
*
|
||||
@@ -382,6 +400,19 @@ class Blueprint
|
||||
return $this->dropIndexCommand('dropForeign', 'foreign', $index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the given column and foreign key should be dropped.
|
||||
*
|
||||
* @param string $column
|
||||
* @return \Illuminate\Support\Fluent
|
||||
*/
|
||||
public function dropConstrainedForeignId($column)
|
||||
{
|
||||
$this->dropForeign([$column]);
|
||||
|
||||
return $this->dropColumn($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the given indexes should be renamed.
|
||||
*
|
||||
@@ -510,6 +541,19 @@ class Blueprint
|
||||
return $this->indexCommand('index', $columns, $name, $algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify an fulltext for the table.
|
||||
*
|
||||
* @param string|array $columns
|
||||
* @param string|null $name
|
||||
* @param string|null $algorithm
|
||||
* @return \Illuminate\Support\Fluent
|
||||
*/
|
||||
public function fullText($columns, $name = null, $algorithm = null)
|
||||
{
|
||||
return $this->indexCommand('fulltext', $columns, $name, $algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a spatial index for the table.
|
||||
*
|
||||
@@ -657,6 +701,17 @@ class Blueprint
|
||||
return $this->addColumn('string', $column, compact('length'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new tiny text column on the table.
|
||||
*
|
||||
* @param string $column
|
||||
* @return \Illuminate\Database\Schema\ColumnDefinition
|
||||
*/
|
||||
public function tinyText($column)
|
||||
{
|
||||
return $this->addColumn('tinyText', $column);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new text column on the table.
|
||||
*
|
||||
@@ -823,14 +878,30 @@ class Blueprint
|
||||
*/
|
||||
public function foreignId($column)
|
||||
{
|
||||
$this->columns[] = $column = new ForeignIdColumnDefinition($this, [
|
||||
return $this->addColumnDefinition(new ForeignIdColumnDefinition($this, [
|
||||
'type' => 'bigInteger',
|
||||
'name' => $column,
|
||||
'autoIncrement' => false,
|
||||
'unsigned' => true,
|
||||
]);
|
||||
]));
|
||||
}
|
||||
|
||||
return $column;
|
||||
/**
|
||||
* Create a foreign ID column for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model|string $model
|
||||
* @param string|null $column
|
||||
* @return \Illuminate\Database\Schema\ForeignIdColumnDefinition
|
||||
*/
|
||||
public function foreignIdFor($model, $column = null)
|
||||
{
|
||||
if (is_string($model)) {
|
||||
$model = new $model;
|
||||
}
|
||||
|
||||
return $model->getKeyType() === 'int' && $model->getIncrementing()
|
||||
? $this->foreignId($column ?: $model->getForeignKey())
|
||||
: $this->foreignUuid($column ?: $model->getForeignKey());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1158,10 +1229,10 @@ class Blueprint
|
||||
*/
|
||||
public function foreignUuid($column)
|
||||
{
|
||||
return $this->columns[] = new ForeignIdColumnDefinition($this, [
|
||||
return $this->addColumnDefinition(new ForeignIdColumnDefinition($this, [
|
||||
'type' => 'uuid',
|
||||
'name' => $column,
|
||||
]);
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1307,11 +1378,11 @@ class Blueprint
|
||||
*/
|
||||
public function morphs($name, $indexName = null)
|
||||
{
|
||||
$this->string("{$name}_type");
|
||||
|
||||
$this->unsignedBigInteger("{$name}_id");
|
||||
|
||||
$this->index(["{$name}_type", "{$name}_id"], $indexName);
|
||||
if (Builder::$defaultMorphKeyType === 'uuid') {
|
||||
$this->uuidMorphs($name, $indexName);
|
||||
} else {
|
||||
$this->numericMorphs($name, $indexName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1322,6 +1393,38 @@ class Blueprint
|
||||
* @return void
|
||||
*/
|
||||
public function nullableMorphs($name, $indexName = null)
|
||||
{
|
||||
if (Builder::$defaultMorphKeyType === 'uuid') {
|
||||
$this->nullableUuidMorphs($name, $indexName);
|
||||
} else {
|
||||
$this->nullableNumericMorphs($name, $indexName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the proper columns for a polymorphic table using numeric IDs (incremental).
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $indexName
|
||||
* @return void
|
||||
*/
|
||||
public function numericMorphs($name, $indexName = null)
|
||||
{
|
||||
$this->string("{$name}_type");
|
||||
|
||||
$this->unsignedBigInteger("{$name}_id");
|
||||
|
||||
$this->index(["{$name}_type", "{$name}_id"], $indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nullable columns for a polymorphic table using numeric IDs (incremental).
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $indexName
|
||||
* @return void
|
||||
*/
|
||||
public function nullableNumericMorphs($name, $indexName = null)
|
||||
{
|
||||
$this->string("{$name}_type")->nullable();
|
||||
|
||||
@@ -1441,11 +1544,44 @@ class Blueprint
|
||||
*/
|
||||
public function addColumn($type, $name, array $parameters = [])
|
||||
{
|
||||
$this->columns[] = $column = new ColumnDefinition(
|
||||
return $this->addColumnDefinition(new ColumnDefinition(
|
||||
array_merge(compact('type', 'name'), $parameters)
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
return $column;
|
||||
/**
|
||||
* Add a new column definition to the blueprint.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\ColumnDefinition $definition
|
||||
* @return \Illuminate\Database\Schema\ColumnDefinition
|
||||
*/
|
||||
protected function addColumnDefinition($definition)
|
||||
{
|
||||
$this->columns[] = $definition;
|
||||
|
||||
if ($this->after) {
|
||||
$definition->after($this->after);
|
||||
|
||||
$this->after = $definition->name;
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the columns from the callback after the given column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function after($column, Closure $callback)
|
||||
{
|
||||
$this->after = $column;
|
||||
|
||||
$callback($this);
|
||||
|
||||
$this->after = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1542,4 +1678,34 @@ class Blueprint
|
||||
return (bool) $column->change;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the blueprint has auto-increment columns.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAutoIncrementColumn()
|
||||
{
|
||||
return ! is_null(collect($this->getAddedColumns())->first(function ($column) {
|
||||
return $column->autoIncrement === true;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auto-increment column starting values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function autoIncrementingStartingValues()
|
||||
{
|
||||
if (! $this->hasAutoIncrementColumn()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return collect($this->getAddedColumns())->mapWithKeys(function ($column) {
|
||||
return $column->autoIncrement === true
|
||||
? [$column->name => $column->get('startingValue', $column->get('from'))]
|
||||
: [$column->name => null];
|
||||
})->filter()->all();
|
||||
}
|
||||
}
|
||||
|
||||
98
vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php
vendored
Normal file → Executable file
98
vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php
vendored
Normal file → Executable file
@@ -3,10 +3,10 @@
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Closure;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Connection;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use RuntimeException;
|
||||
|
||||
class Builder
|
||||
{
|
||||
@@ -38,6 +38,13 @@ class Builder
|
||||
*/
|
||||
public static $defaultStringLength = 255;
|
||||
|
||||
/**
|
||||
* The default relationship morph key type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $defaultMorphKeyType = 'int';
|
||||
|
||||
/**
|
||||
* Create a new database Schema manager.
|
||||
*
|
||||
@@ -61,6 +68,59 @@ class Builder
|
||||
static::$defaultStringLength = $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default morph key type for migrations.
|
||||
*
|
||||
* @param string $type
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function defaultMorphKeyType(string $type)
|
||||
{
|
||||
if (! in_array($type, ['int', 'uuid'])) {
|
||||
throw new InvalidArgumentException("Morph key type must be 'int' or 'uuid'.");
|
||||
}
|
||||
|
||||
static::$defaultMorphKeyType = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default morph key type for migrations to UUIDs.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function morphUsingUuids()
|
||||
{
|
||||
return static::defaultMorphKeyType('uuid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a database in the schema.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function createDatabase($name)
|
||||
{
|
||||
throw new LogicException('This database driver does not support creating databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop a database from the schema if the database exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function dropDatabaseIfExists($name)
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given table exists.
|
||||
*
|
||||
@@ -193,6 +253,20 @@ class Builder
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop columns from a table schema.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string|array $columns
|
||||
* @return void
|
||||
*/
|
||||
public function dropColumns($table, $columns)
|
||||
{
|
||||
$this->table($table, function (Blueprint $blueprint) use ($columns) {
|
||||
$blueprint->dropColumn($columns);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop all tables from the database.
|
||||
*
|
||||
@@ -307,7 +381,7 @@ class Builder
|
||||
return call_user_func($this->resolver, $table, $callback, $prefix);
|
||||
}
|
||||
|
||||
return new Blueprint($table, $callback, $prefix);
|
||||
return Container::getInstance()->make(Blueprint::class, compact('table', 'callback', 'prefix'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,26 +391,10 @@ class Builder
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return void
|
||||
*
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function registerCustomDoctrineType($class, $name, $type)
|
||||
{
|
||||
if (! $this->connection->isDoctrineAvailable()) {
|
||||
throw new RuntimeException(
|
||||
'Registering a custom Doctrine type requires Doctrine DBAL (doctrine/dbal).'
|
||||
);
|
||||
}
|
||||
|
||||
if (! Type::hasType($name)) {
|
||||
Type::addType($name, $class);
|
||||
|
||||
$this->connection
|
||||
->getDoctrineSchemaManager()
|
||||
->getDatabasePlatform()
|
||||
->registerDoctrineTypeMapping($type, $name);
|
||||
}
|
||||
$this->connection->registerDoctrineType($class, $name, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Illuminate\Database\Schema;
|
||||
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Support\Fluent;
|
||||
|
||||
/**
|
||||
@@ -12,21 +11,26 @@ use Illuminate\Support\Fluent;
|
||||
* @method $this change() Change the column
|
||||
* @method $this charset(string $charset) Specify a character set for the column (MySQL)
|
||||
* @method $this collation(string $collation) Specify a collation for the column (MySQL/PostgreSQL/SQL Server)
|
||||
* @method $this comment(string $comment) Add a comment to the column (MySQL)
|
||||
* @method $this comment(string $comment) Add a comment to the column (MySQL/PostgreSQL)
|
||||
* @method $this default(mixed $value) Specify a "default" value for the column
|
||||
* @method $this first() Place the column "first" in the table (MySQL)
|
||||
* @method $this from(int $startingValue) Set the starting value of an auto-incrementing field (MySQL / PostgreSQL)
|
||||
* @method $this generatedAs(string|Expression $expression = null) Create a SQL compliant identity column (PostgreSQL)
|
||||
* @method $this index(string $indexName = null) Add an index
|
||||
* @method $this invisible() Specify that the column should be invisible to "SELECT *" (MySQL)
|
||||
* @method $this nullable(bool $value = true) Allow NULL values to be inserted into the column
|
||||
* @method $this persisted() Mark the computed generated column as persistent (SQL Server)
|
||||
* @method $this primary() Add a primary index
|
||||
* @method $this spatialIndex() Add a spatial index
|
||||
* @method $this storedAs(string $expression) Create a stored generated column (MySQL)
|
||||
* @method $this fulltext(string $indexName = null) Add a fulltext index
|
||||
* @method $this spatialIndex(string $indexName = null) Add a spatial index
|
||||
* @method $this startingValue(int $startingValue) Set the starting value of an auto-incrementing field (MySQL/PostgreSQL)
|
||||
* @method $this storedAs(string $expression) Create a stored generated column (MySQL/PostgreSQL/SQLite)
|
||||
* @method $this type(string $type) Specify a type for the column
|
||||
* @method $this unique(string $indexName = null) Add a unique index
|
||||
* @method $this unsigned() Set the INTEGER column as UNSIGNED (MySQL)
|
||||
* @method $this useCurrent() Set the TIMESTAMP column to use CURRENT_TIMESTAMP as default value
|
||||
* @method $this virtualAs(string $expression) Create a virtual generated column (MySQL)
|
||||
* @method $this useCurrentOnUpdate() Set the TIMESTAMP column to use CURRENT_TIMESTAMP when updating (MySQL)
|
||||
* @method $this virtualAs(string $expression) Create a virtual generated column (MySQL/PostgreSQL/SQLite)
|
||||
*/
|
||||
class ColumnDefinition extends Fluent
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ class ForeignIdColumnDefinition extends ColumnDefinition
|
||||
*
|
||||
* @param string|null $table
|
||||
* @param string $column
|
||||
* @return \Illuminate\Support\Fluent|\Illuminate\Database\Schema\ForeignKeyDefinition
|
||||
* @return \Illuminate\Database\Schema\ForeignKeyDefinition
|
||||
*/
|
||||
public function constrained($table = null, $column = 'id')
|
||||
{
|
||||
@@ -43,7 +43,7 @@ class ForeignIdColumnDefinition extends ColumnDefinition
|
||||
* Specify which column this foreign ID references on another table.
|
||||
*
|
||||
* @param string $column
|
||||
* @return \Illuminate\Support\Fluent|\Illuminate\Database\Schema\ForeignKeyDefinition
|
||||
* @return \Illuminate\Database\Schema\ForeignKeyDefinition
|
||||
*/
|
||||
public function references($column)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,16 @@ class ForeignKeyDefinition extends Fluent
|
||||
return $this->onUpdate('cascade');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that updates should be restricted.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function restrictOnUpdate()
|
||||
{
|
||||
return $this->onUpdate('restrict');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should cascade.
|
||||
*
|
||||
@@ -34,6 +44,16 @@ class ForeignKeyDefinition extends Fluent
|
||||
return $this->onDelete('cascade');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should be restricted.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function restrictOnDelete()
|
||||
{
|
||||
return $this->onDelete('restrict');
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that deletes should set the foreign key value to null.
|
||||
*
|
||||
|
||||
@@ -198,6 +198,7 @@ class ChangeColumn
|
||||
'binary',
|
||||
'boolean',
|
||||
'date',
|
||||
'dateTime',
|
||||
'decimal',
|
||||
'double',
|
||||
'float',
|
||||
|
||||
54
vendor/laravel/framework/src/Illuminate/Database/Schema/Grammars/Grammar.php
vendored
Normal file → Executable file
54
vendor/laravel/framework/src/Illuminate/Database/Schema/Grammars/Grammar.php
vendored
Normal file → Executable file
@@ -9,6 +9,7 @@ use Illuminate\Database\Grammar as BaseGrammar;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Fluent;
|
||||
use LogicException;
|
||||
use RuntimeException;
|
||||
|
||||
abstract class Grammar extends BaseGrammar
|
||||
@@ -27,6 +28,33 @@ abstract class Grammar extends BaseGrammar
|
||||
*/
|
||||
protected $fluentCommands = [];
|
||||
|
||||
/**
|
||||
* Compile a create database command.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function compileCreateDatabase($name, $connection)
|
||||
{
|
||||
throw new LogicException('This database driver does not support creating databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a drop database if exists command.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function compileDropDatabaseIfExists($name)
|
||||
{
|
||||
throw new LogicException('This database driver does not support dropping databases.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a rename column command.
|
||||
*
|
||||
@@ -55,6 +83,32 @@ abstract class Grammar extends BaseGrammar
|
||||
return ChangeColumn::compile($this, $blueprint, $command, $connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a fulltext index key command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function compileFulltext(Blueprint $blueprint, Fluent $command)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support fulltext index creation.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a drop fulltext index command.
|
||||
*
|
||||
* @param \Illuminate\Database\Schema\Blueprint $blueprint
|
||||
* @param \Illuminate\Support\Fluent $command
|
||||
* @return string
|
||||
*/
|
||||
public function compileDropFullText(Blueprint $blueprint, Fluent $command)
|
||||
{
|
||||
throw new RuntimeException('This database driver does not support fulltext index creation.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a foreign key command.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user