Pressroom template verwijderd, website naar root van repo
This commit is contained in:
201
vendor/laravel/framework/src/Illuminate/Database/Capsule/Manager.php
vendored
Executable file
201
vendor/laravel/framework/src/Illuminate/Database/Capsule/Manager.php
vendored
Executable file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Capsule;
|
||||
|
||||
use PDO;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\DatabaseManager;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Support\Traits\CapsuleManagerTrait;
|
||||
use Illuminate\Database\Eloquent\Model as Eloquent;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
|
||||
class Manager
|
||||
{
|
||||
use CapsuleManagerTrait;
|
||||
|
||||
/**
|
||||
* The database manager instance.
|
||||
*
|
||||
* @var \Illuminate\Database\DatabaseManager
|
||||
*/
|
||||
protected $manager;
|
||||
|
||||
/**
|
||||
* Create a new database capsule manager.
|
||||
*
|
||||
* @param \Illuminate\Container\Container|null $container
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container = null)
|
||||
{
|
||||
$this->setupContainer($container ?: new Container);
|
||||
|
||||
// Once we have the container setup, we will setup the default configuration
|
||||
// options in the container "config" binding. This will make the database
|
||||
// manager work correctly out of the box without extreme configuration.
|
||||
$this->setupDefaultConfiguration();
|
||||
|
||||
$this->setupManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the default database configuration options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupDefaultConfiguration()
|
||||
{
|
||||
$this->container['config']['database.fetch'] = PDO::FETCH_OBJ;
|
||||
|
||||
$this->container['config']['database.default'] = 'default';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the database manager instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setupManager()
|
||||
{
|
||||
$factory = new ConnectionFactory($this->container);
|
||||
|
||||
$this->manager = new DatabaseManager($this->container, $factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a connection instance from the global manager.
|
||||
*
|
||||
* @param string $connection
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public static function connection($connection = null)
|
||||
{
|
||||
return static::$instance->getConnection($connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fluent query builder instance.
|
||||
*
|
||||
* @param string $table
|
||||
* @param string $connection
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public static function table($table, $connection = null)
|
||||
{
|
||||
return static::$instance->connection($connection)->table($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a schema builder instance.
|
||||
*
|
||||
* @param string $connection
|
||||
* @return \Illuminate\Database\Schema\Builder
|
||||
*/
|
||||
public static function schema($connection = null)
|
||||
{
|
||||
return static::$instance->connection($connection)->getSchemaBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a registered connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function getConnection($name = null)
|
||||
{
|
||||
return $this->manager->connection($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a connection with the manager.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function addConnection(array $config, $name = 'default')
|
||||
{
|
||||
$connections = $this->container['config']['database.connections'];
|
||||
|
||||
$connections[$name] = $config;
|
||||
|
||||
$this->container['config']['database.connections'] = $connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap Eloquent so it is ready for usage.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function bootEloquent()
|
||||
{
|
||||
Eloquent::setConnectionResolver($this->manager);
|
||||
|
||||
// If we have an event dispatcher instance, we will go ahead and register it
|
||||
// with the Eloquent ORM, allowing for model callbacks while creating and
|
||||
// updating "model" instances; however, it is not necessary to operate.
|
||||
if ($dispatcher = $this->getEventDispatcher()) {
|
||||
Eloquent::setEventDispatcher($dispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fetch mode for the database connections.
|
||||
*
|
||||
* @param int $fetchMode
|
||||
* @return $this
|
||||
*/
|
||||
public function setFetchMode($fetchMode)
|
||||
{
|
||||
$this->container['config']['database.fetch'] = $fetchMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database manager instance.
|
||||
*
|
||||
* @return \Illuminate\Database\DatabaseManager
|
||||
*/
|
||||
public function getDatabaseManager()
|
||||
{
|
||||
return $this->manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current event dispatcher instance.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Events\Dispatcher|null
|
||||
*/
|
||||
public function getEventDispatcher()
|
||||
{
|
||||
if ($this->container->bound('events')) {
|
||||
return $this->container['events'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event dispatcher instance to be used by connections.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function setEventDispatcher(Dispatcher $dispatcher)
|
||||
{
|
||||
$this->container->instance('events', $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass methods to the default connection.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
return static::connection()->$method(...$parameters);
|
||||
}
|
||||
}
|
||||
148
vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php
vendored
Normal file
148
vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Concerns;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
trait BuildsQueries
|
||||
{
|
||||
/**
|
||||
* Chunk the results of the query.
|
||||
*
|
||||
* @param int $count
|
||||
* @param callable $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function chunk($count, callable $callback)
|
||||
{
|
||||
$this->enforceOrderBy();
|
||||
|
||||
$page = 1;
|
||||
|
||||
do {
|
||||
// We'll execute the query for the given page and get the results. If there are
|
||||
// no results we can just break and return from here. When there are results
|
||||
// we will call the callback with the current chunk of these results here.
|
||||
$results = $this->forPage($page, $count)->get();
|
||||
|
||||
$countResults = $results->count();
|
||||
|
||||
if ($countResults == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$page++;
|
||||
} while ($countResults == $count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callback over each item while chunking.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
public function each(callable $callback, $count = 1000)
|
||||
{
|
||||
return $this->chunk($count, function ($results) use ($callback) {
|
||||
foreach ($results as $key => $value) {
|
||||
if ($callback($value, $key) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return mixed
|
||||
*/
|
||||
public function first($columns = ['*'])
|
||||
{
|
||||
return $this->take(1)->get($columns)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback's query changes if the given "value" is true.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param callable $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function when($value, $callback, $default = null)
|
||||
{
|
||||
if ($value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
} elseif ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the callback's query changes if the given "value" is false.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param callable $callback
|
||||
* @param callable $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function unless($value, $callback, $default = null)
|
||||
{
|
||||
if (! $value) {
|
||||
return $callback($this, $value) ?: $this;
|
||||
} elseif ($default) {
|
||||
return $default($this, $value) ?: $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new length-aware paginator instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $items
|
||||
* @param int $total
|
||||
* @param int $perPage
|
||||
* @param int $currentPage
|
||||
* @param array $options
|
||||
* @return \Illuminate\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
protected function paginator($items, $total, $perPage, $currentPage, $options)
|
||||
{
|
||||
return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
|
||||
'items', 'total', 'perPage', 'currentPage', 'options'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new simple paginator instance.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $items
|
||||
* @param int $perPage
|
||||
* @param int $currentPage
|
||||
* @param array $options
|
||||
* @return \Illuminate\Pagination\Paginator
|
||||
*/
|
||||
protected function simplePaginator($items, $perPage, $currentPage, $options)
|
||||
{
|
||||
return Container::getInstance()->makeWith(Paginator::class, compact(
|
||||
'items', 'perPage', 'currentPage', 'options'
|
||||
));
|
||||
}
|
||||
}
|
||||
219
vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php
vendored
Normal file
219
vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
|
||||
trait ManagesTransactions
|
||||
{
|
||||
/**
|
||||
* Execute a Closure within a transaction.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param int $attempts
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception|\Throwable
|
||||
*/
|
||||
public function transaction(Closure $callback, $attempts = 1)
|
||||
{
|
||||
for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
|
||||
$this->beginTransaction();
|
||||
|
||||
// We'll simply execute the given callback within a try / catch block and if we
|
||||
// catch any exception we can rollback this transaction so that none of this
|
||||
// gets actually persisted to a database or stored in a permanent fashion.
|
||||
try {
|
||||
return tap($callback($this), function ($result) {
|
||||
$this->commit();
|
||||
});
|
||||
}
|
||||
|
||||
// If we catch an exception we'll rollback this transaction and try again if we
|
||||
// are not out of attempts. If we are out of attempts we will just throw the
|
||||
// exception back out and let the developer handle an uncaught exceptions.
|
||||
catch (Exception $e) {
|
||||
$this->handleTransactionException(
|
||||
$e, $currentAttempt, $attempts
|
||||
);
|
||||
} catch (Throwable $e) {
|
||||
$this->rollBack();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception encountered when running a transacted statement.
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @param int $currentAttempt
|
||||
* @param int $maxAttempts
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function handleTransactionException($e, $currentAttempt, $maxAttempts)
|
||||
{
|
||||
// On a deadlock, MySQL rolls back the entire transaction so we can't just
|
||||
// retry the query. We have to throw this exception all the way out and
|
||||
// let the developer handle it in another way. We will decrement too.
|
||||
if ($this->causedByDeadlock($e) &&
|
||||
$this->transactions > 1) {
|
||||
--$this->transactions;
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// If there was an exception we will rollback this transaction and then we
|
||||
// can check if we have exceeded the maximum attempt count for this and
|
||||
// if we haven't we will return and try this query again in our loop.
|
||||
$this->rollBack();
|
||||
|
||||
if ($this->causedByDeadlock($e) &&
|
||||
$currentAttempt < $maxAttempts) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new database transaction.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
$this->createTransaction();
|
||||
|
||||
++$this->transactions;
|
||||
|
||||
$this->fireConnectionEvent('beganTransaction');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transaction within the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function createTransaction()
|
||||
{
|
||||
if ($this->transactions == 0) {
|
||||
try {
|
||||
$this->getPdo()->beginTransaction();
|
||||
} catch (Exception $e) {
|
||||
$this->handleBeginTransactionException($e);
|
||||
}
|
||||
} elseif ($this->transactions >= 1 && $this->queryGrammar->supportsSavepoints()) {
|
||||
$this->createSavepoint();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a save point within the database.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function createSavepoint()
|
||||
{
|
||||
$this->getPdo()->exec(
|
||||
$this->queryGrammar->compileSavepoint('trans'.($this->transactions + 1))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception from a transaction beginning.
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function handleBeginTransactionException($e)
|
||||
{
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
$this->reconnect();
|
||||
|
||||
$this->pdo->beginTransaction();
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the active database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if ($this->transactions == 1) {
|
||||
$this->getPdo()->commit();
|
||||
}
|
||||
|
||||
$this->transactions = max(0, $this->transactions - 1);
|
||||
|
||||
$this->fireConnectionEvent('committed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the active database transaction.
|
||||
*
|
||||
* @param int|null $toLevel
|
||||
* @return void
|
||||
*/
|
||||
public function rollBack($toLevel = null)
|
||||
{
|
||||
// We allow developers to rollback to a certain transaction level. We will verify
|
||||
// that this given transaction level is valid before attempting to rollback to
|
||||
// that level. If it's not we will just return out and not attempt anything.
|
||||
$toLevel = is_null($toLevel)
|
||||
? $this->transactions - 1
|
||||
: $toLevel;
|
||||
|
||||
if ($toLevel < 0 || $toLevel >= $this->transactions) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, we will actually perform this rollback within this database and fire the
|
||||
// rollback event. We will also set the current transaction level to the given
|
||||
// level that was passed into this method so it will be right from here out.
|
||||
$this->performRollBack($toLevel);
|
||||
|
||||
$this->transactions = $toLevel;
|
||||
|
||||
$this->fireConnectionEvent('rollingBack');
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a rollback within the database.
|
||||
*
|
||||
* @param int $toLevel
|
||||
* @return void
|
||||
*/
|
||||
protected function performRollBack($toLevel)
|
||||
{
|
||||
if ($toLevel == 0) {
|
||||
$this->getPdo()->rollBack();
|
||||
} elseif ($this->queryGrammar->supportsSavepoints()) {
|
||||
$this->getPdo()->exec(
|
||||
$this->queryGrammar->compileSavepointRollBack('trans'.($toLevel + 1))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of active transactions.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function transactionLevel()
|
||||
{
|
||||
return $this->transactions;
|
||||
}
|
||||
}
|
||||
1203
vendor/laravel/framework/src/Illuminate/Database/Connection.php
vendored
Executable file
1203
vendor/laravel/framework/src/Illuminate/Database/Connection.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
150
vendor/laravel/framework/src/Illuminate/Database/ConnectionInterface.php
vendored
Executable file
150
vendor/laravel/framework/src/Illuminate/Database/ConnectionInterface.php
vendored
Executable file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Closure;
|
||||
|
||||
interface ConnectionInterface
|
||||
{
|
||||
/**
|
||||
* Begin a fluent query against a database table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function table($table);
|
||||
|
||||
/**
|
||||
* Get a new raw query expression.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Query\Expression
|
||||
*/
|
||||
public function raw($value);
|
||||
|
||||
/**
|
||||
* Run a select statement and return a single result.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return mixed
|
||||
*/
|
||||
public function selectOne($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run a select statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return array
|
||||
*/
|
||||
public function select($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run an insert statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return bool
|
||||
*/
|
||||
public function insert($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run an update statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return int
|
||||
*/
|
||||
public function update($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run a delete statement against the database.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return int
|
||||
*/
|
||||
public function delete($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Execute an SQL statement and return the boolean result.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return bool
|
||||
*/
|
||||
public function statement($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run an SQL statement and get the number of rows affected.
|
||||
*
|
||||
* @param string $query
|
||||
* @param array $bindings
|
||||
* @return int
|
||||
*/
|
||||
public function affectingStatement($query, $bindings = []);
|
||||
|
||||
/**
|
||||
* Run a raw, unprepared query against the PDO connection.
|
||||
*
|
||||
* @param string $query
|
||||
* @return bool
|
||||
*/
|
||||
public function unprepared($query);
|
||||
|
||||
/**
|
||||
* Prepare the query bindings for execution.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @return array
|
||||
*/
|
||||
public function prepareBindings(array $bindings);
|
||||
|
||||
/**
|
||||
* Execute a Closure within a transaction.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param int $attempts
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function transaction(Closure $callback, $attempts = 1);
|
||||
|
||||
/**
|
||||
* Start a new database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function beginTransaction();
|
||||
|
||||
/**
|
||||
* Commit the active database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function commit();
|
||||
|
||||
/**
|
||||
* Rollback the active database transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rollBack();
|
||||
|
||||
/**
|
||||
* Get the number of active transactions.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function transactionLevel();
|
||||
|
||||
/**
|
||||
* Execute the given callback in "dry run" mode.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return array
|
||||
*/
|
||||
public function pretend(Closure $callback);
|
||||
}
|
||||
92
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolver.php
vendored
Executable file
92
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolver.php
vendored
Executable file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
class ConnectionResolver implements ConnectionResolverInterface
|
||||
{
|
||||
/**
|
||||
* All of the registered connections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $connections = [];
|
||||
|
||||
/**
|
||||
* The default connection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $default;
|
||||
|
||||
/**
|
||||
* Create a new connection resolver instance.
|
||||
*
|
||||
* @param array $connections
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $connections = [])
|
||||
{
|
||||
foreach ($connections as $name => $connection) {
|
||||
$this->addConnection($name, $connection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a database connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
public function connection($name = null)
|
||||
{
|
||||
if (is_null($name)) {
|
||||
$name = $this->getDefaultConnection();
|
||||
}
|
||||
|
||||
return $this->connections[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a connection to the resolver.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||
* @return void
|
||||
*/
|
||||
public function addConnection($name, ConnectionInterface $connection)
|
||||
{
|
||||
$this->connections[$name] = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a connection has been registered.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasConnection($name)
|
||||
{
|
||||
return isset($this->connections[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultConnection()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultConnection($name)
|
||||
{
|
||||
$this->default = $name;
|
||||
}
|
||||
}
|
||||
29
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolverInterface.php
vendored
Executable file
29
vendor/laravel/framework/src/Illuminate/Database/ConnectionResolverInterface.php
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
interface ConnectionResolverInterface
|
||||
{
|
||||
/**
|
||||
* Get a database connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
public function connection($name = null);
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultConnection();
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultConnection($name);
|
||||
}
|
||||
288
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php
vendored
Executable file
288
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php
vendored
Executable file
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDOException;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\MySqlConnection;
|
||||
use Illuminate\Database\SQLiteConnection;
|
||||
use Illuminate\Database\PostgresConnection;
|
||||
use Illuminate\Database\SqlServerConnection;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
|
||||
class ConnectionFactory
|
||||
{
|
||||
/**
|
||||
* The IoC container instance.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new connection factory instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a PDO connection based on the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function make(array $config, $name = null)
|
||||
{
|
||||
$config = $this->parseConfig($config, $name);
|
||||
|
||||
if (isset($config['read'])) {
|
||||
return $this->createReadWriteConnection($config);
|
||||
}
|
||||
|
||||
return $this->createSingleConnection($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and prepare the database configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function parseConfig(array $config, $name)
|
||||
{
|
||||
return Arr::add(Arr::add($config, 'prefix', ''), 'name', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single database connection instance.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function createSingleConnection(array $config)
|
||||
{
|
||||
$pdo = $this->createPdoResolver($config);
|
||||
|
||||
return $this->createConnection(
|
||||
$config['driver'], $pdo, $config['database'], $config['prefix'], $config
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single database connection instance.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function createReadWriteConnection(array $config)
|
||||
{
|
||||
$connection = $this->createSingleConnection($this->getWriteConfig($config));
|
||||
|
||||
return $connection->setReadPdo($this->createReadPdo($config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PDO instance for reading.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createReadPdo(array $config)
|
||||
{
|
||||
return $this->createPdoResolver($this->getReadConfig($config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read configuration for a read / write connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function getReadConfig(array $config)
|
||||
{
|
||||
return $this->mergeReadWriteConfig(
|
||||
$config, $this->getReadWriteConfig($config, 'read')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read configuration for a read / write connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function getWriteConfig(array $config)
|
||||
{
|
||||
return $this->mergeReadWriteConfig(
|
||||
$config, $this->getReadWriteConfig($config, 'write')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a read / write level configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function getReadWriteConfig(array $config, $type)
|
||||
{
|
||||
return isset($config[$type][0])
|
||||
? Arr::random($config[$type])
|
||||
: $config[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge a configuration for a read / write connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @param array $merge
|
||||
* @return array
|
||||
*/
|
||||
protected function mergeReadWriteConfig(array $config, array $merge)
|
||||
{
|
||||
return Arr::except(array_merge($config, $merge), ['read', 'write']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that resolves to a PDO instance.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createPdoResolver(array $config)
|
||||
{
|
||||
return array_key_exists('host', $config)
|
||||
? $this->createPdoResolverWithHosts($config)
|
||||
: $this->createPdoResolverWithoutHosts($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that resolves to a PDO instance with a specific host or an array of hosts.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createPdoResolverWithHosts(array $config)
|
||||
{
|
||||
return function () use ($config) {
|
||||
foreach (Arr::shuffle($hosts = $this->parseHosts($config)) as $key => $host) {
|
||||
$config['host'] = $host;
|
||||
|
||||
try {
|
||||
return $this->createConnector($config)->connect($config);
|
||||
} catch (PDOException $e) {
|
||||
if (count($hosts) - 1 === $key && $this->container->bound(ExceptionHandler::class)) {
|
||||
$this->container->make(ExceptionHandler::class)->report($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw $e;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the hosts configuration item into an array.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function parseHosts(array $config)
|
||||
{
|
||||
$hosts = array_wrap($config['host']);
|
||||
|
||||
if (empty($hosts)) {
|
||||
throw new InvalidArgumentException('Database hosts array is empty.');
|
||||
}
|
||||
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Closure that resolves to a PDO instance where there is no configured host.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createPdoResolverWithoutHosts(array $config)
|
||||
{
|
||||
return function () use ($config) {
|
||||
return $this->createConnector($config)->connect($config);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a connector instance based on the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connectors\ConnectorInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function createConnector(array $config)
|
||||
{
|
||||
if (! isset($config['driver'])) {
|
||||
throw new InvalidArgumentException('A driver must be specified.');
|
||||
}
|
||||
|
||||
if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
|
||||
return $this->container->make($key);
|
||||
}
|
||||
|
||||
switch ($config['driver']) {
|
||||
case 'mysql':
|
||||
return new MySqlConnector;
|
||||
case 'pgsql':
|
||||
return new PostgresConnector;
|
||||
case 'sqlite':
|
||||
return new SQLiteConnector;
|
||||
case 'sqlsrv':
|
||||
return new SqlServerConnector;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unsupported driver [{$config['driver']}]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new connection instance.
|
||||
*
|
||||
* @param string $driver
|
||||
* @param \PDO|\Closure $connection
|
||||
* @param string $database
|
||||
* @param string $prefix
|
||||
* @param array $config
|
||||
* @return \Illuminate\Database\Connection
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function createConnection($driver, $connection, $database, $prefix = '', array $config = [])
|
||||
{
|
||||
if ($resolver = Connection::getResolver($driver)) {
|
||||
return $resolver($connection, $database, $prefix, $config);
|
||||
}
|
||||
|
||||
switch ($driver) {
|
||||
case 'mysql':
|
||||
return new MySqlConnection($connection, $database, $prefix, $config);
|
||||
case 'pgsql':
|
||||
return new PostgresConnection($connection, $database, $prefix, $config);
|
||||
case 'sqlite':
|
||||
return new SQLiteConnection($connection, $database, $prefix, $config);
|
||||
case 'sqlsrv':
|
||||
return new SqlServerConnection($connection, $database, $prefix, $config);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unsupported driver [$driver]");
|
||||
}
|
||||
}
|
||||
137
vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php
vendored
Executable file
137
vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php
vendored
Executable file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDO;
|
||||
use Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use Doctrine\DBAL\Driver\PDOConnection;
|
||||
use Illuminate\Database\DetectsLostConnections;
|
||||
|
||||
class Connector
|
||||
{
|
||||
use DetectsLostConnections;
|
||||
|
||||
/**
|
||||
* The default PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new PDO connection.
|
||||
*
|
||||
* @param string $dsn
|
||||
* @param array $config
|
||||
* @param array $options
|
||||
* @return \PDO
|
||||
*/
|
||||
public function createConnection($dsn, array $config, array $options)
|
||||
{
|
||||
list($username, $password) = [
|
||||
Arr::get($config, 'username'), Arr::get($config, 'password'),
|
||||
];
|
||||
|
||||
try {
|
||||
return $this->createPdoConnection(
|
||||
$dsn, $username, $password, $options
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return $this->tryAgainIfCausedByLostConnection(
|
||||
$e, $dsn, $username, $password, $options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PDO connection instance.
|
||||
*
|
||||
* @param string $dsn
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param array $options
|
||||
* @return \PDO
|
||||
*/
|
||||
protected function createPdoConnection($dsn, $username, $password, $options)
|
||||
{
|
||||
if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) {
|
||||
return new PDOConnection($dsn, $username, $password, $options);
|
||||
}
|
||||
|
||||
return new PDO($dsn, $username, $password, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the connection is persistent.
|
||||
*
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*/
|
||||
protected function isPersistentConnection($options)
|
||||
{
|
||||
return isset($options[PDO::ATTR_PERSISTENT]) &&
|
||||
$options[PDO::ATTR_PERSISTENT];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception that occurred during connect execution.
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @param string $dsn
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param array $options
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function tryAgainIfCausedByLostConnection(Exception $e, $dsn, $username, $password, $options)
|
||||
{
|
||||
if ($this->causedByLostConnection($e)) {
|
||||
return $this->createPdoConnection($dsn, $username, $password, $options);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PDO options based on the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions(array $config)
|
||||
{
|
||||
$options = Arr::get($config, 'options', []);
|
||||
|
||||
return array_diff_key($this->options, $options) + $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default PDO connection options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default PDO connection options.
|
||||
*
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultOptions(array $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
}
|
||||
}
|
||||
14
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectorInterface.php
vendored
Executable file
14
vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectorInterface.php
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
interface ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config);
|
||||
}
|
||||
180
vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php
vendored
Executable file
180
vendor/laravel/framework/src/Illuminate/Database/Connectors/MySqlConnector.php
vendored
Executable file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDO;
|
||||
|
||||
class MySqlConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
$dsn = $this->getDsn($config);
|
||||
|
||||
$options = $this->getOptions($config);
|
||||
|
||||
// We need to grab the PDO options that should be used while making the brand
|
||||
// new connection instance. The PDO options control various aspects of the
|
||||
// connection's behavior, and some might be specified by the developers.
|
||||
$connection = $this->createConnection($dsn, $config, $options);
|
||||
|
||||
if (! empty($config['database'])) {
|
||||
$connection->exec("use `{$config['database']}`;");
|
||||
}
|
||||
|
||||
$this->configureEncoding($connection, $config);
|
||||
|
||||
// Next, we will check to see if a timezone has been specified in this config
|
||||
// and if it has we will issue a statement to modify the timezone with the
|
||||
// database. Setting this DB timezone is an optional configuration item.
|
||||
$this->configureTimezone($connection, $config);
|
||||
|
||||
$this->setModes($connection, $config);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection character set and collation.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureEncoding($connection, array $config)
|
||||
{
|
||||
if (! isset($config['charset'])) {
|
||||
return $connection;
|
||||
}
|
||||
|
||||
$connection->prepare(
|
||||
"set names '{$config['charset']}'".$this->getCollation($config)
|
||||
)->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the collation for the configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getCollation(array $config)
|
||||
{
|
||||
return isset($config['collation']) ? " collate '{$config['collation']}'" : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timezone on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureTimezone($connection, array $config)
|
||||
{
|
||||
if (isset($config['timezone'])) {
|
||||
$connection->prepare('set time_zone="'.$config['timezone'].'"')->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DSN string from a configuration.
|
||||
*
|
||||
* Chooses socket or host/port based on the 'unix_socket' config value.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDsn(array $config)
|
||||
{
|
||||
return $this->hasSocket($config)
|
||||
? $this->getSocketDsn($config)
|
||||
: $this->getHostDsn($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given configuration array has a UNIX socket value.
|
||||
*
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasSocket(array $config)
|
||||
{
|
||||
return isset($config['unix_socket']) && ! empty($config['unix_socket']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a socket configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getSocketDsn(array $config)
|
||||
{
|
||||
return "mysql:unix_socket={$config['unix_socket']};dbname={$config['database']}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a host / port configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getHostDsn(array $config)
|
||||
{
|
||||
extract($config, EXTR_SKIP);
|
||||
|
||||
return isset($port)
|
||||
? "mysql:host={$host};port={$port};dbname={$database}"
|
||||
: "mysql:host={$host};dbname={$database}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the modes for the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function setModes(PDO $connection, array $config)
|
||||
{
|
||||
if (isset($config['modes'])) {
|
||||
$this->setCustomModes($connection, $config);
|
||||
} elseif (isset($config['strict'])) {
|
||||
if ($config['strict']) {
|
||||
$connection->prepare($this->strictMode())->execute();
|
||||
} else {
|
||||
$connection->prepare("set session sql_mode='NO_ENGINE_SUBSTITUTION'")->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom modes on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function setCustomModes(PDO $connection, array $config)
|
||||
{
|
||||
$modes = implode(',', $config['modes']);
|
||||
|
||||
$connection->prepare("set session sql_mode='{$modes}'")->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query to enable strict mode.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function strictMode()
|
||||
{
|
||||
return "set session sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'";
|
||||
}
|
||||
}
|
||||
174
vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php
vendored
Executable file
174
vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php
vendored
Executable file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDO;
|
||||
|
||||
class PostgresConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* The default PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
// First we'll create the basic DSN and connection instance connecting to the
|
||||
// using the configuration option specified by the developer. We will also
|
||||
// set the default character set on the connections to UTF-8 by default.
|
||||
$connection = $this->createConnection(
|
||||
$this->getDsn($config), $config, $this->getOptions($config)
|
||||
);
|
||||
|
||||
$this->configureEncoding($connection, $config);
|
||||
|
||||
// Next, we will check to see if a timezone has been specified in this config
|
||||
// and if it has we will issue a statement to modify the timezone with the
|
||||
// database. Setting this DB timezone is an optional configuration item.
|
||||
$this->configureTimezone($connection, $config);
|
||||
|
||||
$this->configureSchema($connection, $config);
|
||||
|
||||
// Postgres allows an application_name to be set by the user and this name is
|
||||
// used to when monitoring the application with pg_stat_activity. So we'll
|
||||
// determine if the option has been specified and run a statement if so.
|
||||
$this->configureApplicationName($connection, $config);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the connection character set and collation.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureEncoding($connection, $config)
|
||||
{
|
||||
$charset = $config['charset'];
|
||||
|
||||
$connection->prepare("set names '$charset'")->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timezone on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureTimezone($connection, array $config)
|
||||
{
|
||||
if (isset($config['timezone'])) {
|
||||
$timezone = $config['timezone'];
|
||||
|
||||
$connection->prepare("set time zone '{$timezone}'")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureSchema($connection, $config)
|
||||
{
|
||||
if (isset($config['schema'])) {
|
||||
$schema = $this->formatSchema($config['schema']);
|
||||
|
||||
$connection->prepare("set search_path to {$schema}")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the schema for the DSN.
|
||||
*
|
||||
* @param array|string $schema
|
||||
* @return string
|
||||
*/
|
||||
protected function formatSchema($schema)
|
||||
{
|
||||
if (is_array($schema)) {
|
||||
return '"'.implode('", "', $schema).'"';
|
||||
} else {
|
||||
return '"'.$schema.'"';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the schema on the connection.
|
||||
*
|
||||
* @param \PDO $connection
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
protected function configureApplicationName($connection, $config)
|
||||
{
|
||||
if (isset($config['application_name'])) {
|
||||
$applicationName = $config['application_name'];
|
||||
|
||||
$connection->prepare("set application_name to '$applicationName'")->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DSN string from a configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDsn(array $config)
|
||||
{
|
||||
// First we will create the basic DSN setup as well as the port if it is in
|
||||
// in the configuration options. This will give us the basic DSN we will
|
||||
// need to establish the PDO connections and return them back for use.
|
||||
extract($config, EXTR_SKIP);
|
||||
|
||||
$host = isset($host) ? "host={$host};" : '';
|
||||
|
||||
$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
|
||||
// string back out for usage, as this has been fully constructed here.
|
||||
if (isset($config['port'])) {
|
||||
$dsn .= ";port={$port}";
|
||||
}
|
||||
|
||||
return $this->addSslOptions($dsn, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the SSL options to the DSN.
|
||||
*
|
||||
* @param string $dsn
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function addSslOptions($dsn, array $config)
|
||||
{
|
||||
foreach (['sslmode', 'sslcert', 'sslkey', 'sslrootcert'] as $option) {
|
||||
if (isset($config[$option])) {
|
||||
$dsn .= ";{$option}={$config[$option]}";
|
||||
}
|
||||
}
|
||||
|
||||
return $dsn;
|
||||
}
|
||||
}
|
||||
39
vendor/laravel/framework/src/Illuminate/Database/Connectors/SQLiteConnector.php
vendored
Executable file
39
vendor/laravel/framework/src/Illuminate/Database/Connectors/SQLiteConnector.php
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class SQLiteConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
$options = $this->getOptions($config);
|
||||
|
||||
// SQLite supports "in-memory" databases that only last as long as the owning
|
||||
// connection does. These are useful for tests or for short lifetime store
|
||||
// querying. In-memory databases may only have a single open connection.
|
||||
if ($config['database'] == ':memory:') {
|
||||
return $this->createConnection('sqlite::memory:', $config, $options);
|
||||
}
|
||||
|
||||
$path = realpath($config['database']);
|
||||
|
||||
// Here we'll verify that the SQLite database exists before going any further
|
||||
// as the developer probably wants to know if the database exists and this
|
||||
// SQLite driver will not throw any exception if it does not by default.
|
||||
if ($path === false) {
|
||||
throw new InvalidArgumentException("Database (${config['database']}) does not exist.");
|
||||
}
|
||||
|
||||
return $this->createConnection("sqlite:{$path}", $config, $options);
|
||||
}
|
||||
}
|
||||
175
vendor/laravel/framework/src/Illuminate/Database/Connectors/SqlServerConnector.php
vendored
Executable file
175
vendor/laravel/framework/src/Illuminate/Database/Connectors/SqlServerConnector.php
vendored
Executable file
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Connectors;
|
||||
|
||||
use PDO;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class SqlServerConnector extends Connector implements ConnectorInterface
|
||||
{
|
||||
/**
|
||||
* The PDO connection options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
|
||||
PDO::ATTR_STRINGIFY_FETCHES => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* Establish a database connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \PDO
|
||||
*/
|
||||
public function connect(array $config)
|
||||
{
|
||||
$options = $this->getOptions($config);
|
||||
|
||||
return $this->createConnection($this->getDsn($config), $config, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DSN string from a configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDsn(array $config)
|
||||
{
|
||||
// First we will create the basic DSN setup as well as the port if it is in
|
||||
// in the configuration options. This will give us the basic DSN we will
|
||||
// need to establish the PDO connections and return them back for use.
|
||||
if (in_array('dblib', $this->getAvailableDrivers())) {
|
||||
return $this->getDblibDsn($config);
|
||||
} elseif ($this->prefersOdbc($config)) {
|
||||
return $this->getOdbcDsn($config);
|
||||
} else {
|
||||
return $this->getSqlSrvDsn($config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the database configuration prefers ODBC.
|
||||
*
|
||||
* @param array $config
|
||||
* @return bool
|
||||
*/
|
||||
protected function prefersOdbc(array $config)
|
||||
{
|
||||
return in_array('odbc', $this->getAvailableDrivers()) &&
|
||||
array_get($config, 'odbc') === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a DbLib connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getDblibDsn(array $config)
|
||||
{
|
||||
return $this->buildConnectString('dblib', array_merge([
|
||||
'host' => $this->buildHostString($config, ':'),
|
||||
'dbname' => $config['database'],
|
||||
], Arr::only($config, ['appname', 'charset'])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for an ODBC connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getOdbcDsn(array $config)
|
||||
{
|
||||
return isset($config['odbc_datasource_name'])
|
||||
? 'odbc:'.$config['odbc_datasource_name'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DSN string for a SqlSrv connection.
|
||||
*
|
||||
* @param array $config
|
||||
* @return string
|
||||
*/
|
||||
protected function getSqlSrvDsn(array $config)
|
||||
{
|
||||
$arguments = [
|
||||
'Server' => $this->buildHostString($config, ','),
|
||||
];
|
||||
|
||||
if (isset($config['database'])) {
|
||||
$arguments['Database'] = $config['database'];
|
||||
}
|
||||
|
||||
if (isset($config['readonly'])) {
|
||||
$arguments['ApplicationIntent'] = 'ReadOnly';
|
||||
}
|
||||
|
||||
if (isset($config['pooling']) && $config['pooling'] === false) {
|
||||
$arguments['ConnectionPooling'] = '0';
|
||||
}
|
||||
|
||||
if (isset($config['appname'])) {
|
||||
$arguments['APP'] = $config['appname'];
|
||||
}
|
||||
|
||||
if (isset($config['encrypt'])) {
|
||||
$arguments['Encrypt'] = $config['encrypt'];
|
||||
}
|
||||
|
||||
if (isset($config['trust_server_certificate'])) {
|
||||
$arguments['TrustServerCertificate'] = $config['trust_server_certificate'];
|
||||
}
|
||||
|
||||
if (isset($config['multiple_active_result_sets']) && $config['multiple_active_result_sets'] === false) {
|
||||
$arguments['MultipleActiveResultSets'] = 'false';
|
||||
}
|
||||
|
||||
return $this->buildConnectString('sqlsrv', $arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a connection string from the given arguments.
|
||||
*
|
||||
* @param string $driver
|
||||
* @param array $arguments
|
||||
* @return string
|
||||
*/
|
||||
protected function buildConnectString($driver, array $arguments)
|
||||
{
|
||||
return $driver.':'.implode(';', array_map(function ($key) use ($arguments) {
|
||||
return sprintf('%s=%s', $key, $arguments[$key]);
|
||||
}, array_keys($arguments)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a host string from the given configuration.
|
||||
*
|
||||
* @param array $config
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
protected function buildHostString(array $config, $separator)
|
||||
{
|
||||
if (isset($config['port']) && ! empty($config['port'])) {
|
||||
return $config['host'].$separator.$config['port'];
|
||||
} else {
|
||||
return $config['host'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available PDO drivers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getAvailableDrivers()
|
||||
{
|
||||
return PDO::getAvailableDrivers();
|
||||
}
|
||||
}
|
||||
39
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/BaseCommand.php
vendored
Executable file
39
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/BaseCommand.php
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class BaseCommand extends Command
|
||||
{
|
||||
/**
|
||||
* Get all of the migration paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getMigrationPaths()
|
||||
{
|
||||
// Here, we will check to see if a path option has been defined. If it has we will
|
||||
// use the path relative to the root of the installation folder so our database
|
||||
// migrations may be run for any customized path from within the application.
|
||||
if ($this->input->hasOption('path') && $this->option('path')) {
|
||||
return collect($this->option('path'))->map(function ($path) {
|
||||
return $this->laravel->basePath().'/'.$path;
|
||||
})->all();
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
[$this->getMigrationPath()], $this->migrator->paths()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the migration directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationPath()
|
||||
{
|
||||
return $this->laravel->databasePath().DIRECTORY_SEPARATOR.'migrations';
|
||||
}
|
||||
}
|
||||
70
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/InstallCommand.php
vendored
Executable file
70
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/InstallCommand.php
vendored
Executable file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Illuminate\Database\Migrations\MigrationRepositoryInterface;
|
||||
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:install';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create the migration repository';
|
||||
|
||||
/**
|
||||
* The repository instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\MigrationRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* Create a new migration install command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\MigrationRepositoryInterface $repository
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MigrationRepositoryInterface $repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
$this->repository->setSource($this->input->getOption('database'));
|
||||
|
||||
$this->repository->createRepository();
|
||||
|
||||
$this->info('Migration table created successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
102
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php
vendored
Executable file
102
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php
vendored
Executable file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
|
||||
class MigrateCommand extends BaseCommand
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'migrate {--database= : The database connection to use.}
|
||||
{--force : Force the operation to run when in production.}
|
||||
{--path= : The path of migrations files to be executed.}
|
||||
{--pretend : Dump the SQL queries that would be run.}
|
||||
{--seed : Indicates if the seed task should be re-run.}
|
||||
{--step : Force the migrations to be run so they can be rolled back individually.}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the database migrations';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->prepareDatabase();
|
||||
|
||||
// Next, we will check to see if a path option has been defined. If it has
|
||||
// we will use the path relative to the root of this installation folder
|
||||
// so that migrations may be run for any path within the applications.
|
||||
$this->migrator->run($this->getMigrationPaths(), [
|
||||
'pretend' => $this->option('pretend'),
|
||||
'step' => $this->option('step'),
|
||||
]);
|
||||
|
||||
// Once the migrator has run we will grab the note output and send it out to
|
||||
// the console screen, since the migrator itself functions without having
|
||||
// any instances of the OutputInterface contract passed into the class.
|
||||
foreach ($this->migrator->getNotes() as $note) {
|
||||
$this->output->writeln($note);
|
||||
}
|
||||
|
||||
// Finally, if the "seed" option has been given, we will re-run the database
|
||||
// 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->call('db:seed', ['--force' => true]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the migration database for running.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareDatabase()
|
||||
{
|
||||
$this->migrator->setConnection($this->option('database'));
|
||||
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
$this->call(
|
||||
'migrate:install', ['--database' => $this->option('database')]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
119
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php
vendored
Normal file
119
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateMakeCommand.php
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Support\Composer;
|
||||
use Illuminate\Database\Migrations\MigrationCreator;
|
||||
|
||||
class MigrateMakeCommand extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The console command signature.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'make:migration {name : The name of the migration.}
|
||||
{--create= : The table to be created.}
|
||||
{--table= : The table to migrate.}
|
||||
{--path= : The location where the migration file should be created.}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a new migration file';
|
||||
|
||||
/**
|
||||
* The migration creator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\MigrationCreator
|
||||
*/
|
||||
protected $creator;
|
||||
|
||||
/**
|
||||
* The Composer instance.
|
||||
*
|
||||
* @var \Illuminate\Support\Composer
|
||||
*/
|
||||
protected $composer;
|
||||
|
||||
/**
|
||||
* Create a new migration install command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\MigrationCreator $creator
|
||||
* @param \Illuminate\Support\Composer $composer
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MigrationCreator $creator, Composer $composer)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->creator = $creator;
|
||||
$this->composer = $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
// It's possible for the developer to specify the tables to modify in this
|
||||
// schema operation. The developer may also specify if this table needs
|
||||
// to be freshly created so we can create the appropriate migrations.
|
||||
$name = trim($this->input->getArgument('name'));
|
||||
|
||||
$table = $this->input->getOption('table');
|
||||
|
||||
$create = $this->input->getOption('create') ?: false;
|
||||
|
||||
// If no table was given as an option but a create option is given then we
|
||||
// will use the "create" option as the table name. This allows the devs
|
||||
// to pass a table name into this option as a short-cut for creating.
|
||||
if (! $table && is_string($create)) {
|
||||
$table = $create;
|
||||
|
||||
$create = true;
|
||||
}
|
||||
|
||||
// Now we are ready to write the migration out to disk. Once we've written
|
||||
// the migration out, we will dump-autoload for the entire framework to
|
||||
// make sure that the migrations are registered by the class loaders.
|
||||
$this->writeMigration($name, $table, $create);
|
||||
|
||||
$this->composer->dumpAutoloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the migration file to disk.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param bool $create
|
||||
* @return string
|
||||
*/
|
||||
protected function writeMigration($name, $table, $create)
|
||||
{
|
||||
$file = pathinfo($this->creator->create(
|
||||
$name, $this->getMigrationPath(), $table, $create
|
||||
), PATHINFO_FILENAME);
|
||||
|
||||
$this->line("<info>Created Migration:</info> {$file}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get migration path (either specified by '--path' option or default location).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getMigrationPath()
|
||||
{
|
||||
if (! is_null($targetPath = $this->input->getOption('path'))) {
|
||||
return $this->laravel->basePath().'/'.$targetPath;
|
||||
}
|
||||
|
||||
return parent::getMigrationPath();
|
||||
}
|
||||
}
|
||||
154
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RefreshCommand.php
vendored
Executable file
154
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RefreshCommand.php
vendored
Executable file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class RefreshCommand extends Command
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:refresh';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Reset and re-run all migrations';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Next we'll gather some of the options so that we can have the right options
|
||||
// to pass to the commands. This includes options such as which database to
|
||||
// use and the path to use for the migration. Then we'll run the command.
|
||||
$database = $this->input->getOption('database');
|
||||
|
||||
$path = $this->input->getOption('path');
|
||||
|
||||
$force = $this->input->getOption('force');
|
||||
|
||||
// If the "step" option is specified it means we only want to rollback a small
|
||||
// number of migrations before migrating again. For example, the user might
|
||||
// only rollback and remigrate the latest four migrations instead of all.
|
||||
$step = $this->input->getOption('step') ?: 0;
|
||||
|
||||
if ($step > 0) {
|
||||
$this->runRollback($database, $path, $step, $force);
|
||||
} else {
|
||||
$this->runReset($database, $path, $force);
|
||||
}
|
||||
|
||||
// The refresh command is essentially just a brief aggregate of a few other of
|
||||
// the migration commands and just provides a convenient wrapper to execute
|
||||
// them in succession. We'll also see if we need to re-seed the database.
|
||||
$this->call('migrate', [
|
||||
'--database' => $database,
|
||||
'--path' => $path,
|
||||
'--force' => $force,
|
||||
]);
|
||||
|
||||
if ($this->needsSeeding()) {
|
||||
$this->runSeeder($database);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the rollback command.
|
||||
*
|
||||
* @param string $database
|
||||
* @param string $path
|
||||
* @param bool $step
|
||||
* @param bool $force
|
||||
* @return void
|
||||
*/
|
||||
protected function runRollback($database, $path, $step, $force)
|
||||
{
|
||||
$this->call('migrate:rollback', [
|
||||
'--database' => $database,
|
||||
'--path' => $path,
|
||||
'--step' => $step,
|
||||
'--force' => $force,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the reset command.
|
||||
*
|
||||
* @param string $database
|
||||
* @param string $path
|
||||
* @param bool $force
|
||||
* @return void
|
||||
*/
|
||||
protected function runReset($database, $path, $force)
|
||||
{
|
||||
$this->call('migrate:reset', [
|
||||
'--database' => $database,
|
||||
'--path' => $path,
|
||||
'--force' => $force,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the developer has requested database seeding.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function needsSeeding()
|
||||
{
|
||||
return $this->option('seed') || $this->option('seeder');
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the database seeder command.
|
||||
*
|
||||
* @param string $database
|
||||
* @return void
|
||||
*/
|
||||
protected function runSeeder($database)
|
||||
{
|
||||
$this->call('db:seed', [
|
||||
'--database' => $database,
|
||||
'--class' => $this->option('seeder') ?: 'DatabaseSeeder',
|
||||
'--force' => $this->option('force'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'],
|
||||
|
||||
['path', null, InputOption::VALUE_OPTIONAL, 'The path of migrations files to be executed.'],
|
||||
|
||||
['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_OPTIONAL, 'The number of migrations to be reverted & re-run.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
96
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/ResetCommand.php
vendored
Executable file
96
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/ResetCommand.php
vendored
Executable file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class ResetCommand extends BaseCommand
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:reset';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rollback all database migrations';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration rollback command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->migrator->setConnection($this->option('database'));
|
||||
|
||||
// First, we'll make sure that the migration table actually exists before we
|
||||
// start trying to rollback and re-run all of the migrations. If it's not
|
||||
// present we'll just bail out with an info message for the developers.
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
return $this->comment('Migration table not found.');
|
||||
}
|
||||
|
||||
$this->migrator->reset(
|
||||
$this->getMigrationPaths(), $this->option('pretend')
|
||||
);
|
||||
|
||||
// Once the migrator has run we will grab the note output and send it out to
|
||||
// the console screen, since the migrator itself functions without having
|
||||
// any instances of the OutputInterface contract passed into the class.
|
||||
foreach ($this->migrator->getNotes() as $note) {
|
||||
$this->output->writeln($note);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],
|
||||
|
||||
['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) of migrations files to be executed.'],
|
||||
|
||||
['pretend', null, InputOption::VALUE_NONE, 'Dump the SQL queries that would be run.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
94
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RollbackCommand.php
vendored
Executable file
94
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/RollbackCommand.php
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class RollbackCommand extends BaseCommand
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:rollback';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rollback the last database migration';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration rollback command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->migrator->setConnection($this->option('database'));
|
||||
|
||||
$this->migrator->rollback(
|
||||
$this->getMigrationPaths(), [
|
||||
'pretend' => $this->option('pretend'),
|
||||
'step' => (int) $this->option('step'),
|
||||
]
|
||||
);
|
||||
|
||||
// Once the migrator has run we will grab the note output and send it out to
|
||||
// the console screen, since the migrator itself functions without having
|
||||
// any instances of the OutputInterface contract passed into the class.
|
||||
foreach ($this->migrator->getNotes() as $note) {
|
||||
$this->output->writeln($note);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'],
|
||||
|
||||
['path', null, InputOption::VALUE_OPTIONAL, 'The path of migrations files to be executed.'],
|
||||
|
||||
['pretend', null, InputOption::VALUE_NONE, 'Dump the SQL queries that would be run.'],
|
||||
|
||||
['step', null, InputOption::VALUE_OPTIONAL, 'The number of migrations to be reverted.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
108
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/StatusCommand.php
vendored
Normal file
108
vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/StatusCommand.php
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Migrations;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class StatusCommand extends BaseCommand
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'migrate:status';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Show the status of each migration';
|
||||
|
||||
/**
|
||||
* The migrator instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\Migrator
|
||||
*/
|
||||
protected $migrator;
|
||||
|
||||
/**
|
||||
* Create a new migration rollback command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\Migrator $migrator
|
||||
* @return \Illuminate\Database\Console\Migrations\StatusCommand
|
||||
*/
|
||||
public function __construct(Migrator $migrator)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
$this->migrator->setConnection($this->option('database'));
|
||||
|
||||
if (! $this->migrator->repositoryExists()) {
|
||||
return $this->error('No migrations found.');
|
||||
}
|
||||
|
||||
$ran = $this->migrator->getRepository()->getRan();
|
||||
|
||||
if (count($migrations = $this->getStatusFor($ran)) > 0) {
|
||||
$this->table(['Ran?', 'Migration'], $migrations);
|
||||
} else {
|
||||
$this->error('No migrations found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status for the given ran migrations.
|
||||
*
|
||||
* @param array $ran
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
protected function getStatusFor(array $ran)
|
||||
{
|
||||
return Collection::make($this->getAllMigrationFiles())
|
||||
->map(function ($migration) use ($ran) {
|
||||
$migrationName = $this->migrator->getMigrationName($migration);
|
||||
|
||||
return in_array($migrationName, $ran)
|
||||
? ['<info>Y</info>', $migrationName]
|
||||
: ['<fg=red>N</fg=red>', $migrationName];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all of the migration files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getAllMigrationFiles()
|
||||
{
|
||||
return $this->migrator->getMigrationFiles($this->getMigrationPaths());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to use.'],
|
||||
|
||||
['path', null, InputOption::VALUE_OPTIONAL, 'The path of migrations files to use.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
106
vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/SeedCommand.php
vendored
Normal file
106
vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/SeedCommand.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Seeds;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Console\ConfirmableTrait;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
|
||||
class SeedCommand extends Command
|
||||
{
|
||||
use ConfirmableTrait;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'db:seed';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Seed the database with records';
|
||||
|
||||
/**
|
||||
* The connection resolver instance.
|
||||
*
|
||||
* @var \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* Create a new database seed command instance.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Resolver $resolver)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
if (! $this->confirmToProceed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->resolver->setDefaultConnection($this->getDatabase());
|
||||
|
||||
Model::unguarded(function () {
|
||||
$this->getSeeder()->__invoke();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a seeder instance from the container.
|
||||
*
|
||||
* @return \Illuminate\Database\Seeder
|
||||
*/
|
||||
protected function getSeeder()
|
||||
{
|
||||
$class = $this->laravel->make($this->input->getOption('class'));
|
||||
|
||||
return $class->setContainer($this->laravel)->setCommand($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the database connection to use.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDatabase()
|
||||
{
|
||||
$database = $this->input->getOption('database');
|
||||
|
||||
return $database ?: $this->laravel['config']['database.default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console command options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
return [
|
||||
['class', null, InputOption::VALUE_OPTIONAL, 'The class name of the root seeder', 'DatabaseSeeder'],
|
||||
|
||||
['database', null, InputOption::VALUE_OPTIONAL, 'The database connection to seed'],
|
||||
|
||||
['force', null, InputOption::VALUE_NONE, 'Force the operation to run when in production.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
96
vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/SeederMakeCommand.php
vendored
Normal file
96
vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/SeederMakeCommand.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Console\Seeds;
|
||||
|
||||
use Illuminate\Support\Composer;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
|
||||
class SeederMakeCommand extends GeneratorCommand
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'make:seeder';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a new seeder class';
|
||||
|
||||
/**
|
||||
* The type of class being generated.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
parent::fire();
|
||||
|
||||
$this->composer->dumpAutoloads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stub file for the generator.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getStub()
|
||||
{
|
||||
return __DIR__.'/stubs/seeder.stub';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination class path.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function getPath($name)
|
||||
{
|
||||
return $this->laravel->databasePath().'/seeds/'.$name.'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the class name and format according to the root namespace.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function qualifyClass($name)
|
||||
{
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
16
vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/stubs/seeder.stub
vendored
Normal file
16
vendor/laravel/framework/src/Illuminate/Database/Console/Seeds/stubs/seeder.stub
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DummyClass extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
326
vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php
vendored
Executable file
326
vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php
vendored
Executable file
@@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use PDO;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
|
||||
class DatabaseManager implements ConnectionResolverInterface
|
||||
{
|
||||
/**
|
||||
* The application instance.
|
||||
*
|
||||
* @var \Illuminate\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* The database connection factory instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connectors\ConnectionFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The active connection instances.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $connections = [];
|
||||
|
||||
/**
|
||||
* The custom connection resolvers.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
/**
|
||||
* Create a new database manager instance.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
* @param \Illuminate\Database\Connectors\ConnectionFactory $factory
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($app, ConnectionFactory $factory)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a database connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function connection($name = null)
|
||||
{
|
||||
list($database, $type) = $this->parseConnectionName($name);
|
||||
|
||||
$name = $name ?: $database;
|
||||
|
||||
// If we haven't created this connection, we'll create it based on the config
|
||||
// provided in the application. Once we've created the connections we will
|
||||
// set the "fetch mode" for PDO which determines the query return types.
|
||||
if (! isset($this->connections[$name])) {
|
||||
$this->connections[$name] = $this->configure(
|
||||
$connection = $this->makeConnection($database), $type
|
||||
);
|
||||
}
|
||||
|
||||
return $this->connections[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the connection into an array of the name and read / write type.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function parseConnectionName($name)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultConnection();
|
||||
|
||||
return Str::endsWith($name, ['::read', '::write'])
|
||||
? explode('::', $name, 2) : [$name, null];
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the database connection instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function makeConnection($name)
|
||||
{
|
||||
$config = $this->configuration($name);
|
||||
|
||||
// First we will check by the connection name to see if an extension has been
|
||||
// registered specifically for that connection. If it has we will call the
|
||||
// Closure and pass it the config allowing it to resolve the connection.
|
||||
if (isset($this->extensions[$name])) {
|
||||
return call_user_func($this->extensions[$name], $config, $name);
|
||||
}
|
||||
|
||||
// Next we will check to see if an extension has been registered for a driver
|
||||
// and will call the Closure if so, which allows us to have a more generic
|
||||
// resolver for the drivers themselves which applies to all connections.
|
||||
if (isset($this->extensions[$driver = $config['driver']])) {
|
||||
return call_user_func($this->extensions[$driver], $config, $name);
|
||||
}
|
||||
|
||||
return $this->factory->make($config, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration for a connection.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function configuration($name)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultConnection();
|
||||
|
||||
// To get the database connection configuration, we will just pull each of the
|
||||
// connection configurations and get the configurations for the given name.
|
||||
// If the configuration doesn't exist, we'll throw an exception and bail.
|
||||
$connections = $this->app['config']['database.connections'];
|
||||
|
||||
if (is_null($config = Arr::get($connections, $name))) {
|
||||
throw new InvalidArgumentException("Database [$name] not configured.");
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the database connection instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function configure(Connection $connection, $type)
|
||||
{
|
||||
$connection = $this->setPdoForType($connection, $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
|
||||
// used by the application. Once we're finished we'll return it back out.
|
||||
if ($this->app->bound('events')) {
|
||||
$connection->setEventDispatcher($this->app['events']);
|
||||
}
|
||||
|
||||
// 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(function ($connection) {
|
||||
$this->reconnect($connection->getName());
|
||||
});
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the read / write mode for database connection instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function setPdoForType(Connection $connection, $type = null)
|
||||
{
|
||||
if ($type == 'read') {
|
||||
$connection->setPdo($connection->getReadPdo());
|
||||
} elseif ($type == 'write') {
|
||||
$connection->setReadPdo($connection->getPdo());
|
||||
}
|
||||
|
||||
return $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the given database and remove from local cache.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function purge($name = null)
|
||||
{
|
||||
$name = $name ?: $this->getDefaultConnection();
|
||||
|
||||
$this->disconnect($name);
|
||||
|
||||
unset($this->connections[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the given database.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect($name = null)
|
||||
{
|
||||
if (isset($this->connections[$name = $name ?: $this->getDefaultConnection()])) {
|
||||
$this->connections[$name]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconnect to the given database.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function reconnect($name = null)
|
||||
{
|
||||
$this->disconnect($name = $name ?: $this->getDefaultConnection());
|
||||
|
||||
if (! isset($this->connections[$name])) {
|
||||
return $this->connection($name);
|
||||
}
|
||||
|
||||
return $this->refreshPdoConnections($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the PDO connections on a given connection.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
protected function refreshPdoConnections($name)
|
||||
{
|
||||
$fresh = $this->makeConnection($name);
|
||||
|
||||
return $this->connections[$name]
|
||||
->setPdo($fresh->getPdo())
|
||||
->setReadPdo($fresh->getReadPdo());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultConnection()
|
||||
{
|
||||
return $this->app['config']['database.default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultConnection($name)
|
||||
{
|
||||
$this->app['config']['database.default'] = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the support drivers.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function supportedDrivers()
|
||||
{
|
||||
return ['mysql', 'pgsql', 'sqlite', 'sqlsrv'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the drivers that are actually available.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function availableDrivers()
|
||||
{
|
||||
return array_intersect(
|
||||
$this->supportedDrivers(),
|
||||
str_replace('dblib', 'sqlsrv', PDO::getAvailableDrivers())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an extension connection resolver.
|
||||
*
|
||||
* @param string $name
|
||||
* @param callable $resolver
|
||||
* @return void
|
||||
*/
|
||||
public function extend($name, callable $resolver)
|
||||
{
|
||||
$this->extensions[$name] = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all of the created connections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getConnections()
|
||||
{
|
||||
return $this->connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically pass methods to the default connection.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
return $this->connection()->$method(...$parameters);
|
||||
}
|
||||
}
|
||||
99
vendor/laravel/framework/src/Illuminate/Database/DatabaseServiceProvider.php
vendored
Executable file
99
vendor/laravel/framework/src/Illuminate/Database/DatabaseServiceProvider.php
vendored
Executable file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Faker\Factory as FakerFactory;
|
||||
use Faker\Generator as FakerGenerator;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Contracts\Queue\EntityResolver;
|
||||
use Illuminate\Database\Connectors\ConnectionFactory;
|
||||
use Illuminate\Database\Eloquent\QueueEntityResolver;
|
||||
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
|
||||
|
||||
class DatabaseServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Model::setConnectionResolver($this->app['db']);
|
||||
|
||||
Model::setEventDispatcher($this->app['events']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
Model::clearBootedModels();
|
||||
|
||||
$this->registerConnectionServices();
|
||||
|
||||
$this->registerEloquentFactory();
|
||||
|
||||
$this->registerQueueableEntityResolver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the primary database bindings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerConnectionServices()
|
||||
{
|
||||
// The connection factory is used to create the actual connection instances on
|
||||
// the database. We will inject the factory into the manager so that it may
|
||||
// make the connections while they are actually needed and not of before.
|
||||
$this->app->singleton('db.factory', function ($app) {
|
||||
return new ConnectionFactory($app);
|
||||
});
|
||||
|
||||
// The database manager is used to resolve various connections, since multiple
|
||||
// connections might be managed. It also implements the connection resolver
|
||||
// interface which may be used by other components requiring connections.
|
||||
$this->app->singleton('db', function ($app) {
|
||||
return new DatabaseManager($app, $app['db.factory']);
|
||||
});
|
||||
|
||||
$this->app->bind('db.connection', function ($app) {
|
||||
return $app['db']->connection();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Eloquent factory instance in the container.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerEloquentFactory()
|
||||
{
|
||||
$this->app->singleton(FakerGenerator::class, function ($app) {
|
||||
return FakerFactory::create($app['config']->get('app.faker_locale', 'en_US'));
|
||||
});
|
||||
|
||||
$this->app->singleton(EloquentFactory::class, function ($app) {
|
||||
return EloquentFactory::construct(
|
||||
$app->make(FakerGenerator::class), $this->app->databasePath('factories')
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the queueable entity resolver implementation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerQueueableEntityResolver()
|
||||
{
|
||||
$this->app->singleton(EntityResolver::class, function () {
|
||||
return new QueueEntityResolver;
|
||||
});
|
||||
}
|
||||
}
|
||||
31
vendor/laravel/framework/src/Illuminate/Database/DetectsDeadlocks.php
vendored
Normal file
31
vendor/laravel/framework/src/Illuminate/Database/DetectsDeadlocks.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait DetectsDeadlocks
|
||||
{
|
||||
/**
|
||||
* Determine if the given exception was caused by a deadlock.
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByDeadlock(Exception $e)
|
||||
{
|
||||
$message = $e->getMessage();
|
||||
|
||||
return Str::contains($message, [
|
||||
'Deadlock found when trying to get lock',
|
||||
'deadlock detected',
|
||||
'The database file is locked',
|
||||
'database is locked',
|
||||
'database table is locked',
|
||||
'A table in the database is locked',
|
||||
'has been chosen as the deadlock victim',
|
||||
'Lock wait timeout exceeded; try restarting transaction',
|
||||
]);
|
||||
}
|
||||
}
|
||||
34
vendor/laravel/framework/src/Illuminate/Database/DetectsLostConnections.php
vendored
Normal file
34
vendor/laravel/framework/src/Illuminate/Database/DetectsLostConnections.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait DetectsLostConnections
|
||||
{
|
||||
/**
|
||||
* Determine if the given exception was caused by a lost connection.
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByLostConnection(Exception $e)
|
||||
{
|
||||
$message = $e->getMessage();
|
||||
|
||||
return Str::contains($message, [
|
||||
'server has gone away',
|
||||
'no connection to the server',
|
||||
'Lost connection',
|
||||
'is dead or not enabled',
|
||||
'Error while sending',
|
||||
'decryption failed or bad record mac',
|
||||
'server closed the connection unexpectedly',
|
||||
'SSL connection has been closed unexpectedly',
|
||||
'Error writing data to the connection',
|
||||
'Resource deadlock avoided',
|
||||
'Transaction() on null',
|
||||
]);
|
||||
}
|
||||
}
|
||||
1296
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
vendored
Executable file
1296
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
398
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php
vendored
Executable file
398
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php
vendored
Executable file
@@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use LogicException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Contracts\Queue\QueueableCollection;
|
||||
use Illuminate\Support\Collection as BaseCollection;
|
||||
|
||||
class Collection extends BaseCollection implements QueueableCollection
|
||||
{
|
||||
/**
|
||||
* Find a model in the collection by key.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
*/
|
||||
public function find($key, $default = null)
|
||||
{
|
||||
if ($key instanceof Model) {
|
||||
$key = $key->getKey();
|
||||
}
|
||||
|
||||
if (is_array($key)) {
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
return $this->whereIn($this->first()->getKeyName(), $key);
|
||||
}
|
||||
|
||||
return Arr::first($this->items, function ($model) use ($key) {
|
||||
return $model->getKey() == $key;
|
||||
}, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a set of relationships onto the collection.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function load($relations)
|
||||
{
|
||||
if (count($this->items) > 0) {
|
||||
if (is_string($relations)) {
|
||||
$relations = func_get_args();
|
||||
}
|
||||
|
||||
$query = $this->first()->newQuery()->with($relations);
|
||||
|
||||
$this->items = $query->eagerLoadRelations($this->items);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the collection.
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return $this
|
||||
*/
|
||||
public function add($item)
|
||||
{
|
||||
$this->items[] = $item;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a key exists in the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($key, $operator = null, $value = null)
|
||||
{
|
||||
if (func_num_args() > 1 || $this->useAsCallable($key)) {
|
||||
return parent::contains(...func_get_args());
|
||||
}
|
||||
|
||||
if ($key instanceof Model) {
|
||||
return parent::contains(function ($model) use ($key) {
|
||||
return $model->is($key);
|
||||
});
|
||||
}
|
||||
|
||||
return parent::contains(function ($model) use ($key) {
|
||||
return $model->getKey() == $key;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of primary keys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function modelKeys()
|
||||
{
|
||||
return array_map(function ($model) {
|
||||
return $model->getKey();
|
||||
}, $this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the collection with the given items.
|
||||
*
|
||||
* @param \ArrayAccess|array $items
|
||||
* @return static
|
||||
*/
|
||||
public function merge($items)
|
||||
{
|
||||
$dictionary = $this->getDictionary();
|
||||
|
||||
foreach ($items as $item) {
|
||||
$dictionary[$item->getKey()] = $item;
|
||||
}
|
||||
|
||||
return new static(array_values($dictionary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a map over each of the items.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return \Illuminate\Support\Collection|static
|
||||
*/
|
||||
public function map(callable $callback)
|
||||
{
|
||||
$result = parent::map($callback);
|
||||
|
||||
return $result->contains(function ($item) {
|
||||
return ! $item instanceof Model;
|
||||
}) ? $result->toBase() : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload a fresh model instance from the database for all the entities.
|
||||
*
|
||||
* @param array|string $with
|
||||
* @return static
|
||||
*/
|
||||
public function fresh($with = [])
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return new static;
|
||||
}
|
||||
|
||||
$model = $this->first();
|
||||
|
||||
$freshModels = $model->newQueryWithoutScopes()
|
||||
->with(is_string($with) ? func_get_args() : $with)
|
||||
->whereIn($model->getKeyName(), $this->modelKeys())
|
||||
->get()
|
||||
->getDictionary();
|
||||
|
||||
return $this->map(function ($model) use ($freshModels) {
|
||||
return $model->exists ? $freshModels[$model->getKey()] : null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Diff the collection with the given items.
|
||||
*
|
||||
* @param \ArrayAccess|array $items
|
||||
* @return static
|
||||
*/
|
||||
public function diff($items)
|
||||
{
|
||||
$diff = new static;
|
||||
|
||||
$dictionary = $this->getDictionary($items);
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if (! isset($dictionary[$item->getKey()])) {
|
||||
$diff->add($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersect the collection with the given items.
|
||||
*
|
||||
* @param \ArrayAccess|array $items
|
||||
* @return static
|
||||
*/
|
||||
public function intersect($items)
|
||||
{
|
||||
$intersect = new static;
|
||||
|
||||
$dictionary = $this->getDictionary($items);
|
||||
|
||||
foreach ($this->items as $item) {
|
||||
if (isset($dictionary[$item->getKey()])) {
|
||||
$intersect->add($item);
|
||||
}
|
||||
}
|
||||
|
||||
return $intersect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return only unique items from the collection.
|
||||
*
|
||||
* @param string|callable|null $key
|
||||
* @param bool $strict
|
||||
* @return static|\Illuminate\Support\Collection
|
||||
*/
|
||||
public function unique($key = null, $strict = false)
|
||||
{
|
||||
if (! is_null($key)) {
|
||||
return parent::unique($key, $strict);
|
||||
}
|
||||
|
||||
return new static(array_values($this->getDictionary()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns only the models from the collection with the specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function only($keys)
|
||||
{
|
||||
if (is_null($keys)) {
|
||||
return new static($this->items);
|
||||
}
|
||||
|
||||
$dictionary = Arr::only($this->getDictionary(), $keys);
|
||||
|
||||
return new static(array_values($dictionary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all models in the collection except the models with specified keys.
|
||||
*
|
||||
* @param mixed $keys
|
||||
* @return static
|
||||
*/
|
||||
public function except($keys)
|
||||
{
|
||||
$dictionary = Arr::except($this->getDictionary(), $keys);
|
||||
|
||||
return new static(array_values($dictionary));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically visible, attributes hidden across the entire collection.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeHidden($attributes)
|
||||
{
|
||||
return $this->each(function ($model) use ($attributes) {
|
||||
$model->addHidden($attributes);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically hidden, attributes visible across the entire collection.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeVisible($attributes)
|
||||
{
|
||||
return $this->each(function ($model) use ($attributes) {
|
||||
$model->makeVisible($attributes);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a dictionary keyed by primary keys.
|
||||
*
|
||||
* @param \ArrayAccess|array|null $items
|
||||
* @return array
|
||||
*/
|
||||
public function getDictionary($items = null)
|
||||
{
|
||||
$items = is_null($items) ? $this->items : $items;
|
||||
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($items as $value) {
|
||||
$dictionary[$value->getKey()] = $value;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods are intercepted to always return base collections.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get an array with the values of a given key.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string|null $key
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function pluck($value, $key = null)
|
||||
{
|
||||
return $this->toBase()->pluck($value, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the keys of the collection items.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function keys()
|
||||
{
|
||||
return $this->toBase()->keys();
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip the collection together with one or more arrays.
|
||||
*
|
||||
* @param mixed ...$items
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function zip($items)
|
||||
{
|
||||
return call_user_func_array([$this->toBase(), 'zip'], func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse the collection of items into a single array.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function collapse()
|
||||
{
|
||||
return $this->toBase()->collapse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a flattened array of the items in the collection.
|
||||
*
|
||||
* @param int $depth
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function flatten($depth = INF)
|
||||
{
|
||||
return $this->toBase()->flatten($depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the items in the collection.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function flip()
|
||||
{
|
||||
return $this->toBase()->flip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the entities being queued.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getQueueableClass()
|
||||
{
|
||||
if ($this->count() === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$class = get_class($this->first());
|
||||
|
||||
$this->each(function ($model) use ($class) {
|
||||
if (get_class($model) !== $class) {
|
||||
throw new LogicException('Queueing collections with multiple model types is not supported.');
|
||||
}
|
||||
});
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the identifiers for all of the entities.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueueableIds()
|
||||
{
|
||||
return $this->modelKeys();
|
||||
}
|
||||
}
|
||||
193
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php
vendored
Normal file
193
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/GuardsAttributes.php
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait GuardsAttributes
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [];
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = ['*'];
|
||||
|
||||
/**
|
||||
* Indicates if all mass assignment is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $unguarded = false;
|
||||
|
||||
/**
|
||||
* Get the fillable attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFillable()
|
||||
{
|
||||
return $this->fillable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fillable attributes for the model.
|
||||
*
|
||||
* @param array $fillable
|
||||
* @return $this
|
||||
*/
|
||||
public function fillable(array $fillable)
|
||||
{
|
||||
$this->fillable = $fillable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the guarded attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGuarded()
|
||||
{
|
||||
return $this->guarded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the guarded attributes for the model.
|
||||
*
|
||||
* @param array $guarded
|
||||
* @return $this
|
||||
*/
|
||||
public function guard(array $guarded)
|
||||
{
|
||||
$this->guarded = $guarded;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable all mass assignable restrictions.
|
||||
*
|
||||
* @param bool $state
|
||||
* @return void
|
||||
*/
|
||||
public static function unguard($state = true)
|
||||
{
|
||||
static::$unguarded = $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the mass assignment restrictions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function reguard()
|
||||
{
|
||||
static::$unguarded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if current state is "unguarded".
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUnguarded()
|
||||
{
|
||||
return static::$unguarded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given callable while being unguarded.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function unguarded(callable $callback)
|
||||
{
|
||||
if (static::$unguarded) {
|
||||
return $callback();
|
||||
}
|
||||
|
||||
static::unguard();
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
static::reguard();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given attribute may be mass assigned.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isFillable($key)
|
||||
{
|
||||
if (static::$unguarded) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the key is in the "fillable" array, we can of course assume that it's
|
||||
// a fillable attribute. Otherwise, we will check the guarded array when
|
||||
// we need to determine if the attribute is black-listed on the model.
|
||||
if (in_array($key, $this->getFillable())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the attribute is explicitly listed in the "guarded" array then we can
|
||||
// return false immediately. This means this attribute is definitely not
|
||||
// fillable and there is no point in going any further in this method.
|
||||
if ($this->isGuarded($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return empty($this->getFillable()) &&
|
||||
! Str::startsWith($key, '_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key is guarded.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isGuarded($key)
|
||||
{
|
||||
return in_array($key, $this->getGuarded()) || $this->getGuarded() == ['*'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model is totally guarded.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function totallyGuarded()
|
||||
{
|
||||
return count($this->getFillable()) == 0 && $this->getGuarded() == ['*'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fillable attributes of a given array.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function fillableFromArray(array $attributes)
|
||||
{
|
||||
if (count($this->getFillable()) > 0 && ! static::$unguarded) {
|
||||
return array_intersect_key($attributes, array_flip($this->getFillable()));
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
1063
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
vendored
Normal file
1063
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
325
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php
vendored
Normal file
325
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
trait HasEvents
|
||||
{
|
||||
/**
|
||||
* The event map for the model.
|
||||
*
|
||||
* Allows for object-based events for native Eloquent events.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $events = [];
|
||||
|
||||
/**
|
||||
* User exposed observable events.
|
||||
*
|
||||
* These are extra user-defined events observers may subscribe to.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $observables = [];
|
||||
|
||||
/**
|
||||
* Register an observer with the Model.
|
||||
*
|
||||
* @param object|string $class
|
||||
* @return void
|
||||
*/
|
||||
public static function observe($class)
|
||||
{
|
||||
$instance = new static;
|
||||
|
||||
$className = is_string($class) ? $class : get_class($class);
|
||||
|
||||
// When registering a model observer, we will spin through the possible events
|
||||
// and determine if this observer has that method. If it does, we will hook
|
||||
// it into the model's event system, making it convenient to watch these.
|
||||
foreach ($instance->getObservableEvents() as $event) {
|
||||
if (method_exists($class, $event)) {
|
||||
static::registerModelEvent($event, $className.'@'.$event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the observable event names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getObservableEvents()
|
||||
{
|
||||
return array_merge(
|
||||
[
|
||||
'creating', 'created', 'updating', 'updated',
|
||||
'deleting', 'deleted', 'saving', 'saved',
|
||||
'restoring', 'restored',
|
||||
],
|
||||
$this->observables
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the observable event names.
|
||||
*
|
||||
* @param array $observables
|
||||
* @return $this
|
||||
*/
|
||||
public function setObservableEvents(array $observables)
|
||||
{
|
||||
$this->observables = $observables;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an observable event name.
|
||||
*
|
||||
* @param array|mixed $observables
|
||||
* @return void
|
||||
*/
|
||||
public function addObservableEvents($observables)
|
||||
{
|
||||
$this->observables = array_unique(array_merge(
|
||||
$this->observables, is_array($observables) ? $observables : func_get_args()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an observable event name.
|
||||
*
|
||||
* @param array|mixed $observables
|
||||
* @return void
|
||||
*/
|
||||
public function removeObservableEvents($observables)
|
||||
{
|
||||
$this->observables = array_diff(
|
||||
$this->observables, is_array($observables) ? $observables : func_get_args()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a model event with the dispatcher.
|
||||
*
|
||||
* @param string $event
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
protected static function registerModelEvent($event, $callback)
|
||||
{
|
||||
if (isset(static::$dispatcher)) {
|
||||
$name = static::class;
|
||||
|
||||
static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the given event for the model.
|
||||
*
|
||||
* @param string $event
|
||||
* @param bool $halt
|
||||
* @return mixed
|
||||
*/
|
||||
protected function fireModelEvent($event, $halt = true)
|
||||
{
|
||||
if (! isset(static::$dispatcher)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// First, we will get the proper method to call on the event dispatcher, and then we
|
||||
// will attempt to fire a custom, object based event for the given event. If that
|
||||
// returns a result we can return that result, or we'll call the string events.
|
||||
$method = $halt ? 'until' : 'fire';
|
||||
|
||||
$result = $this->filterModelEventResults(
|
||||
$this->fireCustomModelEvent($event, $method)
|
||||
);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! empty($result) ? $result : static::$dispatcher->{$method}(
|
||||
"eloquent.{$event}: ".static::class, $this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire a custom model event for the given event.
|
||||
*
|
||||
* @param string $event
|
||||
* @param string $method
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function fireCustomModelEvent($event, $method)
|
||||
{
|
||||
if (! isset($this->events[$event])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$result = static::$dispatcher->$method(new $this->events[$event]($this));
|
||||
|
||||
if (! is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the model event results.
|
||||
*
|
||||
* @param mixed $result
|
||||
* @return mixed
|
||||
*/
|
||||
protected function filterModelEventResults($result)
|
||||
{
|
||||
if (is_array($result)) {
|
||||
$result = array_filter($result, function ($response) {
|
||||
return ! is_null($response);
|
||||
});
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a saving model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function saving($callback)
|
||||
{
|
||||
static::registerModelEvent('saving', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a saved model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function saved($callback)
|
||||
{
|
||||
static::registerModelEvent('saved', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an updating model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function updating($callback)
|
||||
{
|
||||
static::registerModelEvent('updating', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an updated model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function updated($callback)
|
||||
{
|
||||
static::registerModelEvent('updated', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a creating model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function creating($callback)
|
||||
{
|
||||
static::registerModelEvent('creating', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a created model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function created($callback)
|
||||
{
|
||||
static::registerModelEvent('created', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a deleting model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function deleting($callback)
|
||||
{
|
||||
static::registerModelEvent('deleting', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a deleted model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function deleted($callback)
|
||||
{
|
||||
static::registerModelEvent('deleted', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all of the event listeners for the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function flushEventListeners()
|
||||
{
|
||||
if (! isset(static::$dispatcher)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = new static;
|
||||
|
||||
foreach ($instance->getObservableEvents() as $event) {
|
||||
static::$dispatcher->forget("eloquent.{$event}: ".static::class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event dispatcher instance.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Events\Dispatcher
|
||||
*/
|
||||
public static function getEventDispatcher()
|
||||
{
|
||||
return static::$dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event dispatcher instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Events\Dispatcher $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public static function setEventDispatcher(Dispatcher $dispatcher)
|
||||
{
|
||||
static::$dispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the event dispatcher for models.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function unsetEventDispatcher()
|
||||
{
|
||||
static::$dispatcher = null;
|
||||
}
|
||||
}
|
||||
71
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasGlobalScopes.php
vendored
Normal file
71
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasGlobalScopes.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Database\Eloquent\Scope;
|
||||
|
||||
trait HasGlobalScopes
|
||||
{
|
||||
/**
|
||||
* Register a new global scope on the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Scope|\Closure|string $scope
|
||||
* @param \Closure|null $implementation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function addGlobalScope($scope, Closure $implementation = null)
|
||||
{
|
||||
if (is_string($scope) && ! is_null($implementation)) {
|
||||
return static::$globalScopes[static::class][$scope] = $implementation;
|
||||
} elseif ($scope instanceof Closure) {
|
||||
return static::$globalScopes[static::class][spl_object_hash($scope)] = $scope;
|
||||
} elseif ($scope instanceof Scope) {
|
||||
return static::$globalScopes[static::class][get_class($scope)] = $scope;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Global scope must be an instance of Closure or Scope.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a model has a global scope.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Scope|string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasGlobalScope($scope)
|
||||
{
|
||||
return ! is_null(static::getGlobalScope($scope));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a global scope registered with the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Scope|string $scope
|
||||
* @return \Illuminate\Database\Eloquent\Scope|\Closure|null
|
||||
*/
|
||||
public static function getGlobalScope($scope)
|
||||
{
|
||||
if (is_string($scope)) {
|
||||
return Arr::get(static::$globalScopes, static::class.'.'.$scope);
|
||||
}
|
||||
|
||||
return Arr::get(
|
||||
static::$globalScopes, static::class.'.'.get_class($scope)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global scopes for this class instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getGlobalScopes()
|
||||
{
|
||||
return Arr::get(static::$globalScopes, static::class, []);
|
||||
}
|
||||
}
|
||||
575
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php
vendored
Normal file
575
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||
|
||||
trait HasRelationships
|
||||
{
|
||||
/**
|
||||
* The loaded relationships for the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $relations = [];
|
||||
|
||||
/**
|
||||
* The relationships that should be touched on save.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $touches = [];
|
||||
|
||||
/**
|
||||
* The many to many relationship methods.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $manyMethods = [
|
||||
'belongsToMany', 'morphToMany', 'morphedByMany',
|
||||
'guessBelongsToManyRelation', 'findFirstMethodThatIsntRelation',
|
||||
];
|
||||
|
||||
/**
|
||||
* Define a one-to-one relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $foreignKey
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
*/
|
||||
public function hasOne($related, $foreignKey = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignKey = $foreignKey ?: $this->getForeignKey();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return new HasOne($instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic one-to-one relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
|
||||
*/
|
||||
public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
list($type, $id) = $this->getMorphs($name, $type, $id);
|
||||
|
||||
$table = $instance->getTable();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return new MorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define an inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)
|
||||
{
|
||||
// If no relation name was given, we will use this debug backtrace to extract
|
||||
// the calling method's name and use that as the relationship name as most
|
||||
// of the time this will be what we desire to use for the relationships.
|
||||
if (is_null($relation)) {
|
||||
$relation = $this->guessBelongsToRelation();
|
||||
}
|
||||
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
// If no foreign key was supplied, we can use a backtrace to guess the proper
|
||||
// foreign key name by using the name of the relationship function, which
|
||||
// when combined with an "_id" should conventionally match the columns.
|
||||
if (is_null($foreignKey)) {
|
||||
$foreignKey = Str::snake($relation).'_'.$instance->getKeyName();
|
||||
}
|
||||
|
||||
// Once we have the foreign key names, we'll just create a new Eloquent query
|
||||
// for the related models and returns the relationship instance which will
|
||||
// actually be responsible for retrieving and hydrating every relations.
|
||||
$ownerKey = $ownerKey ?: $instance->getKeyName();
|
||||
|
||||
return new BelongsTo(
|
||||
$instance->newQuery(), $this, $foreignKey, $ownerKey, $relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function morphTo($name = null, $type = null, $id = null)
|
||||
{
|
||||
// If no name is provided, we will use the backtrace to get the function name
|
||||
// since that is most likely the name of the polymorphic interface. We can
|
||||
// use that to get both the class and foreign key that will be utilized.
|
||||
$name = $name ?: $this->guessBelongsToRelation();
|
||||
|
||||
list($type, $id) = $this->getMorphs(
|
||||
Str::snake($name), $type, $id
|
||||
);
|
||||
|
||||
// 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 empty($class = $this->{$type})
|
||||
? $this->morphEagerTo($name, $type, $id)
|
||||
: $this->morphInstanceTo($class, $name, $type, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
protected function morphEagerTo($name, $type, $id)
|
||||
{
|
||||
return new MorphTo(
|
||||
$this->newQuery()->setEagerLoads([]), $this, $id, null, $type, $name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse one-to-one or many relationship.
|
||||
*
|
||||
* @param string $target
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
protected function morphInstanceTo($target, $name, $type, $id)
|
||||
{
|
||||
$instance = $this->newRelatedInstance(
|
||||
static::getActualClassNameForMorph($target)
|
||||
);
|
||||
|
||||
return new MorphTo(
|
||||
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the actual class name for a given morph class.
|
||||
*
|
||||
* @param string $class
|
||||
* @return string
|
||||
*/
|
||||
public static function getActualClassNameForMorph($class)
|
||||
{
|
||||
return Arr::get(Relation::morphMap() ?: [], $class, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the "belongs to" relationship name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function guessBelongsToRelation()
|
||||
{
|
||||
list($one, $two, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
|
||||
return $caller['function'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a one-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $foreignKey
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function hasMany($related, $foreignKey = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignKey = $foreignKey ?: $this->getForeignKey();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return new HasMany(
|
||||
$instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a has-many-through relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $through
|
||||
* @param string|null $firstKey
|
||||
* @param string|null $secondKey
|
||||
* @param string|null $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||
*/
|
||||
public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null, $localKey = null)
|
||||
{
|
||||
$through = new $through;
|
||||
|
||||
$firstKey = $firstKey ?: $this->getForeignKey();
|
||||
|
||||
$secondKey = $secondKey ?: $through->getForeignKey();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
return new HasManyThrough($instance->newQuery(), $this, $through, $firstKey, $secondKey, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic one-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $localKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
*/
|
||||
public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
|
||||
{
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
// Here we will gather up the morph type and ID for the relationship so that we
|
||||
// can properly query the intermediate table of a relation. Finally, we will
|
||||
// get the table and create the relationship instances for the developers.
|
||||
list($type, $id) = $this->getMorphs($name, $type, $id);
|
||||
|
||||
$table = $instance->getTable();
|
||||
|
||||
$localKey = $localKey ?: $this->getKeyName();
|
||||
|
||||
return new MorphMany($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a many-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $table
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function belongsToMany($related, $table = null, $foreignKey = null, $relatedKey = null, $relation = null)
|
||||
{
|
||||
// If no relationship name was passed, we will pull backtraces to get the
|
||||
// name of the calling function. We will use that function name as the
|
||||
// title of this relation since that is a great convention to apply.
|
||||
if (is_null($relation)) {
|
||||
$relation = $this->guessBelongsToManyRelation();
|
||||
}
|
||||
|
||||
// First, we'll need to determine the foreign key and "other key" for the
|
||||
// relationship. Once we have determined the keys we'll make the query
|
||||
// instances as well as the relationship instances we need for this.
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignKey = $foreignKey ?: $this->getForeignKey();
|
||||
|
||||
$relatedKey = $relatedKey ?: $instance->getForeignKey();
|
||||
|
||||
// If no table name was provided, we can guess it by concatenating the two
|
||||
// models using underscores in alphabetical order. The two model names
|
||||
// are transformed to snake case from their default CamelCase also.
|
||||
if (is_null($table)) {
|
||||
$table = $this->joiningTable($related);
|
||||
}
|
||||
|
||||
return new BelongsToMany(
|
||||
$instance->newQuery(), $this, $table, $foreignKey, $relatedKey, $relation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic many-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @param bool $inverse
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function morphToMany($related, $name, $table = null, $foreignKey = null, $relatedKey = null, $inverse = false)
|
||||
{
|
||||
$caller = $this->guessBelongsToManyRelation();
|
||||
|
||||
// First, we will need to determine the foreign key and "other key" for the
|
||||
// relationship. Once we have determined the keys we will make the query
|
||||
// instances, as well as the relationship instances we need for these.
|
||||
$instance = $this->newRelatedInstance($related);
|
||||
|
||||
$foreignKey = $foreignKey ?: $name.'_id';
|
||||
|
||||
$relatedKey = $relatedKey ?: $instance->getForeignKey();
|
||||
|
||||
// Now we're ready to create a new query builder for this related model and
|
||||
// the relationship instances for this relation. This relations will set
|
||||
// appropriate query constraints then entirely manages the hydrations.
|
||||
$table = $table ?: Str::plural($name);
|
||||
|
||||
return new MorphToMany(
|
||||
$instance->newQuery(), $this, $name, $table,
|
||||
$foreignKey, $relatedKey, $caller, $inverse
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a polymorphic, inverse many-to-many relationship.
|
||||
*
|
||||
* @param string $related
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
|
||||
*/
|
||||
public function morphedByMany($related, $name, $table = null, $foreignKey = null, $relatedKey = null)
|
||||
{
|
||||
$foreignKey = $foreignKey ?: $this->getForeignKey();
|
||||
|
||||
// For the inverse of the polymorphic many-to-many relations, we will change
|
||||
// the way we determine the foreign and other keys, as it is the opposite
|
||||
// of the morph-to-many method since we're figuring out these inverses.
|
||||
$relatedKey = $relatedKey ?: $name.'_id';
|
||||
|
||||
return $this->morphToMany($related, $name, $table, $foreignKey, $relatedKey, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship name of the belongs to many.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function guessBelongsToManyRelation()
|
||||
{
|
||||
$caller = Arr::first(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), function ($trace) {
|
||||
return ! in_array($trace['function'], Model::$manyMethods);
|
||||
});
|
||||
|
||||
return ! is_null($caller) ? $caller['function'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the joining table name for a many-to-many relation.
|
||||
*
|
||||
* @param string $related
|
||||
* @return string
|
||||
*/
|
||||
public function joiningTable($related)
|
||||
{
|
||||
// The joining table name, by convention, is simply the snake cased models
|
||||
// sorted alphabetically and concatenated with an underscore, so we can
|
||||
// just sort the models and join them together to get the table name.
|
||||
$models = [
|
||||
Str::snake(class_basename($related)),
|
||||
Str::snake(class_basename($this)),
|
||||
];
|
||||
|
||||
// Now that we have the model names in an array we can just sort them and
|
||||
// use the implode function to join them together with an underscores,
|
||||
// which is typically used by convention within the database system.
|
||||
sort($models);
|
||||
|
||||
return strtolower(implode('_', $models));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model touches a given relation.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return bool
|
||||
*/
|
||||
public function touches($relation)
|
||||
{
|
||||
return in_array($relation, $this->touches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch the owning relations of the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touchOwners()
|
||||
{
|
||||
foreach ($this->touches as $relation) {
|
||||
$this->$relation()->touch();
|
||||
|
||||
if ($this->$relation instanceof self) {
|
||||
$this->$relation->fireModelEvent('saved', false);
|
||||
|
||||
$this->$relation->touchOwners();
|
||||
} elseif ($this->$relation instanceof Collection) {
|
||||
$this->$relation->each(function (Model $relation) {
|
||||
$relation->touchOwners();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the polymorphic relationship columns.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @return array
|
||||
*/
|
||||
protected function getMorphs($name, $type, $id)
|
||||
{
|
||||
return [$type ?: $name.'_type', $id ?: $name.'_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name for polymorphic relations.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphClass()
|
||||
{
|
||||
$morphMap = Relation::morphMap();
|
||||
|
||||
if (! empty($morphMap) && in_array(static::class, $morphMap)) {
|
||||
return array_search(static::class, $morphMap, true);
|
||||
}
|
||||
|
||||
return static::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new model instance for a related model.
|
||||
*
|
||||
* @param string $class
|
||||
* @return mixed
|
||||
*/
|
||||
protected function newRelatedInstance($class)
|
||||
{
|
||||
return tap(new $class, function ($instance) {
|
||||
if (! $instance->getConnectionName()) {
|
||||
$instance->setConnection($this->connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the loaded relations for the instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRelations()
|
||||
{
|
||||
return $this->relations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specified relationship.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRelation($relation)
|
||||
{
|
||||
return $this->relations[$relation];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given relation is loaded.
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function relationLoaded($key)
|
||||
{
|
||||
return array_key_exists($key, $this->relations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specific relationship in the model.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setRelation($relation, $value)
|
||||
{
|
||||
$this->relations[$relation] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the entire relations array on the model.
|
||||
*
|
||||
* @param array $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function setRelations(array $relations)
|
||||
{
|
||||
$this->relations = $relations;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationships that are touched on save.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTouchedRelations()
|
||||
{
|
||||
return $this->touches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relationships that are touched on save.
|
||||
*
|
||||
* @param array $touches
|
||||
* @return $this
|
||||
*/
|
||||
public function setTouchedRelations(array $touches)
|
||||
{
|
||||
$this->touches = $touches;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
125
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasTimestamps.php
vendored
Normal file
125
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasTimestamps.php
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
trait HasTimestamps
|
||||
{
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
/**
|
||||
* Update the model's update timestamp.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function touch()
|
||||
{
|
||||
if (! $this->usesTimestamps()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->updateTimestamps();
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the creation and update timestamps.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function updateTimestamps()
|
||||
{
|
||||
$time = $this->freshTimestamp();
|
||||
|
||||
if (! $this->isDirty(static::UPDATED_AT)) {
|
||||
$this->setUpdatedAt($time);
|
||||
}
|
||||
|
||||
if (! $this->exists && ! $this->isDirty(static::CREATED_AT)) {
|
||||
$this->setCreatedAt($time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the "created at" attribute.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setCreatedAt($value)
|
||||
{
|
||||
$this->{static::CREATED_AT} = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of the "updated at" attribute.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setUpdatedAt($value)
|
||||
{
|
||||
$this->{static::UPDATED_AT} = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh timestamp for the model.
|
||||
*
|
||||
* @return \Carbon\Carbon
|
||||
*/
|
||||
public function freshTimestamp()
|
||||
{
|
||||
return new Carbon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fresh timestamp for the model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function freshTimestampString()
|
||||
{
|
||||
return $this->fromDateTime($this->freshTimestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model uses timestamps.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function usesTimestamps()
|
||||
{
|
||||
return $this->timestamps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtColumn()
|
||||
{
|
||||
return static::CREATED_AT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdatedAtColumn()
|
||||
{
|
||||
return static::UPDATED_AT;
|
||||
}
|
||||
}
|
||||
126
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HidesAttributes.php
vendored
Normal file
126
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HidesAttributes.php
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
trait HidesAttributes
|
||||
{
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be visible in serialization.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $visible = [];
|
||||
|
||||
/**
|
||||
* Get the hidden attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHidden()
|
||||
{
|
||||
return $this->hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hidden attributes for the model.
|
||||
*
|
||||
* @param array $hidden
|
||||
* @return $this
|
||||
*/
|
||||
public function setHidden(array $hidden)
|
||||
{
|
||||
$this->hidden = $hidden;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add hidden attributes for the model.
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function addHidden($attributes = null)
|
||||
{
|
||||
$this->hidden = array_merge(
|
||||
$this->hidden, is_array($attributes) ? $attributes : func_get_args()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the visible attributes for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getVisible()
|
||||
{
|
||||
return $this->visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visible attributes for the model.
|
||||
*
|
||||
* @param array $visible
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible(array $visible)
|
||||
{
|
||||
$this->visible = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add visible attributes for the model.
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function addVisible($attributes = null)
|
||||
{
|
||||
$this->visible = array_merge(
|
||||
$this->visible, is_array($attributes) ? $attributes : func_get_args()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically hidden, attributes visible.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeVisible($attributes)
|
||||
{
|
||||
$this->hidden = array_diff($this->hidden, (array) $attributes);
|
||||
|
||||
if (! empty($this->visible)) {
|
||||
$this->addVisible($attributes);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given, typically visible, attributes hidden.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeHidden($attributes)
|
||||
{
|
||||
$attributes = (array) $attributes;
|
||||
|
||||
$this->visible = array_diff($this->visible, $attributes);
|
||||
|
||||
$this->hidden = array_unique(array_merge($this->hidden, $attributes));
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
290
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php
vendored
Normal file
290
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/QueriesRelationships.php
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
|
||||
trait QueriesRelationships
|
||||
{
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
if (strpos($relation, '.') !== false) {
|
||||
return $this->hasNested($relation, $operator, $count, $boolean, $callback);
|
||||
}
|
||||
|
||||
$relation = $this->getRelationWithoutConstraints($relation);
|
||||
|
||||
// If we only need to check for the existence of the relation, then we can optimize
|
||||
// the subquery to only run a "where exists" clause instead of this full "count"
|
||||
// clause. This will make these queries run much faster compared with a count.
|
||||
$method = $this->canUseExistsForExistenceCheck($operator, $count)
|
||||
? 'getRelationExistenceQuery'
|
||||
: 'getRelationExistenceCountQuery';
|
||||
|
||||
$hasQuery = $relation->{$method}(
|
||||
$relation->getRelated()->newQuery(), $this
|
||||
);
|
||||
|
||||
// Next we will call any given callback as an "anonymous" scope so they can get the
|
||||
// proper logical grouping of the where clauses if needed by this Eloquent query
|
||||
// builder. Then, we will be ready to finalize and return this query instance.
|
||||
if ($callback) {
|
||||
$hasQuery->callScope($callback);
|
||||
}
|
||||
|
||||
return $this->addHasWhere(
|
||||
$hasQuery, $relation, $operator, $count, $boolean
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nested relationship count / exists conditions to the query.
|
||||
*
|
||||
* Sets up recursive call to whereHas until we finish the nested relation.
|
||||
*
|
||||
* @param string $relations
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
protected function hasNested($relations, $operator = '>=', $count = 1, $boolean = 'and', $callback = null)
|
||||
{
|
||||
$relations = explode('.', $relations);
|
||||
|
||||
$closure = function ($q) use (&$closure, &$relations, $operator, $count, $boolean, $callback) {
|
||||
// In order to nest "has", we need to add count relation constraints on the
|
||||
// callback Closure. We'll do this by simply passing the Closure its own
|
||||
// reference to itself so it calls itself recursively on each segment.
|
||||
count($relations) > 1
|
||||
? $q->whereHas(array_shift($relations), $closure)
|
||||
: $q->has(array_shift($relations), $operator, $count, 'and', $callback);
|
||||
};
|
||||
|
||||
return $this->has(array_shift($relations), '>=', 1, $boolean, $closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orHas($relation, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->has($relation, $operator, $count, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param string $boolean
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function doesntHave($relation, $boolean = 'and', Closure $callback = null)
|
||||
{
|
||||
return $this->has($relation, '<', 1, $boolean, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|null $callback
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereHas($relation, Closure $callback = null, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->has($relation, $operator, $count, 'and', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses and an "or".
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure $callback
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function orWhereHas($relation, Closure $callback = null, $operator = '>=', $count = 1)
|
||||
{
|
||||
return $this->has($relation, $operator, $count, 'or', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a relationship count / exists condition to the query with where clauses.
|
||||
*
|
||||
* @param string $relation
|
||||
* @param \Closure|null $callback
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function whereDoesntHave($relation, Closure $callback = null)
|
||||
{
|
||||
return $this->doesntHave($relation, 'and', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subselect queries to count the relations.
|
||||
*
|
||||
* @param mixed $relations
|
||||
* @return $this
|
||||
*/
|
||||
public function withCount($relations)
|
||||
{
|
||||
if (empty($relations)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_null($this->query->columns)) {
|
||||
$this->query->select([$this->query->from.'.*']);
|
||||
}
|
||||
|
||||
$relations = is_array($relations) ? $relations : func_get_args();
|
||||
|
||||
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.
|
||||
$segments = explode(' ', $name);
|
||||
|
||||
unset($alias);
|
||||
|
||||
if (count($segments) == 3 && Str::lower($segments[1]) == 'as') {
|
||||
list($name, $alias) = [$segments[0], $segments[2]];
|
||||
}
|
||||
|
||||
$relation = $this->getRelationWithoutConstraints($name);
|
||||
|
||||
// Here we will get the relationship count 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
|
||||
);
|
||||
|
||||
$query->callScope($constraints);
|
||||
|
||||
$query->mergeConstraintsFrom($relation->getQuery());
|
||||
|
||||
// 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 = snake_case(isset($alias) ? $alias : $name).'_count';
|
||||
|
||||
$this->selectSub($query->toBase(), $column);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the "has" condition where clause to the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $hasQuery
|
||||
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
protected function addHasWhere(Builder $hasQuery, Relation $relation, $operator, $count, $boolean)
|
||||
{
|
||||
$hasQuery->mergeConstraintsFrom($relation->getQuery());
|
||||
|
||||
return $this->canUseExistsForExistenceCheck($operator, $count)
|
||||
? $this->addWhereExistsQuery($hasQuery->toBase(), $boolean, $not = ($operator === '<' && $count === 1))
|
||||
: $this->addWhereCountQuery($hasQuery->toBase(), $operator, $count, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the where constraints from another query to the current query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $from
|
||||
* @return \Illuminate\Database\Eloquent\Builder|static
|
||||
*/
|
||||
public function mergeConstraintsFrom(Builder $from)
|
||||
{
|
||||
$whereBindings = Arr::get(
|
||||
$from->getQuery()->getRawBindings(), 'where', []
|
||||
);
|
||||
|
||||
// Here we have some other query that we want to merge the where constraints from. We will
|
||||
// copy over any where constraints on the query as well as remove any global scopes the
|
||||
// query might have removed. Then we will return ourselves with the finished merging.
|
||||
return $this->withoutGlobalScopes(
|
||||
$from->removedScopes()
|
||||
)->mergeWheres(
|
||||
$from->getQuery()->wheres, $whereBindings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a sub-query count clause to this query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
*/
|
||||
protected function addWhereCountQuery(QueryBuilder $query, $operator = '>=', $count = 1, $boolean = 'and')
|
||||
{
|
||||
$this->query->addBinding($query->getBindings(), 'where');
|
||||
|
||||
return $this->where(
|
||||
new Expression('('.$query->toSql().')'),
|
||||
$operator,
|
||||
is_numeric($count) ? new Expression($count) : $count,
|
||||
$boolean
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "has relation" base query instance.
|
||||
*
|
||||
* @param string $relation
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
protected function getRelationWithoutConstraints($relation)
|
||||
{
|
||||
return Relation::noConstraints(function () use ($relation) {
|
||||
return $this->getModel()->{$relation}();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we can run an "exists" query to optimize performance.
|
||||
*
|
||||
* @param string $operator
|
||||
* @param int $count
|
||||
* @return bool
|
||||
*/
|
||||
protected function canUseExistsForExistenceCheck($operator, $count)
|
||||
{
|
||||
return ($operator === '>=' || $operator === '<') && $count === 1;
|
||||
}
|
||||
}
|
||||
253
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factory.php
vendored
Normal file
253
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factory.php
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
<?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 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 short-name.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param callable $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function defineAs($class, $name, callable $attributes)
|
||||
{
|
||||
return $this->define($class, $attributes, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a class with a given set of attributes.
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $attributes
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function define($class, callable $attributes, $name = 'default')
|
||||
{
|
||||
$this->definitions[$class][$name] = $attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a state with a given set of attributes.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $state
|
||||
* @param callable $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function state($class, $state, callable $attributes)
|
||||
{
|
||||
$this->states[$class][$state] = $attributes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 and type and persist it to the database.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function createAs($class, $name, array $attributes = [])
|
||||
{
|
||||
return $this->of($class, $name)->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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of the given model and type.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function makeAs($class, $name, array $attributes = [])
|
||||
{
|
||||
return $this->of($class, $name)->make($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw attribute array for a given named model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
public function rawOf($class, $name, array $attributes = [])
|
||||
{
|
||||
return $this->raw($class, $attributes, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw attribute array for a given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param array $attributes
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function raw($class, array $attributes = [], $name = 'default')
|
||||
{
|
||||
return array_merge(
|
||||
call_user_func($this->definitions[$class][$name], $this->faker), $attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder for the given model.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $name
|
||||
* @return \Illuminate\Database\Eloquent\FactoryBuilder
|
||||
*/
|
||||
public function of($class, $name = 'default')
|
||||
{
|
||||
return new FactoryBuilder($class, $name, $this->definitions, $this->states, $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)
|
||||
{
|
||||
return $this->define($offset, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @return void
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->definitions[$offset]);
|
||||
}
|
||||
}
|
||||
283
vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php
vendored
Normal file
283
vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Closure;
|
||||
use Faker\Generator as Faker;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
||||
class FactoryBuilder
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The model definitions in the container.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $definitions;
|
||||
|
||||
/**
|
||||
* The model being built.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $class;
|
||||
|
||||
/**
|
||||
* The name of the model being built.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'default';
|
||||
|
||||
/**
|
||||
* The model states.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $states;
|
||||
|
||||
/**
|
||||
* 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 string $name
|
||||
* @param array $definitions
|
||||
* @param array $states
|
||||
* @param \Faker\Generator $faker
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($class, $name, array $definitions, array $states, Faker $faker)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->class = $class;
|
||||
$this->faker = $faker;
|
||||
$this->states = $states;
|
||||
$this->definitions = $definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 mixed
|
||||
*/
|
||||
public function create(array $attributes = [])
|
||||
{
|
||||
$results = $this->make($attributes);
|
||||
|
||||
if ($results instanceof Model) {
|
||||
$this->store(collect([$results]));
|
||||
} else {
|
||||
$this->store($results);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
$model->setConnection($model->newQueryWithoutScopes()->getConnection()->getName());
|
||||
|
||||
$model->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a collection of models.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function make(array $attributes = [])
|
||||
{
|
||||
if ($this->amount === null) {
|
||||
return $this->makeInstance($attributes);
|
||||
}
|
||||
|
||||
if ($this->amount < 1) {
|
||||
return (new $this->class)->newCollection();
|
||||
}
|
||||
|
||||
return (new $this->class)->newCollection(array_map(function () use ($attributes) {
|
||||
return $this->makeInstance($attributes);
|
||||
}, range(1, $this->amount)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected function getRawAttributes(array $attributes = [])
|
||||
{
|
||||
$definition = call_user_func(
|
||||
$this->definitions[$this->class][$this->name],
|
||||
$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
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function makeInstance(array $attributes = [])
|
||||
{
|
||||
return Model::unguarded(function () use ($attributes) {
|
||||
if (! isset($this->definitions[$this->class][$this->name])) {
|
||||
throw new InvalidArgumentException("Unable to locate factory with name [{$this->name}] [{$this->class}].");
|
||||
}
|
||||
|
||||
return new $this->class(
|
||||
$this->getRawAttributes($attributes)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the active states to the model definition array.
|
||||
*
|
||||
* @param array $definition
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function applyStates(array $definition, array $attributes = [])
|
||||
{
|
||||
foreach ($this->activeStates as $state) {
|
||||
if (! isset($this->states[$this->class][$state])) {
|
||||
throw new InvalidArgumentException("Unable to locate [{$state}] state for [{$this->class}].");
|
||||
}
|
||||
|
||||
$definition = array_merge($definition, call_user_func(
|
||||
$this->states[$this->class][$state],
|
||||
$this->faker, $attributes
|
||||
));
|
||||
}
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand all attributes to their underlying values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function expandAttributes(array $attributes)
|
||||
{
|
||||
foreach ($attributes as &$attribute) {
|
||||
if ($attribute instanceof Closure) {
|
||||
$attribute = $attribute($attributes);
|
||||
}
|
||||
|
||||
if ($attribute instanceof static) {
|
||||
$attribute = $attribute->create()->getKey();
|
||||
}
|
||||
|
||||
if ($attribute instanceof Model) {
|
||||
$attribute = $attribute->getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
35
vendor/laravel/framework/src/Illuminate/Database/Eloquent/JsonEncodingException.php
vendored
Normal file
35
vendor/laravel/framework/src/Illuminate/Database/Eloquent/JsonEncodingException.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class JsonEncodingException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Create a new JSON encoding exception for the model.
|
||||
*
|
||||
* @param mixed $model
|
||||
* @param string $message
|
||||
* @return static
|
||||
*/
|
||||
public static function forModel($model, $message)
|
||||
{
|
||||
return new static('Error encoding model ['.get_class($model).'] with ID ['.$model->getKey().'] to JSON: '.$message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JSON encoding exception for an attribute.
|
||||
*
|
||||
* @param mixed $model
|
||||
* @param mixed $key
|
||||
* @param string $message
|
||||
* @return static
|
||||
*/
|
||||
public static function forAttribute($model, $key, $message)
|
||||
{
|
||||
$class = get_class($model);
|
||||
|
||||
return new static("Unable to encode attribute [{$key}] for model [{$class}] to JSON: {$message}.");
|
||||
}
|
||||
}
|
||||
10
vendor/laravel/framework/src/Illuminate/Database/Eloquent/MassAssignmentException.php
vendored
Executable file
10
vendor/laravel/framework/src/Illuminate/Database/Eloquent/MassAssignmentException.php
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class MassAssignmentException extends RuntimeException
|
||||
{
|
||||
//
|
||||
}
|
||||
1394
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
vendored
Normal file
1394
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
65
vendor/laravel/framework/src/Illuminate/Database/Eloquent/ModelNotFoundException.php
vendored
Executable file
65
vendor/laravel/framework/src/Illuminate/Database/Eloquent/ModelNotFoundException.php
vendored
Executable file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class ModelNotFoundException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Name of the affected Eloquent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* The affected model IDs.
|
||||
*
|
||||
* @var int|array
|
||||
*/
|
||||
protected $ids;
|
||||
|
||||
/**
|
||||
* Set the affected Eloquent model and instance ids.
|
||||
*
|
||||
* @param string $model
|
||||
* @param int|array $ids
|
||||
* @return $this
|
||||
*/
|
||||
public function setModel($model, $ids = [])
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->ids = array_wrap($ids);
|
||||
|
||||
$this->message = "No query results for model [{$model}]";
|
||||
|
||||
if (count($this->ids) > 0) {
|
||||
$this->message .= ' '.implode(', ', $this->ids);
|
||||
} else {
|
||||
$this->message .= '.';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the affected Eloquent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getModel()
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the affected Eloquent model IDs.
|
||||
*
|
||||
* @return int|array
|
||||
*/
|
||||
public function getIds()
|
||||
{
|
||||
return $this->ids;
|
||||
}
|
||||
}
|
||||
29
vendor/laravel/framework/src/Illuminate/Database/Eloquent/QueueEntityResolver.php
vendored
Normal file
29
vendor/laravel/framework/src/Illuminate/Database/Eloquent/QueueEntityResolver.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use Illuminate\Contracts\Queue\EntityNotFoundException;
|
||||
use Illuminate\Contracts\Queue\EntityResolver as EntityResolverContract;
|
||||
|
||||
class QueueEntityResolver implements EntityResolverContract
|
||||
{
|
||||
/**
|
||||
* Resolve the entity for the given ID.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $id
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Queue\EntityNotFoundException
|
||||
*/
|
||||
public function resolve($type, $id)
|
||||
{
|
||||
$instance = (new $type)->find($id);
|
||||
|
||||
if ($instance) {
|
||||
return $instance;
|
||||
}
|
||||
|
||||
throw new EntityNotFoundException($type, $id);
|
||||
}
|
||||
}
|
||||
22
vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php
vendored
Executable file
22
vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class RelationNotFoundException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param mixed $model
|
||||
* @param string $relation
|
||||
* @return static
|
||||
*/
|
||||
public static function make($model, $relation)
|
||||
{
|
||||
$class = get_class($model);
|
||||
|
||||
return new static("Call to undefined relationship [{$relation}] on model [{$class}].");
|
||||
}
|
||||
}
|
||||
359
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php
vendored
Executable file
359
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsTo.php
vendored
Executable file
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class BelongsTo extends Relation
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* The child model instance of the relation.
|
||||
*/
|
||||
protected $child;
|
||||
|
||||
/**
|
||||
* The foreign key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The associated key on the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $ownerKey;
|
||||
|
||||
/**
|
||||
* The name of the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relation;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new belongs to relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $child
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $relation
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $child, $foreignKey, $ownerKey, $relation)
|
||||
{
|
||||
$this->ownerKey = $ownerKey;
|
||||
$this->relation = $relation;
|
||||
$this->foreignKey = $foreignKey;
|
||||
|
||||
// In the underlying base relationship class, this variable is referred to as
|
||||
// the "parent" since most relationships are not inversed. But, since this
|
||||
// one is we will create a "child" variable for much better readability.
|
||||
$this->child = $child;
|
||||
|
||||
parent::__construct($query, $child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->query->first() ?: $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
// For belongs to relationships, which are essentially the inverse of has one
|
||||
// or has many relationships, we need to actually query on the primary key
|
||||
// of the related models matching on the foreign key that's on a parent.
|
||||
$table = $this->related->getTable();
|
||||
|
||||
$this->query->where($table.'.'.$this->ownerKey, '=', $this->child->{$this->foreignKey});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
// We'll grab the primary key name of the related models since it could be set to
|
||||
// a non-standard name and not "id". We will then construct the constraint for
|
||||
// our eagerly loading query so it returns the proper models from execution.
|
||||
$key = $this->related->getTable().'.'.$this->ownerKey;
|
||||
|
||||
$this->query->whereIn($key, $this->getEagerModelKeys($models));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather the keys from an array of related models.
|
||||
*
|
||||
* @param array $models
|
||||
* @return array
|
||||
*/
|
||||
protected function getEagerModelKeys(array $models)
|
||||
{
|
||||
$keys = [];
|
||||
|
||||
// First we need to gather all of the keys from the parent models so we know what
|
||||
// to query for via the eager loading query. We will add them to an array then
|
||||
// execute a "where in" statement to gather up all of those related records.
|
||||
foreach ($models as $model) {
|
||||
if (! is_null($value = $model->{$this->foreignKey})) {
|
||||
$keys[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no keys that were not null we will just return an array with null
|
||||
// so this query wont fail plus returns zero results, which should be what the
|
||||
// developer expects to happen in this situation. Otherwise we'll sort them.
|
||||
if (count($keys) === 0) {
|
||||
return [null];
|
||||
}
|
||||
|
||||
sort($keys);
|
||||
|
||||
return array_values(array_unique($keys));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
$foreign = $this->foreignKey;
|
||||
|
||||
$owner = $this->ownerKey;
|
||||
|
||||
// First we will get to build a dictionary of the child models by their primary
|
||||
// key of the relationship, then we can easily match the children back onto
|
||||
// the parents using that dictionary and the primary key of the children.
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->getAttribute($owner)] = $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}]);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the parent model on the relationship.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(array $attributes)
|
||||
{
|
||||
return $this->getResults()->fill($attributes)->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the model instance to the given parent.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model|int|string $model
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function associate($model)
|
||||
{
|
||||
$ownerKey = $model instanceof Model ? $model->getAttribute($this->ownerKey) : $model;
|
||||
|
||||
$this->child->setAttribute($this->foreignKey, $ownerKey);
|
||||
|
||||
if ($model instanceof Model) {
|
||||
$this->child->setRelation($this->relation, $model);
|
||||
}
|
||||
|
||||
return $this->child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissociate previously associated model from the given parent.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function dissociate()
|
||||
{
|
||||
$this->child->setAttribute($this->foreignKey, null);
|
||||
|
||||
return $this->child->setRelation($this->relation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a 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 ($parentQuery->getQuery()->from == $query->getQuery()->from) {
|
||||
return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedForeignKey(), '=', $query->getModel()->getTable().'.'.$this->ownerKey
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$query->select($columns)->from(
|
||||
$query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash()
|
||||
);
|
||||
|
||||
$query->getModel()->setTable($hash);
|
||||
|
||||
return $query->whereColumn(
|
||||
$hash.'.'.$query->getModel()->getKeyName(), '=', $this->getQualifiedForeignKey()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function relationHasIncrementingId()
|
||||
{
|
||||
return $this->related->getIncrementing() &&
|
||||
$this->related->getKeyType() === 'int';
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKey()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified foreign key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKey()
|
||||
{
|
||||
return $this->child->getTable().'.'.$this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOwnerKey()
|
||||
{
|
||||
return $this->ownerKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified associated key of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedOwnerKeyName()
|
||||
{
|
||||
return $this->related->getTable().'.'.$this->ownerKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelation()
|
||||
{
|
||||
return $this->relation;
|
||||
}
|
||||
}
|
||||
911
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
vendored
Executable file
911
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php
vendored
Executable file
@@ -0,0 +1,911 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class BelongsToMany extends Relation
|
||||
{
|
||||
use Concerns\InteractsWithPivotTable;
|
||||
|
||||
/**
|
||||
* The intermediate table for the relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The foreign key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The associated key of the relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relatedKey;
|
||||
|
||||
/**
|
||||
* The "name" of the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relationName;
|
||||
|
||||
/**
|
||||
* The pivot table columns to retrieve.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pivotColumns = [];
|
||||
|
||||
/**
|
||||
* Any pivot table restrictions for where clauses.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pivotWheres = [];
|
||||
|
||||
/**
|
||||
* Any pivot table restrictions for whereIn clauses.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pivotWhereIns = [];
|
||||
|
||||
/**
|
||||
* The custom pivot table column for the created_at timestamp.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $pivotCreatedAt;
|
||||
|
||||
/**
|
||||
* The custom pivot table column for the updated_at timestamp.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $pivotUpdatedAt;
|
||||
|
||||
/**
|
||||
* The class name of the custom pivot model to use for the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $using;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new belongs to many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $table
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @param string $relationName
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $table, $foreignKey, $relatedKey, $relationName = null)
|
||||
{
|
||||
$this->table = $table;
|
||||
$this->relatedKey = $relatedKey;
|
||||
$this->foreignKey = $foreignKey;
|
||||
$this->relationName = $relationName;
|
||||
|
||||
parent::__construct($query, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
$this->performJoin();
|
||||
|
||||
if (static::$constraints) {
|
||||
$this->addWhereConstraints();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the join clause for the relation query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder|null $query
|
||||
* @return $this
|
||||
*/
|
||||
protected function performJoin($query = null)
|
||||
{
|
||||
$query = $query ?: $this->query;
|
||||
|
||||
// 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->related->getKeyName();
|
||||
|
||||
$query->join($this->table, $key, '=', $this->getQualifiedRelatedKeyName());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the where clause for the relation query.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function addWhereConstraints()
|
||||
{
|
||||
$this->query->where(
|
||||
$this->getQualifiedForeignKeyName(), '=', $this->parent->getKey()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$this->query->whereIn($this->getQualifiedForeignKeyName(), $this->getKeys($models));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
$dictionary = $this->buildDictionary($results);
|
||||
|
||||
// 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.
|
||||
foreach ($models as $model) {
|
||||
if (isset($dictionary[$key = $model->getKey()])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->related->newCollection($dictionary[$key])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build model dictionary keyed by the relation's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return array
|
||||
*/
|
||||
protected function buildDictionary(Collection $results)
|
||||
{
|
||||
// First we will build a dictionary of child models keyed by the foreign key
|
||||
// of the relation so that we will easily and quickly match them to their
|
||||
// parents without having a possibly slow inner loops for every models.
|
||||
$dictionary = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->pivot->{$this->foreignKey}][] = $result;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the custom pivot model to use for the relationship.
|
||||
*
|
||||
* @param string $class
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function using($class)
|
||||
{
|
||||
$this->using = $class;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a where clause for a pivot table column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $operator
|
||||
* @param mixed $value
|
||||
* @param string $boolean
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function wherePivot($column, $operator = null, $value = null, $boolean = 'and')
|
||||
{
|
||||
$this->pivotWheres[] = func_get_args();
|
||||
|
||||
return $this->where($this->table.'.'.$column, $operator, $value, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a "where in" clause for a pivot table column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param mixed $values
|
||||
* @param string $boolean
|
||||
* @param bool $not
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function wherePivotIn($column, $values, $boolean = 'and', $not = false)
|
||||
{
|
||||
$this->pivotWhereIns[] = func_get_args();
|
||||
|
||||
return $this->whereIn($this->table.'.'.$column, $values, $boolean, $not);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an "or where" clause for a pivot table column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param string $operator
|
||||
* @param mixed $value
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function orWherePivot($column, $operator = null, $value = null)
|
||||
{
|
||||
return $this->wherePivot($column, $operator, $value, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an "or where in" clause for a pivot table column.
|
||||
*
|
||||
* @param string $column
|
||||
* @param mixed $values
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function orWherePivotIn($column, $values)
|
||||
{
|
||||
return $this->wherePivotIn($column, $values, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or return new instance of the related model.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function findOrNew($id, $columns = ['*'])
|
||||
{
|
||||
if (is_null($instance = $this->find($id, $columns))) {
|
||||
$instance = $this->related->newInstance();
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related model record matching the attributes or instantiate it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related record matching the attributes or create it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $joining
|
||||
* @param bool $touch
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrCreate(array $attributes, array $joining = [], $touch = true)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->create($attributes, $joining, $touch);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a related record matching the attributes, and fill it with values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @param array $joining
|
||||
* @param bool $touch
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function updateOrCreate(array $attributes, array $values = [], array $joining = [], $touch = true)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
return $this->create($values, $joining, $touch);
|
||||
}
|
||||
|
||||
$instance->fill($values);
|
||||
|
||||
$instance->save(['touch' => false]);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|null
|
||||
*/
|
||||
public function find($id, $columns = ['*'])
|
||||
{
|
||||
return is_array($id) ? $this->findMany($id, $columns) : $this->where(
|
||||
$this->getRelated()->getQualifiedKeyName(), '=', $id
|
||||
)->first($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find multiple related models by their primary keys.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function findMany($ids, $columns = ['*'])
|
||||
{
|
||||
return empty($ids) ? $this->getRelated()->newCollection() : $this->whereIn(
|
||||
$this->getRelated()->getQualifiedKeyName(), $ids
|
||||
)->get($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or throw an exception.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findOrFail($id, $columns = ['*'])
|
||||
{
|
||||
$result = $this->find($id, $columns);
|
||||
|
||||
if (is_array($id)) {
|
||||
if (count($result) == count(array_unique($id))) {
|
||||
return $result;
|
||||
}
|
||||
} elseif (! is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return mixed
|
||||
*/
|
||||
public function first($columns = ['*'])
|
||||
{
|
||||
$results = $this->take(1)->get($columns);
|
||||
|
||||
return count($results) > 0 ? $results->first() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result or throw an exception.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function firstOrFail($columns = ['*'])
|
||||
{
|
||||
if (! is_null($model = $this->first($columns))) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a "select" statement.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
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
|
||||
// models with the result of those columns as a separate model relation.
|
||||
$columns = $this->query->getQuery()->columns ? [] : $columns;
|
||||
|
||||
$builder = $this->query->applyScopes();
|
||||
|
||||
$models = $builder->addSelect(
|
||||
$this->shouldSelect($columns)
|
||||
)->getModels();
|
||||
|
||||
$this->hydratePivotRelation($models);
|
||||
|
||||
// If we actually found models we will also eager load any relationships that
|
||||
// have been specified as needing to be eager loaded. This will solve the
|
||||
// n + 1 query problem for the developer and also increase performance.
|
||||
if (count($models) > 0) {
|
||||
$models = $builder->eagerLoadRelations($models);
|
||||
}
|
||||
|
||||
return $this->related->newCollection($models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the select columns for the relation query.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
protected function shouldSelect(array $columns = ['*'])
|
||||
{
|
||||
if ($columns == ['*']) {
|
||||
$columns = [$this->related->getTable().'.*'];
|
||||
}
|
||||
|
||||
return array_merge($columns, $this->aliasedPivotColumns());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pivot columns for the relation.
|
||||
*
|
||||
* "pivot_" is prefixed ot each column for easy removal later.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function aliasedPivotColumns()
|
||||
{
|
||||
$defaults = [$this->foreignKey, $this->relatedKey];
|
||||
|
||||
return collect(array_merge($defaults, $this->pivotColumns))->map(function ($column) {
|
||||
return $this->table.'.'.$column.' as pivot_'.$column;
|
||||
})->unique()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginator for the "select" statement.
|
||||
*
|
||||
* @param int $perPage
|
||||
* @param array $columns
|
||||
* @param string $pageName
|
||||
* @param int|null $page
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return tap($this->query->paginate($perPage, $columns, $pageName, $page), function ($paginator) {
|
||||
$this->hydratePivotRelation($paginator->items());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the given query into a simple paginator.
|
||||
*
|
||||
* @param int $perPage
|
||||
* @param array $columns
|
||||
* @param string $pageName
|
||||
* @param int|null $page
|
||||
* @return \Illuminate\Contracts\Pagination\Paginator
|
||||
*/
|
||||
public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return tap($this->query->simplePaginate($perPage, $columns, $pageName, $page), function ($paginator) {
|
||||
$this->hydratePivotRelation($paginator->items());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Chunk the results of the query.
|
||||
*
|
||||
* @param int $count
|
||||
* @param callable $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function chunk($count, callable $callback)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect());
|
||||
|
||||
return $this->query->chunk($count, function ($results) use ($callback) {
|
||||
$this->hydratePivotRelation($results->all());
|
||||
|
||||
return $callback($results);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate the pivot table relationship on the models.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
protected function hydratePivotRelation(array $models)
|
||||
{
|
||||
// To hydrate the pivot relationship, we will just gather the pivot attributes
|
||||
// and create a new Pivot model, which is basically a dynamic model that we
|
||||
// will set the attributes, table, and connections on it so it will work.
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation('pivot', $this->newExistingPivot(
|
||||
$this->migratePivotAttributes($model)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pivot attributes from a model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return array
|
||||
*/
|
||||
protected function migratePivotAttributes(Model $model)
|
||||
{
|
||||
$values = [];
|
||||
|
||||
foreach ($model->getAttributes() as $key => $value) {
|
||||
// To get the pivots attributes we will just take any of the attributes which
|
||||
// begin with "pivot_" and add those to this arrays, as well as unsetting
|
||||
// them from the parent's models since they exist in a different table.
|
||||
if (strpos($key, 'pivot_') === 0) {
|
||||
$values[substr($key, 6)] = $value;
|
||||
|
||||
unset($model->$key);
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're touching the parent model, touch.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touchIfTouching()
|
||||
{
|
||||
if ($this->touchingParent()) {
|
||||
$this->getParent()->touch();
|
||||
}
|
||||
|
||||
if ($this->getParent()->touches($this->relationName)) {
|
||||
$this->touch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we should touch the parent on sync.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function touchingParent()
|
||||
{
|
||||
return $this->getRelated()->touches($this->guessInverseRelation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to guess the name of the inverse of the relation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function guessInverseRelation()
|
||||
{
|
||||
return Str::camel(Str::plural(class_basename($this->getParent())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch all of the related models for the relationship.
|
||||
*
|
||||
* E.g.: Touch all roles associated with this user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touch()
|
||||
{
|
||||
$key = $this->getRelated()->getKeyName();
|
||||
|
||||
$columns = [
|
||||
$this->related->getUpdatedAtColumn() => $this->related->freshTimestampString(),
|
||||
];
|
||||
|
||||
// If we actually have IDs for the relation, we will run the query to update all
|
||||
// the related model's timestamps, to make sure these all reflect the changes
|
||||
// to the parent models. This will help us keep any caching synced up here.
|
||||
if (count($ids = $this->allRelatedIds()) > 0) {
|
||||
$this->getRelated()->newQuery()->whereIn($key, $ids)->update($columns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the IDs for the related models.
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function allRelatedIds()
|
||||
{
|
||||
$related = $this->getRelated();
|
||||
|
||||
return $this->getQuery()->select(
|
||||
$related->getQualifiedKeyName()
|
||||
)->pluck($related->getKeyName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a new model and attach it to the parent model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @param array $pivotAttributes
|
||||
* @param bool $touch
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function save(Model $model, array $pivotAttributes = [], $touch = true)
|
||||
{
|
||||
$model->save(['touch' => false]);
|
||||
|
||||
$this->attach($model->getKey(), $pivotAttributes, $touch);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an array of new models and attach them to the parent model.
|
||||
*
|
||||
* @param \Illuminate\Support\Collection|array $models
|
||||
* @param array $pivotAttributes
|
||||
* @return array
|
||||
*/
|
||||
public function saveMany($models, array $pivotAttributes = [])
|
||||
{
|
||||
foreach ($models as $key => $model) {
|
||||
$this->save($model, (array) Arr::get($pivotAttributes, $key), false);
|
||||
}
|
||||
|
||||
$this->touchIfTouching();
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $joining
|
||||
* @param bool $touch
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function create(array $attributes, array $joining = [], $touch = true)
|
||||
{
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
|
||||
// Once we save the related model, we need to attach it to the base model via
|
||||
// through intermediate table so we'll use the existing "attach" method to
|
||||
// accomplish this which will insert the record and any more attributes.
|
||||
$instance->save(['touch' => false]);
|
||||
|
||||
$this->attach($instance->getKey(), $joining, $touch);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of new instances of the related models.
|
||||
*
|
||||
* @param array $records
|
||||
* @param array $joinings
|
||||
* @return array
|
||||
*/
|
||||
public function createMany(array $records, array $joinings = [])
|
||||
{
|
||||
$instances = [];
|
||||
|
||||
foreach ($records as $key => $record) {
|
||||
$instances[] = $this->create($record, (array) Arr::get($joinings, $key), false);
|
||||
}
|
||||
|
||||
$this->touchIfTouching();
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a 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 ($parentQuery->getQuery()->from == $query->getQuery()->from) {
|
||||
return $this->getRelationExistenceQueryForSelfJoin($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
$this->performJoin($query);
|
||||
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForSelfJoin(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$query->select($columns);
|
||||
|
||||
$query->from($this->related->getTable().' as '.$hash = $this->getRelationCountHash());
|
||||
|
||||
$this->related->setTable($hash);
|
||||
|
||||
$this->performJoin($query);
|
||||
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for comparing against the parent key in "has" query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExistenceCompareKey()
|
||||
{
|
||||
return $this->getQualifiedForeignKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param mixed $createdAt
|
||||
* @param mixed $updatedAt
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function withTimestamps($createdAt = null, $updatedAt = null)
|
||||
{
|
||||
$this->pivotCreatedAt = $createdAt;
|
||||
$this->pivotUpdatedAt = $updatedAt;
|
||||
|
||||
return $this->withPivot($this->createdAt(), $this->updatedAt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createdAt()
|
||||
{
|
||||
return $this->pivotCreatedAt ?: $this->parent->getCreatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function updatedAt()
|
||||
{
|
||||
return $this->pivotUpdatedAt ?: $this->parent->getUpdatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified foreign key for the relation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKeyName()
|
||||
{
|
||||
return $this->table.'.'.$this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified "related key" for the relation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedRelatedKeyName()
|
||||
{
|
||||
return $this->table.'.'.$this->relatedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the intermediate table for the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship name for the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelationName()
|
||||
{
|
||||
return $this->relationName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Collection as BaseCollection;
|
||||
|
||||
trait InteractsWithPivotTable
|
||||
{
|
||||
/**
|
||||
* Toggles a model (or models) from the parent.
|
||||
*
|
||||
* Each existing model is detached, and non existing ones are attached.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @param bool $touch
|
||||
* @return array
|
||||
*/
|
||||
public function toggle($ids, $touch = true)
|
||||
{
|
||||
$changes = [
|
||||
'attached' => [], 'detached' => [],
|
||||
];
|
||||
|
||||
$records = $this->formatRecordsList((array) $this->parseIds($ids));
|
||||
|
||||
// Next, we will determine which IDs should get removed from the join table by
|
||||
// checking which of the given ID/records is in the list of current records
|
||||
// and removing all of those rows from this "intermediate" joining table.
|
||||
$detach = array_values(array_intersect(
|
||||
$this->newPivotQuery()->pluck($this->relatedKey)->all(),
|
||||
array_keys($records)
|
||||
));
|
||||
|
||||
if (count($detach) > 0) {
|
||||
$this->detach($detach, false);
|
||||
|
||||
$changes['detached'] = $this->castKeys($detach);
|
||||
}
|
||||
|
||||
// Finally, for all of the records which were not "detached", we'll attach the
|
||||
// records into the intermediate table. Then, we will add those attaches to
|
||||
// this change list and get ready to return these results to the callers.
|
||||
$attach = array_diff_key($records, array_flip($detach));
|
||||
|
||||
if (count($attach) > 0) {
|
||||
$this->attach($attach, [], false);
|
||||
|
||||
$changes['attached'] = array_keys($attach);
|
||||
}
|
||||
|
||||
// Once we have finished attaching or detaching the records, we will see if we
|
||||
// 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 ($touch && (count($changes['attached']) ||
|
||||
count($changes['detached']))) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the intermediate tables with a list of IDs without detaching.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection|array $ids
|
||||
* @return array
|
||||
*/
|
||||
public function syncWithoutDetaching($ids)
|
||||
{
|
||||
return $this->sync($ids, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the intermediate tables with a list of IDs or collection of models.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|array $ids
|
||||
* @param bool $detaching
|
||||
* @return array
|
||||
*/
|
||||
public function sync($ids, $detaching = true)
|
||||
{
|
||||
$changes = [
|
||||
'attached' => [], 'detached' => [], 'updated' => [],
|
||||
];
|
||||
|
||||
// First we need to attach any of the associated models that are not currently
|
||||
// in this joining table. We'll spin through the given IDs, checking to see
|
||||
// if they exist in the array of current ones, and if not we will insert.
|
||||
$current = $this->newPivotQuery()->pluck(
|
||||
$this->relatedKey
|
||||
)->all();
|
||||
|
||||
$detach = array_diff($current, array_keys(
|
||||
$records = $this->formatRecordsList((array) $this->parseIds($ids))
|
||||
));
|
||||
|
||||
// Next, we will take the differences of the currents and given IDs and detach
|
||||
// all of the entities that exist in the "current" array but are not in the
|
||||
// array of the new IDs given to the method which will complete the sync.
|
||||
if ($detaching && count($detach) > 0) {
|
||||
$this->detach($detach);
|
||||
|
||||
$changes['detached'] = $this->castKeys($detach);
|
||||
}
|
||||
|
||||
// Now we are finally ready to attach the new records. Note that we'll disable
|
||||
// touching until after the entire operation is complete so we don't fire a
|
||||
// ton of touch operations until we are totally done syncing the records.
|
||||
$changes = array_merge(
|
||||
$changes, $this->attachNew($records, $current, false)
|
||||
);
|
||||
|
||||
// Once we have finished attaching or detaching the records, we will see if we
|
||||
// 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'])) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the sync / toggle record list so that it is keyed by ID.
|
||||
*
|
||||
* @param array $records
|
||||
* @return array
|
||||
*/
|
||||
protected function formatRecordsList(array $records)
|
||||
{
|
||||
return collect($records)->mapWithKeys(function ($attributes, $id) {
|
||||
if (! is_array($attributes)) {
|
||||
list($id, $attributes) = [$attributes, []];
|
||||
}
|
||||
|
||||
return [$id => $attributes];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach all of the records that aren't in the given current records.
|
||||
*
|
||||
* @param array $records
|
||||
* @param array $current
|
||||
* @param bool $touch
|
||||
* @return array
|
||||
*/
|
||||
protected function attachNew(array $records, array $current, $touch = true)
|
||||
{
|
||||
$changes = ['attached' => [], 'updated' => []];
|
||||
|
||||
foreach ($records as $id => $attributes) {
|
||||
// If the ID is not in the list of existing pivot IDs, we will insert a new pivot
|
||||
// record, otherwise, we will just update this existing record on this joining
|
||||
// table, so that the developers will easily update these records pain free.
|
||||
if (! in_array($id, $current)) {
|
||||
$this->attach($id, $attributes, $touch);
|
||||
|
||||
$changes['attached'][] = $this->castKey($id);
|
||||
}
|
||||
|
||||
// Now we'll try to update an existing pivot record with the attributes that were
|
||||
// given to the method. If the model is actually updated we will add it to the
|
||||
// list of updated pivot records so we return them back out to the consumer.
|
||||
elseif (count($attributes) > 0 &&
|
||||
$this->updateExistingPivot($id, $attributes, $touch)) {
|
||||
$changes['updated'][] = $this->castKey($id);
|
||||
}
|
||||
}
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing pivot record on the table.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $attributes
|
||||
* @param bool $touch
|
||||
* @return int
|
||||
*/
|
||||
public function updateExistingPivot($id, array $attributes, $touch = true)
|
||||
{
|
||||
if (in_array($this->updatedAt(), $this->pivotColumns)) {
|
||||
$attributes = $this->addTimestampsToAttachment($attributes, true);
|
||||
}
|
||||
|
||||
$updated = $this->newPivotStatementForId($id)->update($attributes);
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a model to the parent.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $attributes
|
||||
* @param bool $touch
|
||||
* @return void
|
||||
*/
|
||||
public function attach($id, array $attributes = [], $touch = true)
|
||||
{
|
||||
// Here we will insert the attachment records into the pivot table. Once we have
|
||||
// inserted the records, we will touch the relationships if necessary and the
|
||||
// function will return. We can parse the IDs before inserting the records.
|
||||
$this->newPivotStatement()->insert($this->formatAttachRecords(
|
||||
(array) $this->parseIds($id), $attributes
|
||||
));
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of records to insert into the pivot table.
|
||||
*
|
||||
* @param array $ids
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function formatAttachRecords($ids, array $attributes)
|
||||
{
|
||||
$records = [];
|
||||
|
||||
$hasTimestamps = ($this->hasPivotColumn($this->createdAt()) ||
|
||||
$this->hasPivotColumn($this->updatedAt()));
|
||||
|
||||
// To create the attachment records, we will simply spin through the IDs given
|
||||
// and create a new record to insert for each ID. Each ID may actually be a
|
||||
// key in the array, with extra attributes to be placed in other columns.
|
||||
foreach ($ids as $key => $value) {
|
||||
$records[] = $this->formatAttachRecord(
|
||||
$key, $value, $attributes, $hasTimestamps
|
||||
);
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full attachment record payload.
|
||||
*
|
||||
* @param int $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @param bool $hasTimestamps
|
||||
* @return array
|
||||
*/
|
||||
protected function formatAttachRecord($key, $value, $attributes, $hasTimestamps)
|
||||
{
|
||||
list($id, $attributes) = $this->extractAttachIdAndAttributes($key, $value, $attributes);
|
||||
|
||||
return array_merge(
|
||||
$this->baseAttachRecord($id, $hasTimestamps), $attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attach record ID and extra attributes.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function extractAttachIdAndAttributes($key, $value, array $attributes)
|
||||
{
|
||||
return is_array($value)
|
||||
? [$key, array_merge($value, $attributes)]
|
||||
: [$value, $attributes];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot attachment record.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $timed
|
||||
* @return array
|
||||
*/
|
||||
protected function baseAttachRecord($id, $timed)
|
||||
{
|
||||
$record[$this->relatedKey] = $id;
|
||||
|
||||
$record[$this->foreignKey] = $this->parent->getKey();
|
||||
|
||||
// If the record needs to have creation and update timestamps, we will make
|
||||
// them by calling the parent model's "freshTimestamp" method which will
|
||||
// provide us with a fresh timestamp in this model's preferred format.
|
||||
if ($timed) {
|
||||
$record = $this->addTimestampsToAttachment($record);
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the creation and update timestamps on an attach record.
|
||||
*
|
||||
* @param array $record
|
||||
* @param bool $exists
|
||||
* @return array
|
||||
*/
|
||||
protected function addTimestampsToAttachment(array $record, $exists = false)
|
||||
{
|
||||
$fresh = $this->parent->freshTimestamp();
|
||||
|
||||
if (! $exists && $this->hasPivotColumn($this->createdAt())) {
|
||||
$record[$this->createdAt()] = $fresh;
|
||||
}
|
||||
|
||||
if ($this->hasPivotColumn($this->updatedAt())) {
|
||||
$record[$this->updatedAt()] = $fresh;
|
||||
}
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given column is defined as a pivot column.
|
||||
*
|
||||
* @param string $column
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasPivotColumn($column)
|
||||
{
|
||||
return in_array($column, $this->pivotColumns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach models from the relationship.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @param bool $touch
|
||||
* @return int
|
||||
*/
|
||||
public function detach($ids = null, $touch = true)
|
||||
{
|
||||
$query = $this->newPivotQuery();
|
||||
|
||||
// If associated IDs were passed to the method we will only delete those
|
||||
// associations, otherwise all of the association ties will be broken.
|
||||
// We'll return the numbers of affected rows when we do the deletes.
|
||||
if (! is_null($ids = $this->parseIds($ids))) {
|
||||
if (count($ids) === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$query->whereIn($this->relatedKey, (array) $ids);
|
||||
}
|
||||
|
||||
// Once we have all of the conditions set on the statement, we are ready
|
||||
// to run the delete on the pivot table. Then, if the touch parameter
|
||||
// is true, we will go ahead and touch all related models to sync.
|
||||
$results = $query->delete();
|
||||
|
||||
if ($touch) {
|
||||
$this->touchIfTouching();
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param bool $exists
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
public function newPivot(array $attributes = [], $exists = false)
|
||||
{
|
||||
$pivot = $this->related->newPivot(
|
||||
$this->parent, $attributes, $this->table, $exists, $this->using
|
||||
);
|
||||
|
||||
return $pivot->setPivotKeys($this->foreignKey, $this->relatedKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new existing pivot model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
public function newExistingPivot(array $attributes = [])
|
||||
{
|
||||
return $this->newPivot($attributes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new plain query builder for the pivot table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function newPivotStatement()
|
||||
{
|
||||
return $this->query->getQuery()->newQuery()->from($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new pivot statement for a given "other" ID.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function newPivotStatementForId($id)
|
||||
{
|
||||
return $this->newPivotQuery()->where($this->relatedKey, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query builder for the pivot table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
protected function newPivotQuery()
|
||||
{
|
||||
$query = $this->newPivotStatement();
|
||||
|
||||
foreach ($this->pivotWheres as $arguments) {
|
||||
call_user_func_array([$query, 'where'], $arguments);
|
||||
}
|
||||
|
||||
foreach ($this->pivotWhereIns as $arguments) {
|
||||
call_user_func_array([$query, 'whereIn'], $arguments);
|
||||
}
|
||||
|
||||
return $query->where($this->foreignKey, $this->parent->getKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the columns on the pivot table to retrieve.
|
||||
*
|
||||
* @param array|mixed $columns
|
||||
* @return $this
|
||||
*/
|
||||
public function withPivot($columns)
|
||||
{
|
||||
$this->pivotColumns = array_merge(
|
||||
$this->pivotColumns, is_array($columns) ? $columns : func_get_args()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the IDs from the given mixed value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
protected function parseIds($value)
|
||||
{
|
||||
if ($value instanceof Model) {
|
||||
return $value->getKey();
|
||||
}
|
||||
|
||||
if ($value instanceof Collection) {
|
||||
return $value->modelKeys();
|
||||
}
|
||||
|
||||
if ($value instanceof BaseCollection) {
|
||||
return $value->toArray();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given keys to integers if they are numeric and string otherwise.
|
||||
*
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
protected function castKeys(array $keys)
|
||||
{
|
||||
return (array) array_map(function ($v) {
|
||||
return $this->castKey($v);
|
||||
}, $keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given key to an integer if it is numeric.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @return mixed
|
||||
*/
|
||||
protected function castKey($key)
|
||||
{
|
||||
return is_numeric($key) ? (int) $key : (string) $key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
trait SupportsDefaultModels
|
||||
{
|
||||
/**
|
||||
* Indicates if a default model instance should be used.
|
||||
*
|
||||
* Alternatively, may be a Closure or array.
|
||||
*
|
||||
* @var \Closure|array|bool
|
||||
*/
|
||||
protected $withDefault;
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
abstract protected function newRelatedInstanceFor(Model $parent);
|
||||
|
||||
/**
|
||||
* Return a new model instance in case the relationship does not exist.
|
||||
*
|
||||
* @param \Closure|array|bool $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function withDefault($callback = true)
|
||||
{
|
||||
$this->withDefault = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default value for this relation.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model|null
|
||||
*/
|
||||
protected function getDefaultFor(Model $parent)
|
||||
{
|
||||
if (! $this->withDefault) {
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $this->newRelatedInstanceFor($parent);
|
||||
|
||||
if (is_callable($this->withDefault)) {
|
||||
return call_user_func($this->withDefault, $instance) ?: $instance;
|
||||
}
|
||||
|
||||
if (is_array($this->withDefault)) {
|
||||
$instance->forceFill($this->withDefault);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
||||
47
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasMany.php
vendored
Executable file
47
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasMany.php
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class HasMany extends HasOneOrMany
|
||||
{
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->query->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchMany($models, $results, $relation);
|
||||
}
|
||||
}
|
||||
455
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php
vendored
Normal file
455
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasManyThrough.php
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class HasManyThrough extends Relation
|
||||
{
|
||||
/**
|
||||
* The "through" parent model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $throughParent;
|
||||
|
||||
/**
|
||||
* The far parent model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $farParent;
|
||||
|
||||
/**
|
||||
* The near key on the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $firstKey;
|
||||
|
||||
/**
|
||||
* The far key on the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secondKey;
|
||||
|
||||
/**
|
||||
* The local key on the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $localKey;
|
||||
|
||||
/**
|
||||
* Create a new has many through relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $farParent
|
||||
* @param \Illuminate\Database\Eloquent\Model $throughParent
|
||||
* @param string $firstKey
|
||||
* @param string $secondKey
|
||||
* @param string $localKey
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $farParent, Model $throughParent, $firstKey, $secondKey, $localKey)
|
||||
{
|
||||
$this->localKey = $localKey;
|
||||
$this->firstKey = $firstKey;
|
||||
$this->secondKey = $secondKey;
|
||||
$this->farParent = $farParent;
|
||||
$this->throughParent = $throughParent;
|
||||
|
||||
parent::__construct($query, $throughParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
$localValue = $this->farParent[$this->localKey];
|
||||
|
||||
$this->performJoin();
|
||||
|
||||
if (static::$constraints) {
|
||||
$this->query->where($this->getQualifiedFirstKeyName(), '=', $localValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the join clause on the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder|null $query
|
||||
* @return void
|
||||
*/
|
||||
protected function performJoin(Builder $query = null)
|
||||
{
|
||||
$query = $query ?: $this->query;
|
||||
|
||||
$farKey = $this->getQualifiedFarKeyName();
|
||||
|
||||
$query->join($this->throughParent->getTable(), $this->getQualifiedParentKeyName(), '=', $farKey);
|
||||
|
||||
if ($this->throughParentSoftDeletes()) {
|
||||
$query->whereNull($this->throughParent->getQualifiedDeletedAtColumn());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether "through" parent of the relation uses Soft Deletes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function throughParentSoftDeletes()
|
||||
{
|
||||
return in_array(SoftDeletes::class, class_uses_recursive(
|
||||
get_class($this->throughParent)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$this->query->whereIn(
|
||||
$this->getQualifiedFirstKeyName(), $this->getKeys($models, $this->localKey)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
$dictionary = $this->buildDictionary($results);
|
||||
|
||||
// Once we have the dictionary we can simply spin through the parent models to
|
||||
// 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->getKey()])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->related->newCollection($dictionary[$key])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build model dictionary keyed by the relation's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return array
|
||||
*/
|
||||
protected function buildDictionary(Collection $results)
|
||||
{
|
||||
$dictionary = [];
|
||||
|
||||
// First we will create a dictionary of models keyed by the foreign key of the
|
||||
// relationship as this will allow us to quickly access all of the related
|
||||
// models without having to do nested looping which will be quite slow.
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->{$this->firstKey}][] = $result;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related model record matching the attributes or instantiate it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a related record matching the attributes, and fill it with values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function updateOrCreate(array $attributes, array $values = [])
|
||||
{
|
||||
$instance = $this->firstOrNew($attributes);
|
||||
|
||||
$instance->fill($values)->save();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first related model.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return mixed
|
||||
*/
|
||||
public function first($columns = ['*'])
|
||||
{
|
||||
$results = $this->take(1)->get($columns);
|
||||
|
||||
return count($results) > 0 ? $results->first() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query and get the first result or throw an exception.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|static
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function firstOrFail($columns = ['*'])
|
||||
{
|
||||
if (! is_null($model = $this->first($columns))) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|null
|
||||
*/
|
||||
public function find($id, $columns = ['*'])
|
||||
{
|
||||
if (is_array($id)) {
|
||||
return $this->findMany($id, $columns);
|
||||
}
|
||||
|
||||
return $this->where(
|
||||
$this->getRelated()->getQualifiedKeyName(), '=', $id
|
||||
)->first($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find multiple related models by their primary keys.
|
||||
*
|
||||
* @param mixed $ids
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function findMany($ids, $columns = ['*'])
|
||||
{
|
||||
if (empty($ids)) {
|
||||
return $this->getRelated()->newCollection();
|
||||
}
|
||||
|
||||
return $this->whereIn(
|
||||
$this->getRelated()->getQualifiedKeyName(), $ids
|
||||
)->get($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or throw an exception.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findOrFail($id, $columns = ['*'])
|
||||
{
|
||||
$result = $this->find($id, $columns);
|
||||
|
||||
if (is_array($id)) {
|
||||
if (count($result) == count(array_unique($id))) {
|
||||
return $result;
|
||||
}
|
||||
} elseif (! is_null($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel(get_class($this->related));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as a "select" statement.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
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
|
||||
// models with the result of those columns as a separate model relation.
|
||||
$columns = $this->query->getQuery()->columns ? [] : $columns;
|
||||
|
||||
$builder = $this->query->applyScopes();
|
||||
|
||||
$models = $builder->addSelect(
|
||||
$this->shouldSelect($columns)
|
||||
)->getModels();
|
||||
|
||||
// If we actually found models we will also eager load any relationships that
|
||||
// have been specified as needing to be eager loaded. This will solve the
|
||||
// n + 1 query problem for the developer and also increase performance.
|
||||
if (count($models) > 0) {
|
||||
$models = $builder->eagerLoadRelations($models);
|
||||
}
|
||||
|
||||
return $this->related->newCollection($models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginator for the "select" statement.
|
||||
*
|
||||
* @param int $perPage
|
||||
* @param array $columns
|
||||
* @param string $pageName
|
||||
* @param int $page
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return $this->query->paginate($perPage, $columns, $pageName, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the given query into a simple paginator.
|
||||
*
|
||||
* @param int $perPage
|
||||
* @param array $columns
|
||||
* @param string $pageName
|
||||
* @param int|null $page
|
||||
* @return \Illuminate\Contracts\Pagination\Paginator
|
||||
*/
|
||||
public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
|
||||
{
|
||||
$this->query->addSelect($this->shouldSelect($columns));
|
||||
|
||||
return $this->query->simplePaginate($perPage, $columns, $pageName, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the select clause for the relation query.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return array
|
||||
*/
|
||||
protected function shouldSelect(array $columns = ['*'])
|
||||
{
|
||||
if ($columns == ['*']) {
|
||||
$columns = [$this->related->getTable().'.*'];
|
||||
}
|
||||
|
||||
return array_merge($columns, [$this->getQualifiedFirstKeyName()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a 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 = ['*'])
|
||||
{
|
||||
$this->performJoin($query);
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getExistenceCompareKey(), '=', $this->getQualifiedFirstKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for comparing against the parent key in "has" query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExistenceCompareKey()
|
||||
{
|
||||
return $this->farParent->getQualifiedKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the related model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedFarKeyName()
|
||||
{
|
||||
return $this->getQualifiedForeignKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the related model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKeyName()
|
||||
{
|
||||
return $this->related->getTable().'.'.$this->secondKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the qualified foreign key on the "through" model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedFirstKeyName()
|
||||
{
|
||||
return $this->throughParent->getTable().'.'.$this->firstKey;
|
||||
}
|
||||
}
|
||||
64
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOne.php
vendored
Executable file
64
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOne.php
vendored
Executable file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class HasOne extends HasOneOrMany
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->query->first() ?: $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOne($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance()->setAttribute(
|
||||
$this->getForeignKeyName(), $parent->{$this->localKey}
|
||||
);
|
||||
}
|
||||
}
|
||||
417
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php
vendored
Executable file
417
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/HasOneOrMany.php
vendored
Executable file
@@ -0,0 +1,417 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
abstract class HasOneOrMany extends Relation
|
||||
{
|
||||
/**
|
||||
* The foreign key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The local key of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $localKey;
|
||||
|
||||
/**
|
||||
* The count of self joins.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $selfJoinCount = 0;
|
||||
|
||||
/**
|
||||
* Create a new has one or many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $localKey
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $foreignKey, $localKey)
|
||||
{
|
||||
$this->localKey = $localKey;
|
||||
$this->foreignKey = $foreignKey;
|
||||
|
||||
parent::__construct($query, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an un-saved instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function make(array $attributes = [])
|
||||
{
|
||||
return tap($this->related->newInstance($attributes), function ($instance) {
|
||||
$instance->setAttribute($this->getForeignKeyName(), $this->getParentKey());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
$this->query->where($this->foreignKey, '=', $this->getParentKey());
|
||||
|
||||
$this->query->whereNotNull($this->foreignKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$this->query->whereIn(
|
||||
$this->foreignKey, $this->getKeys($models, $this->localKey)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their single parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function matchOne(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOneOrMany($models, $results, $relation, 'one');
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their many parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function matchMany(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOneOrMany($models, $results, $relation, 'many');
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their many parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function matchOneOrMany(array $models, Collection $results, $relation, $type)
|
||||
{
|
||||
$dictionary = $this->buildDictionary($results);
|
||||
|
||||
// Once we have the dictionary we can simply spin through the parent models to
|
||||
// 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)])) {
|
||||
$model->setRelation(
|
||||
$relation, $this->getRelationValue($dictionary, $key, $type)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a relationship by one or many type.
|
||||
*
|
||||
* @param array $dictionary
|
||||
* @param string $key
|
||||
* @param string $type
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getRelationValue(array $dictionary, $key, $type)
|
||||
{
|
||||
$value = $dictionary[$key];
|
||||
|
||||
return $type == 'one' ? reset($value) : $this->related->newCollection($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build model dictionary keyed by the relation's foreign key.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return array
|
||||
*/
|
||||
protected function buildDictionary(Collection $results)
|
||||
{
|
||||
$dictionary = [];
|
||||
|
||||
$foreign = $this->getForeignKeyName();
|
||||
|
||||
// First we will create a dictionary of models keyed by the foreign key of the
|
||||
// relationship as this will allow us to quickly access all of the related
|
||||
// models without having to do nested looping which will be quite slow.
|
||||
foreach ($results as $result) {
|
||||
$dictionary[$result->{$foreign}][] = $result;
|
||||
}
|
||||
|
||||
return $dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a model by its primary key or return new instance of the related model.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function findOrNew($id, $columns = ['*'])
|
||||
{
|
||||
if (is_null($instance = $this->find($id, $columns))) {
|
||||
$instance = $this->related->newInstance();
|
||||
|
||||
$instance->setAttribute($this->getForeignKeyName(), $this->getParentKey());
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related model record matching the attributes or instantiate it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
|
||||
$instance->setAttribute($this->getForeignKeyName(), $this->getParentKey());
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related record matching the attributes or create it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrCreate(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->create($attributes);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a related record matching the attributes, and fill it with values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function updateOrCreate(array $attributes, array $values = [])
|
||||
{
|
||||
return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
|
||||
$instance->fill($values);
|
||||
|
||||
$instance->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a model instance to the parent model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Database\Eloquent\Model|false
|
||||
*/
|
||||
public function save(Model $model)
|
||||
{
|
||||
$model->setAttribute($this->getForeignKeyName(), $this->getParentKey());
|
||||
|
||||
return $model->save() ? $model : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a collection of models to the parent instance.
|
||||
*
|
||||
* @param \Traversable|array $models
|
||||
* @return \Traversable|array
|
||||
*/
|
||||
public function saveMany($models)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$this->save($model);
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function create(array $attributes)
|
||||
{
|
||||
return tap($this->related->newInstance($attributes), function ($instance) {
|
||||
$instance->setAttribute($this->getForeignKeyName(), $this->getParentKey());
|
||||
|
||||
$instance->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Collection of new instances of the related model.
|
||||
*
|
||||
* @param array $records
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function createMany(array $records)
|
||||
{
|
||||
$instances = $this->related->newCollection();
|
||||
|
||||
foreach ($records as $record) {
|
||||
$instances->push($this->create($record));
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an update on all the related models.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return int
|
||||
*/
|
||||
public function update(array $attributes)
|
||||
{
|
||||
if ($this->related->usesTimestamps()) {
|
||||
$attributes[$this->relatedUpdatedAt()] = $this->related->freshTimestampString();
|
||||
}
|
||||
|
||||
return $this->query->update($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a 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 ($query->getQuery()->from == $parentQuery->getQuery()->from) {
|
||||
return $this->getRelationExistenceQueryForSelfRelation($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship query on the same table.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @param array|mixed $columns
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceQueryForSelfRelation(Builder $query, Builder $parentQuery, $columns = ['*'])
|
||||
{
|
||||
$query->from($query->getModel()->getTable().' as '.$hash = $this->getRelationCountHash());
|
||||
|
||||
$query->getModel()->setTable($hash);
|
||||
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedParentKeyName(), '=', $hash.'.'.$this->getForeignKeyName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExistenceCompareKey()
|
||||
{
|
||||
return $this->getQualifiedForeignKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key value of the parent's local key.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParentKey()
|
||||
{
|
||||
return $this->parent->getAttribute($this->localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified parent key name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedParentKeyName()
|
||||
{
|
||||
return $this->parent->getTable().'.'.$this->localKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plain foreign key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKeyName()
|
||||
{
|
||||
$segments = explode('.', $this->getQualifiedForeignKeyName());
|
||||
|
||||
return $segments[count($segments) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key for the relationship.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedForeignKeyName()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
}
|
||||
47
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphMany.php
vendored
Executable file
47
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphMany.php
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class MorphMany extends MorphOneOrMany
|
||||
{
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->query->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->related->newCollection());
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchMany($models, $results, $relation);
|
||||
}
|
||||
}
|
||||
64
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOne.php
vendored
Executable file
64
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOne.php
vendored
Executable file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Relations\Concerns\SupportsDefaultModels;
|
||||
|
||||
class MorphOne extends MorphOneOrMany
|
||||
{
|
||||
use SupportsDefaultModels;
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->query->first() ?: $this->getDefaultFor($this->parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function initRelation(array $models, $relation)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
$model->setRelation($relation, $this->getDefaultFor($model));
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $this->matchOne($models, $results, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new related instance for the given model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function newRelatedInstanceFor(Model $parent)
|
||||
{
|
||||
return $this->related->newInstance()
|
||||
->setAttribute($this->getForeignKeyName(), $parent->{$this->localKey})
|
||||
->setAttribute($this->getMorphType(), $this->morphClass);
|
||||
}
|
||||
}
|
||||
248
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php
vendored
Executable file
248
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphOneOrMany.php
vendored
Executable file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
abstract class MorphOneOrMany extends HasOneOrMany
|
||||
{
|
||||
/**
|
||||
* The foreign key type for the relationship.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The class name of the parent model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphClass;
|
||||
|
||||
/**
|
||||
* Create a new morph one or many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $type
|
||||
* @param string $id
|
||||
* @param string $localKey
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $type, $id, $localKey)
|
||||
{
|
||||
$this->morphType = $type;
|
||||
|
||||
$this->morphClass = $parent->getMorphClass();
|
||||
|
||||
parent::__construct($query, $parent, $id, $localKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return an un-saved instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function make(array $attributes = [])
|
||||
{
|
||||
return tap($this->related->newInstance($attributes), function ($instance) {
|
||||
// When saving a polymorphic relationship, we need to set not only the foreign
|
||||
// key, but also the foreign key type, which is typically the class name of
|
||||
// the parent model. This makes the polymorphic item unique in the table.
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addConstraints()
|
||||
{
|
||||
if (static::$constraints) {
|
||||
parent::addConstraints();
|
||||
|
||||
$this->query->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
parent::addEagerConstraints($models);
|
||||
|
||||
$this->query->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a related model by its primary key or return new instance of the related model.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param array $columns
|
||||
* @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function findOrNew($id, $columns = ['*'])
|
||||
{
|
||||
if (is_null($instance = $this->find($id, $columns))) {
|
||||
$instance = $this->related->newInstance();
|
||||
|
||||
// When saving a polymorphic relationship, we need to set not only the foreign
|
||||
// key, but also the foreign key type, which is typically the class name of
|
||||
// the parent model. This makes the polymorphic item unique in the table.
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related model record matching the attributes or instantiate it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrNew(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
|
||||
// When saving a polymorphic relationship, we need to set not only the foreign
|
||||
// key, but also the foreign key type, which is typically the class name of
|
||||
// the parent model. This makes the polymorphic item unique in the table.
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the first related record matching the attributes or create it.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function firstOrCreate(array $attributes)
|
||||
{
|
||||
if (is_null($instance = $this->where($attributes)->first())) {
|
||||
$instance = $this->create($attributes);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update a related record matching the attributes, and fill it with values.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $values
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function updateOrCreate(array $attributes, array $values = [])
|
||||
{
|
||||
return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
|
||||
$instance->fill($values);
|
||||
|
||||
$instance->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a model instance to the parent model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function save(Model $model)
|
||||
{
|
||||
$model->setAttribute($this->getMorphType(), $this->morphClass);
|
||||
|
||||
return parent::save($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the related model.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function create(array $attributes)
|
||||
{
|
||||
$instance = $this->related->newInstance($attributes);
|
||||
|
||||
// When saving a polymorphic relationship, we need to set not only the foreign
|
||||
// key, but also the foreign key type, which is typically the class name of
|
||||
// the parent model. This makes the polymorphic item unique in the table.
|
||||
$this->setForeignAttributesForCreate($instance);
|
||||
|
||||
$instance->save();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the foreign ID and type for creating a related model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
protected function setForeignAttributesForCreate(Model $model)
|
||||
{
|
||||
$model->{$this->getForeignKeyName()} = $this->getParentKey();
|
||||
|
||||
$model->{$this->getMorphType()} = $this->morphClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = ['*'])
|
||||
{
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns)->where(
|
||||
$this->morphType, $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key "type" name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plain morph type name without the table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return last(explode('.', $this->morphType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the parent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphClass()
|
||||
{
|
||||
return $this->morphClass;
|
||||
}
|
||||
}
|
||||
79
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphPivot.php
vendored
Normal file
79
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphPivot.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class MorphPivot extends Pivot
|
||||
{
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
* Explicitly define this so it's not included in saved attributes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The value of the polymorphic relation.
|
||||
*
|
||||
* Explicitly define this so it's not included in saved attributes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphClass;
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
{
|
||||
$query->where($this->morphType, $this->morphClass);
|
||||
|
||||
return parent::setKeysForSaveQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot model record from the database.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$query = $this->getDeleteQuery();
|
||||
|
||||
$query->where($this->morphType, $this->morphClass);
|
||||
|
||||
return $query->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the morph type for the pivot.
|
||||
*
|
||||
* @param string $morphType
|
||||
* @return $this
|
||||
*/
|
||||
public function setMorphType($morphType)
|
||||
{
|
||||
$this->morphType = $morphType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the morph class for the pivot.
|
||||
*
|
||||
* @param string $morphClass
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphPivot
|
||||
*/
|
||||
public function setMorphClass($morphClass)
|
||||
{
|
||||
$this->morphClass = $morphClass;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
272
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphTo.php
vendored
Normal file
272
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphTo.php
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class MorphTo extends BelongsTo
|
||||
{
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The models whose relations are being eager loaded.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
protected $models;
|
||||
|
||||
/**
|
||||
* All of the models keyed by ID.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dictionary = [];
|
||||
|
||||
/**
|
||||
* A buffer of dynamic calls to query macros.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $macroBuffer = [];
|
||||
|
||||
/**
|
||||
* Create a new morph to relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $foreignKey
|
||||
* @param string $ownerKey
|
||||
* @param string $type
|
||||
* @param string $relation
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $foreignKey, $ownerKey, $type, $relation)
|
||||
{
|
||||
$this->morphType = $type;
|
||||
|
||||
parent::__construct($query, $parent, $foreignKey, $ownerKey, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
$this->buildDictionary($this->models = Collection::make($models));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a dictionary with the models.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Collection $models
|
||||
* @return void
|
||||
*/
|
||||
protected function buildDictionary(Collection $models)
|
||||
{
|
||||
foreach ($models as $model) {
|
||||
if ($model->{$this->morphType}) {
|
||||
$this->dictionary[$model->{$this->morphType}][$model->{$this->foreignKey}][] = $model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->ownerKey ? $this->query->first() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* Called via eager load method of Eloquent query builder.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEager()
|
||||
{
|
||||
foreach (array_keys($this->dictionary) as $type) {
|
||||
$this->matchToMorphParents($type, $this->getResultsByType($type));
|
||||
}
|
||||
|
||||
return $this->models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the relation results for a type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
protected function getResultsByType($type)
|
||||
{
|
||||
$instance = $this->createModelByType($type);
|
||||
|
||||
$query = $this->replayMacros($instance->newQuery())
|
||||
->mergeConstraintsFrom($this->getQuery())
|
||||
->with($this->getQuery()->getEagerLoads());
|
||||
|
||||
return $query->whereIn(
|
||||
$instance->getTable().'.'.$instance->getKeyName(), $this->gatherKeysByType($type)
|
||||
)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gather all of the foreign keys for a given type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function gatherKeysByType($type)
|
||||
{
|
||||
return collect($this->dictionary[$type])->map(function ($models) {
|
||||
return head($models)->{$this->foreignKey};
|
||||
})->values()->unique()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new model instance by type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function createModelByType($type)
|
||||
{
|
||||
$class = Model::getActualClassNameForMorph($type);
|
||||
|
||||
return new $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
public function match(array $models, Collection $results, $relation)
|
||||
{
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the results for a given type to their parents.
|
||||
*
|
||||
* @param string $type
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @return void
|
||||
*/
|
||||
protected function matchToMorphParents($type, Collection $results)
|
||||
{
|
||||
foreach ($results as $result) {
|
||||
if (isset($this->dictionary[$type][$result->getKey()])) {
|
||||
foreach ($this->dictionary[$type][$result->getKey()] as $model) {
|
||||
$model->setRelation($this->relation, $result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate the model instance to the given parent.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function associate($model)
|
||||
{
|
||||
$this->parent->setAttribute($this->foreignKey, $model->getKey());
|
||||
|
||||
$this->parent->setAttribute($this->morphType, $model->getMorphClass());
|
||||
|
||||
return $this->parent->setRelation($this->relation, $model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissociate previously associated model from the given parent.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function dissociate()
|
||||
{
|
||||
$this->parent->setAttribute($this->foreignKey, null);
|
||||
|
||||
$this->parent->setAttribute($this->morphType, null);
|
||||
|
||||
return $this->parent->setRelation($this->relation, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key "type" name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dictionary used by the relationship.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDictionary()
|
||||
{
|
||||
return $this->dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replay stored macro calls on the actual related instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function replayMacros(Builder $query)
|
||||
{
|
||||
foreach ($this->macroBuffer as $macro) {
|
||||
$query->{$macro['method']}(...$macro['parameters']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic method calls to the relationship.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
try {
|
||||
return parent::__call($method, $parameters);
|
||||
}
|
||||
|
||||
// If we tried to call a method that does not exist on the parent Builder instance,
|
||||
// we'll assume that we want to call a query macro (e.g. withTrashed) that only
|
||||
// exists on related models. We will just store the call and replay it later.
|
||||
catch (BadMethodCallException $e) {
|
||||
$this->macroBuffer[] = compact('method', 'parameters');
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
}
|
||||
162
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphToMany.php
vendored
Normal file
162
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/MorphToMany.php
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class MorphToMany extends BelongsToMany
|
||||
{
|
||||
/**
|
||||
* The type of the polymorphic relation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphType;
|
||||
|
||||
/**
|
||||
* The class name of the morph type constraint.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $morphClass;
|
||||
|
||||
/**
|
||||
* Indicates if we are connecting the inverse of the relation.
|
||||
*
|
||||
* This primarily affects the morphClass constraint.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $inverse;
|
||||
|
||||
/**
|
||||
* Create a new morph to many relationship instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param string $name
|
||||
* @param string $table
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @param string $relationName
|
||||
* @param bool $inverse
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent, $name, $table, $foreignKey, $relatedKey, $relationName = null, $inverse = false)
|
||||
{
|
||||
$this->inverse = $inverse;
|
||||
$this->morphType = $name.'_type';
|
||||
$this->morphClass = $inverse ? $query->getModel()->getMorphClass() : $parent->getMorphClass();
|
||||
|
||||
parent::__construct($query, $parent, $table, $foreignKey, $relatedKey, $relationName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the where clause for the relation query.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function addWhereConstraints()
|
||||
{
|
||||
parent::addWhereConstraints();
|
||||
|
||||
$this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
public function addEagerConstraints(array $models)
|
||||
{
|
||||
parent::addEagerConstraints($models);
|
||||
|
||||
$this->query->where($this->table.'.'.$this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot attachment record.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $timed
|
||||
* @return array
|
||||
*/
|
||||
protected function baseAttachRecord($id, $timed)
|
||||
{
|
||||
return Arr::add(
|
||||
parent::baseAttachRecord($id, $timed), $this->morphType, $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship count 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 = ['*'])
|
||||
{
|
||||
return parent::getRelationExistenceQuery($query, $parentQuery, $columns)->where(
|
||||
$this->table.'.'.$this->morphType, $this->morphClass
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query builder for the pivot table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
protected function newPivotQuery()
|
||||
{
|
||||
return parent::newPivotQuery()->where($this->morphType, $this->morphClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param bool $exists
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Pivot
|
||||
*/
|
||||
public function newPivot(array $attributes = [], $exists = false)
|
||||
{
|
||||
$using = $this->using;
|
||||
|
||||
$pivot = $using ? $using::fromRawAttributes($this->parent, $attributes, $this->table, $exists)
|
||||
: new MorphPivot($this->parent, $attributes, $this->table, $exists);
|
||||
|
||||
$pivot->setPivotKeys($this->foreignKey, $this->relatedKey)
|
||||
->setMorphType($this->morphType)
|
||||
->setMorphClass($this->morphClass);
|
||||
|
||||
return $pivot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key "type" name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphType()
|
||||
{
|
||||
return $this->morphType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the parent model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMorphClass()
|
||||
{
|
||||
return $this->morphClass;
|
||||
}
|
||||
}
|
||||
198
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Pivot.php
vendored
Executable file
198
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Pivot.php
vendored
Executable file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class Pivot extends Model
|
||||
{
|
||||
/**
|
||||
* The parent model of the relationship.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public $parent;
|
||||
|
||||
/**
|
||||
* The name of the foreign key column.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $foreignKey;
|
||||
|
||||
/**
|
||||
* The name of the "other key" column.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $relatedKey;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* Create a new pivot model instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param array $attributes
|
||||
* @param string $table
|
||||
* @param bool $exists
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Model $parent, $attributes, $table, $exists = false)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// The pivot model is a "dynamic" model since we will set the tables dynamically
|
||||
// for the instance. This allows it work for any intermediate tables for the
|
||||
// many to many relationship that are defined by this developer's classes.
|
||||
$this->setConnection($parent->getConnectionName())
|
||||
->setTable($table)
|
||||
->forceFill($attributes)
|
||||
->syncOriginal();
|
||||
|
||||
// We store off the parent instance so we will access the timestamp column names
|
||||
// for the model, since the pivot model timestamps aren't easily configurable
|
||||
// from the developer's point of view. We can use the parents to get these.
|
||||
$this->parent = $parent;
|
||||
|
||||
$this->exists = $exists;
|
||||
|
||||
$this->timestamps = $this->hasTimestampAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new pivot model from raw values returned from a query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @param array $attributes
|
||||
* @param string $table
|
||||
* @param bool $exists
|
||||
* @return static
|
||||
*/
|
||||
public static function fromRawAttributes(Model $parent, $attributes, $table, $exists = false)
|
||||
{
|
||||
$instance = new static($parent, $attributes, $table, $exists);
|
||||
|
||||
$instance->setRawAttributes($attributes, true);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the keys for a save update query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function setKeysForSaveQuery(Builder $query)
|
||||
{
|
||||
$query->where($this->foreignKey, $this->getAttribute($this->foreignKey));
|
||||
|
||||
return $query->where($this->relatedKey, $this->getAttribute($this->relatedKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the pivot model record from the database.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
return $this->getDeleteQuery()->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query builder for a delete operation on the pivot.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected function getDeleteQuery()
|
||||
{
|
||||
return $this->newQuery()->where([
|
||||
$this->foreignKey => $this->getAttribute($this->foreignKey),
|
||||
$this->relatedKey => $this->getAttribute($this->relatedKey),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foreign key column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getForeignKey()
|
||||
{
|
||||
return $this->foreignKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "related key" column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRelatedKey()
|
||||
{
|
||||
return $this->relatedKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "related key" column name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOtherKey()
|
||||
{
|
||||
return $this->getRelatedKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the key names for the pivot model instance.
|
||||
*
|
||||
* @param string $foreignKey
|
||||
* @param string $relatedKey
|
||||
* @return $this
|
||||
*/
|
||||
public function setPivotKeys($foreignKey, $relatedKey)
|
||||
{
|
||||
$this->foreignKey = $foreignKey;
|
||||
|
||||
$this->relatedKey = $relatedKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the pivot model has timestamp attributes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTimestampAttributes()
|
||||
{
|
||||
return array_key_exists($this->getCreatedAtColumn(), $this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtColumn()
|
||||
{
|
||||
return $this->parent->getCreatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdatedAtColumn()
|
||||
{
|
||||
return $this->parent->getUpdatedAtColumn();
|
||||
}
|
||||
}
|
||||
361
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php
vendored
Executable file
361
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php
vendored
Executable file
@@ -0,0 +1,361 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent\Relations;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
/**
|
||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
abstract class Relation
|
||||
{
|
||||
use Macroable {
|
||||
__call as macroCall;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Eloquent query builder instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* The parent model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $parent;
|
||||
|
||||
/**
|
||||
* The related model instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
protected $related;
|
||||
|
||||
/**
|
||||
* Indicates if the relation is adding constraints.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $constraints = true;
|
||||
|
||||
/**
|
||||
* An array to map class names to their morph names in database.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $morphMap = [];
|
||||
|
||||
/**
|
||||
* Create a new relation instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Model $parent
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $query, Model $parent)
|
||||
{
|
||||
$this->query = $query;
|
||||
$this->parent = $parent;
|
||||
$this->related = $query->getModel();
|
||||
|
||||
$this->addConstraints();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a callback with constraints disabled on the relation.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
public static function noConstraints(Closure $callback)
|
||||
{
|
||||
$previous = static::$constraints;
|
||||
|
||||
static::$constraints = false;
|
||||
|
||||
// When resetting the relation where clause, we want to shift the first element
|
||||
// off of the bindings, leaving only the constraints that the developers put
|
||||
// as "extra" on the relationships, and not original relation constraints.
|
||||
try {
|
||||
return call_user_func($callback);
|
||||
} finally {
|
||||
static::$constraints = $previous;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base constraints on the relation query.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function addConstraints();
|
||||
|
||||
/**
|
||||
* Set the constraints for an eager load of the relation.
|
||||
*
|
||||
* @param array $models
|
||||
* @return void
|
||||
*/
|
||||
abstract public function addEagerConstraints(array $models);
|
||||
|
||||
/**
|
||||
* Initialize the relation on a set of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
abstract public function initRelation(array $models, $relation);
|
||||
|
||||
/**
|
||||
* Match the eagerly loaded results to their parents.
|
||||
*
|
||||
* @param array $models
|
||||
* @param \Illuminate\Database\Eloquent\Collection $results
|
||||
* @param string $relation
|
||||
* @return array
|
||||
*/
|
||||
abstract public function match(array $models, Collection $results, $relation);
|
||||
|
||||
/**
|
||||
* Get the results of the relationship.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function getResults();
|
||||
|
||||
/**
|
||||
* Get the relationship for eager loading.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function getEager()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch all of the related models for the relationship.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function touch()
|
||||
{
|
||||
$column = $this->getRelated()->getUpdatedAtColumn();
|
||||
|
||||
$this->rawUpdate([$column => $this->getRelated()->freshTimestampString()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a raw update against the base query.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return int
|
||||
*/
|
||||
public function rawUpdate(array $attributes = [])
|
||||
{
|
||||
return $this->query->update($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the constraints for a relationship count query.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \Illuminate\Database\Eloquent\Builder $parentQuery
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getRelationExistenceCountQuery(Builder $query, Builder $parentQuery)
|
||||
{
|
||||
return $this->getRelationExistenceQuery(
|
||||
$query, $parentQuery, new Expression('count(*)')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = ['*'])
|
||||
{
|
||||
return $query->select($columns)->whereColumn(
|
||||
$this->getQualifiedParentKeyName(), '=', $this->getExistenceCompareKey()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the primary keys for an array of models.
|
||||
*
|
||||
* @param array $models
|
||||
* @param string $key
|
||||
* @return array
|
||||
*/
|
||||
protected function getKeys(array $models, $key = null)
|
||||
{
|
||||
return collect($models)->map(function ($value) use ($key) {
|
||||
return $key ? $value->getAttribute($key) : $value->getKey();
|
||||
})->values()->unique()->sort()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying query for the relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base query builder driving the Eloquent builder.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function getBaseQuery()
|
||||
{
|
||||
return $this->query->getQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent model of the relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified parent key name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedParentKeyName()
|
||||
{
|
||||
return $this->parent->getQualifiedKeyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the related model of the relation.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Model
|
||||
*/
|
||||
public function getRelated()
|
||||
{
|
||||
return $this->related;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "created at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createdAt()
|
||||
{
|
||||
return $this->parent->getCreatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function updatedAt()
|
||||
{
|
||||
return $this->parent->getUpdatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the related model's "updated at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function relatedUpdatedAt()
|
||||
{
|
||||
return $this->related->getUpdatedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or get the morph map for polymorphic relations.
|
||||
*
|
||||
* @param array|null $map
|
||||
* @param bool $merge
|
||||
* @return array
|
||||
*/
|
||||
public static function morphMap(array $map = null, $merge = true)
|
||||
{
|
||||
$map = static::buildMorphMapFromModels($map);
|
||||
|
||||
if (is_array($map)) {
|
||||
static::$morphMap = $merge && static::$morphMap
|
||||
? array_merge(static::$morphMap, $map) : $map;
|
||||
}
|
||||
|
||||
return static::$morphMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a table-keyed array from model class names.
|
||||
*
|
||||
* @param string[]|null $models
|
||||
* @return array|null
|
||||
*/
|
||||
protected static function buildMorphMapFromModels(array $models = null)
|
||||
{
|
||||
if (is_null($models) || Arr::isAssoc($models)) {
|
||||
return $models;
|
||||
}
|
||||
|
||||
return array_combine(array_map(function ($model) {
|
||||
return (new $model)->getTable();
|
||||
}, $models), $models);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dynamic method calls to the relationship.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (static::hasMacro($method)) {
|
||||
return $this->macroCall($method, $parameters);
|
||||
}
|
||||
|
||||
$result = call_user_func_array([$this->query, $method], $parameters);
|
||||
|
||||
if ($result === $this->query) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a clone of the underlying query builder when cloning.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->query = clone $this->query;
|
||||
}
|
||||
}
|
||||
15
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Scope.php
vendored
Normal file
15
vendor/laravel/framework/src/Illuminate/Database/Eloquent/Scope.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
interface Scope
|
||||
{
|
||||
/**
|
||||
* Apply the scope to a given Eloquent query builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $builder, Model $model);
|
||||
}
|
||||
167
vendor/laravel/framework/src/Illuminate/Database/Eloquent/SoftDeletes.php
vendored
Normal file
167
vendor/laravel/framework/src/Illuminate/Database/Eloquent/SoftDeletes.php
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
trait SoftDeletes
|
||||
{
|
||||
/**
|
||||
* Indicates if the model is currently force deleting.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $forceDeleting = false;
|
||||
|
||||
/**
|
||||
* Boot the soft deleting trait for a model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function bootSoftDeletes()
|
||||
{
|
||||
static::addGlobalScope(new SoftDeletingScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a hard delete on a soft deleted model.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function forceDelete()
|
||||
{
|
||||
$this->forceDeleting = true;
|
||||
|
||||
$deleted = $this->delete();
|
||||
|
||||
$this->forceDeleting = false;
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual delete query on this model instance.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function performDeleteOnModel()
|
||||
{
|
||||
if ($this->forceDeleting) {
|
||||
return $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey())->forceDelete();
|
||||
}
|
||||
|
||||
return $this->runSoftDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual delete query on this model instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function runSoftDelete()
|
||||
{
|
||||
$query = $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey());
|
||||
|
||||
$time = $this->freshTimestamp();
|
||||
|
||||
$columns = [$this->getDeletedAtColumn() => $this->fromDateTime($time)];
|
||||
|
||||
$this->{$this->getDeletedAtColumn()} = $time;
|
||||
|
||||
if ($this->timestamps) {
|
||||
$this->{$this->getUpdatedAtColumn()} = $time;
|
||||
|
||||
$columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
|
||||
}
|
||||
|
||||
$query->update($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted model instance.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function restore()
|
||||
{
|
||||
// If the restoring event does not return false, we will proceed with this
|
||||
// restore operation. Otherwise, we bail out so the developer will stop
|
||||
// the restore totally. We will clear the deleted timestamp and save.
|
||||
if ($this->fireModelEvent('restoring') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->{$this->getDeletedAtColumn()} = null;
|
||||
|
||||
// Once we have saved the model, we will fire the "restored" event so this
|
||||
// developer will do anything they need to after a restore operation is
|
||||
// totally finished. Then we will return the result of the save call.
|
||||
$this->exists = true;
|
||||
|
||||
$result = $this->save();
|
||||
|
||||
$this->fireModelEvent('restored', false);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model instance has been soft-deleted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function trashed()
|
||||
{
|
||||
return ! is_null($this->{$this->getDeletedAtColumn()});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a restoring model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function restoring($callback)
|
||||
{
|
||||
static::registerModelEvent('restoring', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a restored model event with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
*/
|
||||
public static function restored($callback)
|
||||
{
|
||||
static::registerModelEvent('restored', $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the model is currently force deleting.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isForceDeleting()
|
||||
{
|
||||
return $this->forceDeleting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the "deleted at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDeletedAtColumn()
|
||||
{
|
||||
return defined('static::DELETED_AT') ? static::DELETED_AT : 'deleted_at';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fully qualified "deleted at" column.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getQualifiedDeletedAtColumn()
|
||||
{
|
||||
return $this->getTable().'.'.$this->getDeletedAtColumn();
|
||||
}
|
||||
}
|
||||
127
vendor/laravel/framework/src/Illuminate/Database/Eloquent/SoftDeletingScope.php
vendored
Normal file
127
vendor/laravel/framework/src/Illuminate/Database/Eloquent/SoftDeletingScope.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Eloquent;
|
||||
|
||||
class SoftDeletingScope implements Scope
|
||||
{
|
||||
/**
|
||||
* All of the extensions to be added to the builder.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = ['Restore', 'WithTrashed', 'WithoutTrashed', 'OnlyTrashed'];
|
||||
|
||||
/**
|
||||
* Apply the scope to a given Eloquent query builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @param \Illuminate\Database\Eloquent\Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $builder, Model $model)
|
||||
{
|
||||
$builder->whereNull($model->getQualifiedDeletedAtColumn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the query builder with the needed functions.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
public function extend(Builder $builder)
|
||||
{
|
||||
foreach ($this->extensions as $extension) {
|
||||
$this->{"add{$extension}"}($builder);
|
||||
}
|
||||
|
||||
$builder->onDelete(function (Builder $builder) {
|
||||
$column = $this->getDeletedAtColumn($builder);
|
||||
|
||||
return $builder->update([
|
||||
$column => $builder->getModel()->freshTimestampString(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "deleted at" column for the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return string
|
||||
*/
|
||||
protected function getDeletedAtColumn(Builder $builder)
|
||||
{
|
||||
if (count($builder->getQuery()->joins) > 0) {
|
||||
return $builder->getModel()->getQualifiedDeletedAtColumn();
|
||||
}
|
||||
|
||||
return $builder->getModel()->getDeletedAtColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the restore extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addRestore(Builder $builder)
|
||||
{
|
||||
$builder->macro('restore', function (Builder $builder) {
|
||||
$builder->withTrashed();
|
||||
|
||||
return $builder->update([$builder->getModel()->getDeletedAtColumn() => null]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the with-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addWithTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('withTrashed', function (Builder $builder) {
|
||||
return $builder->withoutGlobalScope($this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the without-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addWithoutTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('withoutTrashed', function (Builder $builder) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
$builder->withoutGlobalScope($this)->whereNull(
|
||||
$model->getQualifiedDeletedAtColumn()
|
||||
);
|
||||
|
||||
return $builder;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the only-trashed extension to the builder.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||
* @return void
|
||||
*/
|
||||
protected function addOnlyTrashed(Builder $builder)
|
||||
{
|
||||
$builder->macro('onlyTrashed', function (Builder $builder) {
|
||||
$model = $builder->getModel();
|
||||
|
||||
$builder->withoutGlobalScope($this)->whereNotNull(
|
||||
$model->getQualifiedDeletedAtColumn()
|
||||
);
|
||||
|
||||
return $builder;
|
||||
});
|
||||
}
|
||||
}
|
||||
32
vendor/laravel/framework/src/Illuminate/Database/Events/ConnectionEvent.php
vendored
Normal file
32
vendor/laravel/framework/src/Illuminate/Database/Events/ConnectionEvent.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
abstract class ConnectionEvent
|
||||
{
|
||||
/**
|
||||
* The name of the connection.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $connectionName;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->connectionName = $connection->getName();
|
||||
}
|
||||
}
|
||||
58
vendor/laravel/framework/src/Illuminate/Database/Events/QueryExecuted.php
vendored
Normal file
58
vendor/laravel/framework/src/Illuminate/Database/Events/QueryExecuted.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class QueryExecuted
|
||||
{
|
||||
/**
|
||||
* The SQL query that was executed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $sql;
|
||||
|
||||
/**
|
||||
* The array of query bindings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $bindings;
|
||||
|
||||
/**
|
||||
* The number of milliseconds it took to execute the query.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
public $time;
|
||||
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* The database connection name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $connectionName;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $bindings
|
||||
* @param float $time
|
||||
* @param
|
||||
*/
|
||||
public function __construct($sql, $bindings, $time, $connection)
|
||||
{
|
||||
$this->sql = $sql;
|
||||
$this->time = $time;
|
||||
$this->bindings = $bindings;
|
||||
$this->connection = $connection;
|
||||
$this->connectionName = $connection->getName();
|
||||
}
|
||||
}
|
||||
33
vendor/laravel/framework/src/Illuminate/Database/Events/StatementPrepared.php
vendored
Normal file
33
vendor/laravel/framework/src/Illuminate/Database/Events/StatementPrepared.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class StatementPrepared
|
||||
{
|
||||
/**
|
||||
* The database connection instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Connection
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* The PDO statement.
|
||||
*
|
||||
* @var \PDOStatement
|
||||
*/
|
||||
public $statement;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @param \PDOStatement $statement
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($connection, $statement)
|
||||
{
|
||||
$this->statement = $statement;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
}
|
||||
8
vendor/laravel/framework/src/Illuminate/Database/Events/TransactionBeginning.php
vendored
Normal file
8
vendor/laravel/framework/src/Illuminate/Database/Events/TransactionBeginning.php
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class TransactionBeginning extends ConnectionEvent
|
||||
{
|
||||
//
|
||||
}
|
||||
8
vendor/laravel/framework/src/Illuminate/Database/Events/TransactionCommitted.php
vendored
Normal file
8
vendor/laravel/framework/src/Illuminate/Database/Events/TransactionCommitted.php
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class TransactionCommitted extends ConnectionEvent
|
||||
{
|
||||
//
|
||||
}
|
||||
8
vendor/laravel/framework/src/Illuminate/Database/Events/TransactionRolledBack.php
vendored
Normal file
8
vendor/laravel/framework/src/Illuminate/Database/Events/TransactionRolledBack.php
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Events;
|
||||
|
||||
class TransactionRolledBack extends ConnectionEvent
|
||||
{
|
||||
//
|
||||
}
|
||||
205
vendor/laravel/framework/src/Illuminate/Database/Grammar.php
vendored
Executable file
205
vendor/laravel/framework/src/Illuminate/Database/Grammar.php
vendored
Executable file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Database\Query\Expression;
|
||||
|
||||
abstract class Grammar
|
||||
{
|
||||
/**
|
||||
* The grammar table prefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tablePrefix = '';
|
||||
|
||||
/**
|
||||
* Wrap an array of values.
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function wrapArray(array $values)
|
||||
{
|
||||
return array_map([$this, 'wrap'], $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a table in keyword identifiers.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression|string $table
|
||||
* @return string
|
||||
*/
|
||||
public function wrapTable($table)
|
||||
{
|
||||
if (! $this->isExpression($table)) {
|
||||
return $this->wrap($this->tablePrefix.$table, true);
|
||||
}
|
||||
|
||||
return $this->getValue($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value in keyword identifiers.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression|string $value
|
||||
* @param bool $prefixAlias
|
||||
* @return string
|
||||
*/
|
||||
public function wrap($value, $prefixAlias = false)
|
||||
{
|
||||
if ($this->isExpression($value)) {
|
||||
return $this->getValue($value);
|
||||
}
|
||||
|
||||
// If the value being wrapped has a column alias we will need to separate out
|
||||
// the pieces so we can wrap each of the segments of the expression on it
|
||||
// own, and then joins them both back together with the "as" connector.
|
||||
if (strpos(strtolower($value), ' as ') !== false) {
|
||||
return $this->wrapAliasedValue($value, $prefixAlias);
|
||||
}
|
||||
|
||||
return $this->wrapSegments(explode('.', $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a value that has an alias.
|
||||
*
|
||||
* @param string $value
|
||||
* @param bool $prefixAlias
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapAliasedValue($value, $prefixAlias = false)
|
||||
{
|
||||
$segments = preg_split('/\s+as\s+/i', $value);
|
||||
|
||||
// If we are wrapping a table we need to prefix the alias with the table prefix
|
||||
// as well in order to generate proper syntax. If this is a column of course
|
||||
// no prefix is necessary. The condition will be true when from wrapTable.
|
||||
if ($prefixAlias) {
|
||||
$segments[1] = $this->tablePrefix.$segments[1];
|
||||
}
|
||||
|
||||
return $this->wrap(
|
||||
$segments[0]).' as '.$this->wrapValue($segments[1]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given value segments.
|
||||
*
|
||||
* @param array $segments
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapSegments($segments)
|
||||
{
|
||||
return collect($segments)->map(function ($segment, $key) use ($segments) {
|
||||
return $key == 0 && count($segments) > 1
|
||||
? $this->wrapTable($segment)
|
||||
: $this->wrapValue($segment);
|
||||
})->implode('.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a single string in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapValue($value)
|
||||
{
|
||||
if ($value !== '*') {
|
||||
return '"'.str_replace('"', '""', $value).'"';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of column names into a delimited string.
|
||||
*
|
||||
* @param array $columns
|
||||
* @return string
|
||||
*/
|
||||
public function columnize(array $columns)
|
||||
{
|
||||
return implode(', ', array_map([$this, 'wrap'], $columns));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create query parameter place-holders for an array.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function parameterize(array $values)
|
||||
{
|
||||
return implode(', ', array_map([$this, 'parameter'], $values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate query parameter place-holder for a value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
public function parameter($value)
|
||||
{
|
||||
return $this->isExpression($value) ? $this->getValue($value) : '?';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given value is a raw expression.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function isExpression($value)
|
||||
{
|
||||
return $value instanceof Expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a raw expression.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression $expression
|
||||
* @return string
|
||||
*/
|
||||
public function getValue($expression)
|
||||
{
|
||||
return $expression->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format for database stored dates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat()
|
||||
{
|
||||
return 'Y-m-d H:i:s';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grammar's table prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTablePrefix()
|
||||
{
|
||||
return $this->tablePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the grammar's table prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return $this
|
||||
*/
|
||||
public function setTablePrefix($prefix)
|
||||
{
|
||||
$this->tablePrefix = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
87
vendor/laravel/framework/src/Illuminate/Database/MigrationServiceProvider.php
vendored
Executable file
87
vendor/laravel/framework/src/Illuminate/Database/MigrationServiceProvider.php
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Database\Migrations\Migrator;
|
||||
use Illuminate\Database\Migrations\MigrationCreator;
|
||||
use Illuminate\Database\Migrations\DatabaseMigrationRepository;
|
||||
|
||||
class MigrationServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = true;
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registerRepository();
|
||||
|
||||
$this->registerMigrator();
|
||||
|
||||
$this->registerCreator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the migration repository service.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerRepository()
|
||||
{
|
||||
$this->app->singleton('migration.repository', function ($app) {
|
||||
$table = $app['config']['database.migrations'];
|
||||
|
||||
return new DatabaseMigrationRepository($app['db'], $table);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the migrator service.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerMigrator()
|
||||
{
|
||||
// The migrator is responsible for actually running and rollback the migration
|
||||
// files in the application. We'll pass in our database connection resolver
|
||||
// so the migrator can resolve any of these connections when it needs to.
|
||||
$this->app->singleton('migrator', function ($app) {
|
||||
$repository = $app['migration.repository'];
|
||||
|
||||
return new Migrator($repository, $app['db'], $app['files']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the migration creator.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerCreator()
|
||||
{
|
||||
$this->app->singleton('migration.creator', function ($app) {
|
||||
return new MigrationCreator($app['files']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [
|
||||
'migrator', 'migration.repository', 'migration.creator',
|
||||
];
|
||||
}
|
||||
}
|
||||
197
vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php
vendored
Executable file
197
vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php
vendored
Executable file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
|
||||
class DatabaseMigrationRepository implements MigrationRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* The database connection resolver instance.
|
||||
*
|
||||
* @var \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* The name of the migration table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table;
|
||||
|
||||
/**
|
||||
* The name of the database connection to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Create a new database migration repository instance.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Resolver $resolver, $table)
|
||||
{
|
||||
$this->table = $table;
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ran migrations.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRan()
|
||||
{
|
||||
return $this->table()
|
||||
->orderBy('batch', 'asc')
|
||||
->orderBy('migration', 'asc')
|
||||
->pluck('migration')->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of migrations.
|
||||
*
|
||||
* @param int $steps
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrations($steps)
|
||||
{
|
||||
$query = $this->table()->where('batch', '>=', '1');
|
||||
|
||||
return $query->orderBy('migration', 'desc')->take($steps)->get()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last migration batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLast()
|
||||
{
|
||||
$query = $this->table()->where('batch', $this->getLastBatchNumber());
|
||||
|
||||
return $query->orderBy('migration', 'desc')->get()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log that a migration was run.
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $batch
|
||||
* @return void
|
||||
*/
|
||||
public function log($file, $batch)
|
||||
{
|
||||
$record = ['migration' => $file, 'batch' => $batch];
|
||||
|
||||
$this->table()->insert($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a migration from the log.
|
||||
*
|
||||
* @param object $migration
|
||||
* @return void
|
||||
*/
|
||||
public function delete($migration)
|
||||
{
|
||||
$this->table()->where('migration', $migration->migration)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next migration batch number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNextBatchNumber()
|
||||
{
|
||||
return $this->getLastBatchNumber() + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last migration batch number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastBatchNumber()
|
||||
{
|
||||
return $this->table()->max('batch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createRepository()
|
||||
{
|
||||
$schema = $this->getConnection()->getSchemaBuilder();
|
||||
|
||||
$schema->create($this->table, function ($table) {
|
||||
// The migrations table is responsible for keeping track of which of the
|
||||
// migrations have actually run for the application. We'll create the
|
||||
// table to hold the migration file's path as well as the batch ID.
|
||||
$table->increments('id');
|
||||
$table->string('migration');
|
||||
$table->integer('batch');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the migration repository exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function repositoryExists()
|
||||
{
|
||||
$schema = $this->getConnection()->getSchemaBuilder();
|
||||
|
||||
return $schema->hasTable($this->table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a query builder for the migration table.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
protected function table()
|
||||
{
|
||||
return $this->getConnection()->table($this->table)->useWritePdo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the connection resolver instance.
|
||||
*
|
||||
* @return \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
public function getConnectionResolver()
|
||||
{
|
||||
return $this->resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the database connection instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->resolver->connection($this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the information source to gather data.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setSource($name)
|
||||
{
|
||||
$this->connection = $name;
|
||||
}
|
||||
}
|
||||
23
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migration.php
vendored
Executable file
23
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migration.php
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
abstract class Migration
|
||||
{
|
||||
/**
|
||||
* The name of the database connection to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* Get the migration connection name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
}
|
||||
204
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationCreator.php
vendored
Executable file
204
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationCreator.php
vendored
Executable file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class MigrationCreator
|
||||
{
|
||||
/**
|
||||
* The filesystem instance.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* The registered post create hooks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $postCreate = [];
|
||||
|
||||
/**
|
||||
* Create a new migration creator instance.
|
||||
*
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Filesystem $files)
|
||||
{
|
||||
$this->files = $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new migration at the given path.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string $table
|
||||
* @param bool $create
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create($name, $path, $table = null, $create = false)
|
||||
{
|
||||
$this->ensureMigrationDoesntAlreadyExist($name);
|
||||
|
||||
// First we will get the stub file for the migration, which serves as a type
|
||||
// of template for the migration. Once we have those we will populate the
|
||||
// various place-holders, save the file, and run the post create event.
|
||||
$stub = $this->getStub($table, $create);
|
||||
|
||||
$this->files->put(
|
||||
$path = $this->getPath($name, $path),
|
||||
$this->populateStub($name, $stub, $table)
|
||||
);
|
||||
|
||||
// Next, we will fire any hooks that are supposed to fire after a migration is
|
||||
// created. Once that is done we'll be ready to return the full path to the
|
||||
// migration file so it can be used however it's needed by the developer.
|
||||
$this->firePostCreateHooks();
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a migration with the given name doesn't already exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function ensureMigrationDoesntAlreadyExist($name)
|
||||
{
|
||||
if (class_exists($className = $this->getClassName($name))) {
|
||||
throw new InvalidArgumentException("A {$className} migration already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migration stub file.
|
||||
*
|
||||
* @param string $table
|
||||
* @param bool $create
|
||||
* @return string
|
||||
*/
|
||||
protected function getStub($table, $create)
|
||||
{
|
||||
if (is_null($table)) {
|
||||
return $this->files->get($this->stubPath().'/blank.stub');
|
||||
}
|
||||
|
||||
// We also have stubs for creating new tables and modifying existing tables
|
||||
// to save the developer some typing when they are creating a new tables
|
||||
// or modifying existing tables. We'll grab the appropriate stub here.
|
||||
else {
|
||||
$stub = $create ? 'create.stub' : 'update.stub';
|
||||
|
||||
return $this->files->get($this->stubPath()."/{$stub}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the place-holders in the migration stub.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $stub
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
protected function populateStub($name, $stub, $table)
|
||||
{
|
||||
$stub = str_replace('DummyClass', $this->getClassName($name), $stub);
|
||||
|
||||
// Here we will replace the table place-holders with the table specified by
|
||||
// the developer, which is useful for quickly creating a tables creation
|
||||
// or update migration from the console instead of typing it manually.
|
||||
if (! is_null($table)) {
|
||||
$stub = str_replace('DummyTable', $table, $stub);
|
||||
}
|
||||
|
||||
return $stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of a migration name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function getClassName($name)
|
||||
{
|
||||
return Str::studly($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full path to the migration.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function getPath($name, $path)
|
||||
{
|
||||
return $path.'/'.$this->getDatePrefix().'_'.$name.'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire the registered post create hooks.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function firePostCreateHooks()
|
||||
{
|
||||
foreach ($this->postCreate as $callback) {
|
||||
call_user_func($callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a post migration create hook.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @return void
|
||||
*/
|
||||
public function afterCreate(Closure $callback)
|
||||
{
|
||||
$this->postCreate[] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date prefix for the migration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDatePrefix()
|
||||
{
|
||||
return date('Y_m_d_His');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to the stubs.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function stubPath()
|
||||
{
|
||||
return __DIR__.'/stubs';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filesystem instance.
|
||||
*
|
||||
* @return \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
public function getFilesystem()
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
}
|
||||
74
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php
vendored
Executable file
74
vendor/laravel/framework/src/Illuminate/Database/Migrations/MigrationRepositoryInterface.php
vendored
Executable file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
interface MigrationRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get the ran migrations for a given package.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRan();
|
||||
|
||||
/**
|
||||
* Get list of migrations.
|
||||
*
|
||||
* @param int $steps
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrations($steps);
|
||||
|
||||
/**
|
||||
* Get the last migration batch.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLast();
|
||||
|
||||
/**
|
||||
* Log that a migration was run.
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $batch
|
||||
* @return void
|
||||
*/
|
||||
public function log($file, $batch);
|
||||
|
||||
/**
|
||||
* Remove a migration from the log.
|
||||
*
|
||||
* @param object $migration
|
||||
* @return void
|
||||
*/
|
||||
public function delete($migration);
|
||||
|
||||
/**
|
||||
* Get the next migration batch number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getNextBatchNumber();
|
||||
|
||||
/**
|
||||
* Create the migration repository data store.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function createRepository();
|
||||
|
||||
/**
|
||||
* Determine if the migration repository exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function repositoryExists();
|
||||
|
||||
/**
|
||||
* Set the information source to gather data.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setSource($name);
|
||||
}
|
||||
575
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php
vendored
Executable file
575
vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php
vendored
Executable file
@@ -0,0 +1,575 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Migrations;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Database\ConnectionResolverInterface as Resolver;
|
||||
|
||||
class Migrator
|
||||
{
|
||||
/**
|
||||
* The migration repository implementation.
|
||||
*
|
||||
* @var \Illuminate\Database\Migrations\MigrationRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* The filesystem instance.
|
||||
*
|
||||
* @var \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
protected $files;
|
||||
|
||||
/**
|
||||
* The connection resolver instance.
|
||||
*
|
||||
* @var \Illuminate\Database\ConnectionResolverInterface
|
||||
*/
|
||||
protected $resolver;
|
||||
|
||||
/**
|
||||
* The name of the default connection.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* The notes for the current operation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $notes = [];
|
||||
|
||||
/**
|
||||
* The paths to all of the migration files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* Create a new migrator instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Migrations\MigrationRepositoryInterface $repository
|
||||
* @param \Illuminate\Database\ConnectionResolverInterface $resolver
|
||||
* @param \Illuminate\Filesystem\Filesystem $files
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(MigrationRepositoryInterface $repository,
|
||||
Resolver $resolver,
|
||||
Filesystem $files)
|
||||
{
|
||||
$this->files = $files;
|
||||
$this->resolver = $resolver;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the pending migrations at a given path.
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function run($paths = [], array $options = [])
|
||||
{
|
||||
$this->notes = [];
|
||||
|
||||
// Once we grab all of the migration files for the path, we will compare them
|
||||
// against the migrations that have already been run for this package then
|
||||
// run each of the outstanding migrations against a database connection.
|
||||
$files = $this->getMigrationFiles($paths);
|
||||
|
||||
$this->requireFiles($migrations = $this->pendingMigrations(
|
||||
$files, $this->repository->getRan()
|
||||
));
|
||||
|
||||
// Once we have all these migrations that are outstanding we are ready to run
|
||||
// we will go ahead and run them "up". This will execute each migration as
|
||||
// an operation against a database. Then we'll return this list of them.
|
||||
$this->runPending($migrations, $options);
|
||||
|
||||
return $migrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migration files that have not yet run.
|
||||
*
|
||||
* @param array $files
|
||||
* @param array $ran
|
||||
* @return array
|
||||
*/
|
||||
protected function pendingMigrations($files, $ran)
|
||||
{
|
||||
return Collection::make($files)
|
||||
->reject(function ($file) use ($ran) {
|
||||
return in_array($this->getMigrationName($file), $ran);
|
||||
})->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an array of migrations.
|
||||
*
|
||||
* @param array $migrations
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public function runPending(array $migrations, array $options = [])
|
||||
{
|
||||
// First we will just make sure that there are any migrations to run. If there
|
||||
// aren't, we will just make a note of it to the developer so they're aware
|
||||
// that all of the migrations have been run against this database system.
|
||||
if (count($migrations) == 0) {
|
||||
$this->note('<info>Nothing to migrate.</info>');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, we will get the next batch number for the migrations so we can insert
|
||||
// correct batch number in the database migrations repository when we store
|
||||
// each migration's execution. We will also extract a few of the options.
|
||||
$batch = $this->repository->getNextBatchNumber();
|
||||
|
||||
$pretend = Arr::get($options, 'pretend', false);
|
||||
|
||||
$step = Arr::get($options, 'step', false);
|
||||
|
||||
// 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
|
||||
// that the migration was run so we don't repeat it next time we execute.
|
||||
foreach ($migrations as $file) {
|
||||
$this->runUp($file, $batch, $pretend);
|
||||
|
||||
if ($step) {
|
||||
$batch++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run "up" a migration instance.
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $batch
|
||||
* @param bool $pretend
|
||||
* @return void
|
||||
*/
|
||||
protected function runUp($file, $batch, $pretend)
|
||||
{
|
||||
// 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)
|
||||
);
|
||||
|
||||
if ($pretend) {
|
||||
return $this->pretendToRun($migration, 'up');
|
||||
}
|
||||
|
||||
$this->note("<comment>Migrating:</comment> {$name}");
|
||||
|
||||
$this->runMigration($migration, 'up');
|
||||
|
||||
// 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}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the last migration operation.
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
public function rollback($paths = [], array $options = [])
|
||||
{
|
||||
$this->notes = [];
|
||||
|
||||
// We want to pull in the last batch of migrations that ran on the previous
|
||||
// migration operation. We'll then reverse those migrations and run each
|
||||
// of them "down" to reverse the last migration "operation" which ran.
|
||||
$migrations = $this->getMigrationsForRollback($options);
|
||||
|
||||
if (count($migrations) === 0) {
|
||||
$this->note('<info>Nothing to rollback.</info>');
|
||||
|
||||
return [];
|
||||
} else {
|
||||
return $this->rollbackMigrations($migrations, $paths, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migrations for a rollback operation.
|
||||
*
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function getMigrationsForRollback(array $options)
|
||||
{
|
||||
if (($steps = Arr::get($options, 'step', 0)) > 0) {
|
||||
return $this->repository->getMigrations($steps);
|
||||
} else {
|
||||
return $this->repository->getLast();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the given migrations.
|
||||
*
|
||||
* @param array $migrations
|
||||
* @param array|string $paths
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function rollbackMigrations(array $migrations, $paths, array $options)
|
||||
{
|
||||
$rolledBack = [];
|
||||
|
||||
$this->requireFiles($files = $this->getMigrationFiles($paths));
|
||||
|
||||
// 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
|
||||
// repository already returns these migration's names in reverse order.
|
||||
foreach ($migrations as $migration) {
|
||||
$migration = (object) $migration;
|
||||
|
||||
if (! $file = Arr::get($files, $migration->migration)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rolledBack[] = $file;
|
||||
|
||||
$this->runDown(
|
||||
$file, $migration,
|
||||
Arr::get($options, 'pretend', false)
|
||||
);
|
||||
}
|
||||
|
||||
return $rolledBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls all of the currently applied migrations back.
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param bool $pretend
|
||||
* @return array
|
||||
*/
|
||||
public function reset($paths = [], $pretend = false)
|
||||
{
|
||||
$this->notes = [];
|
||||
|
||||
// Next, we will reverse the migration list so we can run them back in the
|
||||
// correct order for resetting this database. This will allow us to get
|
||||
// the database back into its "empty" state ready for the migrations.
|
||||
$migrations = array_reverse($this->repository->getRan());
|
||||
|
||||
if (count($migrations) === 0) {
|
||||
$this->note('<info>Nothing to rollback.</info>');
|
||||
|
||||
return [];
|
||||
} else {
|
||||
return $this->resetMigrations($migrations, $paths, $pretend);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the given migrations.
|
||||
*
|
||||
* @param array $migrations
|
||||
* @param array $paths
|
||||
* @param bool $pretend
|
||||
* @return array
|
||||
*/
|
||||
protected function resetMigrations(array $migrations, array $paths, $pretend = false)
|
||||
{
|
||||
// Since the getRan method that retrieves the migration name just gives us the
|
||||
// migration name, we will format the names into objects with the name as a
|
||||
// property on the objects so that we can pass it to the rollback method.
|
||||
$migrations = collect($migrations)->map(function ($m) {
|
||||
return (object) ['migration' => $m];
|
||||
})->all();
|
||||
|
||||
return $this->rollbackMigrations(
|
||||
$migrations, $paths, compact('pretend')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run "down" a migration instance.
|
||||
*
|
||||
* @param string $file
|
||||
* @param object $migration
|
||||
* @param bool $pretend
|
||||
* @return void
|
||||
*/
|
||||
protected function runDown($file, $migration, $pretend)
|
||||
{
|
||||
// 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)
|
||||
);
|
||||
|
||||
$this->note("<comment>Rolling back:</comment> {$name}");
|
||||
|
||||
if ($pretend) {
|
||||
return $this->pretendToRun($instance, 'down');
|
||||
}
|
||||
|
||||
$this->runMigration($instance, 'down');
|
||||
|
||||
// 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}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a migration inside a transaction if the database supports it.
|
||||
*
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
protected function runMigration($migration, $method)
|
||||
{
|
||||
$connection = $this->resolveConnection(
|
||||
$migration->getConnection()
|
||||
);
|
||||
|
||||
$callback = function () use ($migration, $method) {
|
||||
if (method_exists($migration, $method)) {
|
||||
$migration->{$method}();
|
||||
}
|
||||
};
|
||||
|
||||
$this->getSchemaGrammar($connection)->supportsSchemaTransactions()
|
||||
? $connection->transaction($callback)
|
||||
: $callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretend to run the migrations.
|
||||
*
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return void
|
||||
*/
|
||||
protected function pretendToRun($migration, $method)
|
||||
{
|
||||
foreach ($this->getQueries($migration, $method) as $query) {
|
||||
$name = get_class($migration);
|
||||
|
||||
$this->note("<info>{$name}:</info> {$query['query']}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the queries that would be run for a migration.
|
||||
*
|
||||
* @param object $migration
|
||||
* @param string $method
|
||||
* @return array
|
||||
*/
|
||||
protected function getQueries($migration, $method)
|
||||
{
|
||||
// Now that we have the connections we can resolve it and pretend to run the
|
||||
// queries against the database returning the array of raw SQL statements
|
||||
// that would get fired against the database system for this migration.
|
||||
$db = $this->resolveConnection(
|
||||
$connection = $migration->getConnection()
|
||||
);
|
||||
|
||||
return $db->pretend(function () use ($migration, $method) {
|
||||
if (method_exists($migration, $method)) {
|
||||
$migration->{$method}();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a migration instance from a file.
|
||||
*
|
||||
* @param string $file
|
||||
* @return object
|
||||
*/
|
||||
public function resolve($file)
|
||||
{
|
||||
$class = Str::studly(implode('_', array_slice(explode('_', $file), 4)));
|
||||
|
||||
return new $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the migration files in a given path.
|
||||
*
|
||||
* @param string|array $paths
|
||||
* @return array
|
||||
*/
|
||||
public function getMigrationFiles($paths)
|
||||
{
|
||||
return Collection::make($paths)->flatMap(function ($path) {
|
||||
return $this->files->glob($path.'/*_*.php');
|
||||
})->filter()->sortBy(function ($file) {
|
||||
return $this->getMigrationName($file);
|
||||
})->values()->keyBy(function ($file) {
|
||||
return $this->getMigrationName($file);
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Require in all the migration files in a given path.
|
||||
*
|
||||
* @param array $files
|
||||
* @return void
|
||||
*/
|
||||
public function requireFiles(array $files)
|
||||
{
|
||||
foreach ($files as $file) {
|
||||
$this->files->requireOnce($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the migration.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public function getMigrationName($path)
|
||||
{
|
||||
return str_replace('.php', '', basename($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom migration path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
public function path($path)
|
||||
{
|
||||
$this->paths = array_unique(array_merge($this->paths, [$path]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the custom migration paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function paths()
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*/
|
||||
public function setConnection($name)
|
||||
{
|
||||
if (! is_null($name)) {
|
||||
$this->resolver->setDefaultConnection($name);
|
||||
}
|
||||
|
||||
$this->repository->setSource($name);
|
||||
|
||||
$this->connection = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the database connection instance.
|
||||
*
|
||||
* @param string $connection
|
||||
* @return \Illuminate\Database\Connection
|
||||
*/
|
||||
public function resolveConnection($connection)
|
||||
{
|
||||
return $this->resolver->connection($connection ?: $this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema grammar out of a migration connection.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return \Illuminate\Database\Schema\Grammars\Grammar
|
||||
*/
|
||||
protected function getSchemaGrammar($connection)
|
||||
{
|
||||
if (is_null($grammar = $connection->getSchemaGrammar())) {
|
||||
$connection->useDefaultSchemaGrammar();
|
||||
|
||||
$grammar = $connection->getSchemaGrammar();
|
||||
}
|
||||
|
||||
return $grammar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the migration repository instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Migrations\MigrationRepositoryInterface
|
||||
*/
|
||||
public function getRepository()
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the migration repository exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function repositoryExists()
|
||||
{
|
||||
return $this->repository->repositoryExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file system instance.
|
||||
*
|
||||
* @return \Illuminate\Filesystem\Filesystem
|
||||
*/
|
||||
public function getFilesystem()
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise a note event for the migrator.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
protected function note($message)
|
||||
{
|
||||
$this->notes[] = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notes for the last operation.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getNotes()
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
}
|
||||
28
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/blank.stub
vendored
Executable file
28
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/blank.stub
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DummyClass extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
31
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/create.stub
vendored
Executable file
31
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/create.stub
vendored
Executable file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DummyClass extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('DummyTable', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('DummyTable');
|
||||
}
|
||||
}
|
||||
32
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/update.stub
vendored
Executable file
32
vendor/laravel/framework/src/Illuminate/Database/Migrations/stubs/update.stub
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class DummyClass extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('DummyTable', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('DummyTable', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
84
vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php
vendored
Executable file
84
vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use PDO;
|
||||
use Illuminate\Database\Schema\MySqlBuilder;
|
||||
use Illuminate\Database\Query\Processors\MySqlProcessor;
|
||||
use Doctrine\DBAL\Driver\PDOMySql\Driver as DoctrineDriver;
|
||||
use Illuminate\Database\Query\Grammars\MySqlGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Schema\Grammars\MySqlGrammar as SchemaGrammar;
|
||||
|
||||
class MySqlConnection extends Connection
|
||||
{
|
||||
/**
|
||||
* Get the default query grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Grammars\MySqlGrammar
|
||||
*/
|
||||
protected function getDefaultQueryGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new QueryGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a schema builder instance for the connection.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\MySqlBuilder
|
||||
*/
|
||||
public function getSchemaBuilder()
|
||||
{
|
||||
if (is_null($this->schemaGrammar)) {
|
||||
$this->useDefaultSchemaGrammar();
|
||||
}
|
||||
|
||||
return new MySqlBuilder($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default schema grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\Grammars\MySqlGrammar
|
||||
*/
|
||||
protected function getDefaultSchemaGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Processors\MySqlProcessor
|
||||
*/
|
||||
protected function getDefaultPostProcessor()
|
||||
{
|
||||
return new MySqlProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOMySql\Driver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind values to their parameters in the given statement.
|
||||
*
|
||||
* @param \PDOStatement $statement
|
||||
* @param array $bindings
|
||||
* @return void
|
||||
*/
|
||||
public function bindValues($statement, $bindings)
|
||||
{
|
||||
foreach ($bindings as $key => $value) {
|
||||
$statement->bindValue(
|
||||
is_string($key) ? $key : $key + 1, $value,
|
||||
is_int($value) || is_float($value) ? PDO::PARAM_INT : PDO::PARAM_STR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
vendor/laravel/framework/src/Illuminate/Database/PostgresConnection.php
vendored
Executable file
66
vendor/laravel/framework/src/Illuminate/Database/PostgresConnection.php
vendored
Executable file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use Illuminate\Database\Schema\PostgresBuilder;
|
||||
use Doctrine\DBAL\Driver\PDOPgSql\Driver as DoctrineDriver;
|
||||
use Illuminate\Database\Query\Processors\PostgresProcessor;
|
||||
use Illuminate\Database\Query\Grammars\PostgresGrammar as QueryGrammar;
|
||||
use Illuminate\Database\Schema\Grammars\PostgresGrammar as SchemaGrammar;
|
||||
|
||||
class PostgresConnection extends Connection
|
||||
{
|
||||
/**
|
||||
* Get the default query grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Grammars\PostgresGrammar
|
||||
*/
|
||||
protected function getDefaultQueryGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new QueryGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a schema builder instance for the connection.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\PostgresBuilder
|
||||
*/
|
||||
public function getSchemaBuilder()
|
||||
{
|
||||
if (is_null($this->schemaGrammar)) {
|
||||
$this->useDefaultSchemaGrammar();
|
||||
}
|
||||
|
||||
return new PostgresBuilder($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default schema grammar instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Schema\Grammars\PostgresGrammar
|
||||
*/
|
||||
protected function getDefaultSchemaGrammar()
|
||||
{
|
||||
return $this->withTablePrefix(new SchemaGrammar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default post processor instance.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\Processors\PostgresProcessor
|
||||
*/
|
||||
protected function getDefaultPostProcessor()
|
||||
{
|
||||
return new PostgresProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Doctrine DBAL driver.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Driver\PDOPgSql\Driver
|
||||
*/
|
||||
protected function getDoctrineDriver()
|
||||
{
|
||||
return new DoctrineDriver;
|
||||
}
|
||||
}
|
||||
2452
vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
vendored
Executable file
2452
vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
44
vendor/laravel/framework/src/Illuminate/Database/Query/Expression.php
vendored
Executable file
44
vendor/laravel/framework/src/Illuminate/Database/Query/Expression.php
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query;
|
||||
|
||||
class Expression
|
||||
{
|
||||
/**
|
||||
* The value of the expression.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Create a new raw query expression.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the expression.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the expression.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->getValue();
|
||||
}
|
||||
}
|
||||
852
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php
vendored
Executable file
852
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php
vendored
Executable file
@@ -0,0 +1,852 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Grammars;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Database\Grammar as BaseGrammar;
|
||||
|
||||
class Grammar extends BaseGrammar
|
||||
{
|
||||
/**
|
||||
* The grammar specific operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators = [];
|
||||
|
||||
/**
|
||||
* The components that make up a select clause.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selectComponents = [
|
||||
'aggregate',
|
||||
'columns',
|
||||
'from',
|
||||
'joins',
|
||||
'wheres',
|
||||
'groups',
|
||||
'havings',
|
||||
'orders',
|
||||
'limit',
|
||||
'offset',
|
||||
'unions',
|
||||
'lock',
|
||||
];
|
||||
|
||||
/**
|
||||
* Compile a select query into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileSelect(Builder $query)
|
||||
{
|
||||
// If the query does not have any columns set, we'll set the columns to the
|
||||
// * character to just get all of the columns from the database. Then we
|
||||
// can build the query and concatenate all the pieces together as one.
|
||||
$original = $query->columns;
|
||||
|
||||
if (is_null($query->columns)) {
|
||||
$query->columns = ['*'];
|
||||
}
|
||||
|
||||
// To compile the query, we'll spin through each component of the query and
|
||||
// see if that component exists. If it does we'll just call the compiler
|
||||
// function for the component which is responsible for making the SQL.
|
||||
$sql = trim($this->concatenate(
|
||||
$this->compileComponents($query))
|
||||
);
|
||||
|
||||
$query->columns = $original;
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the components necessary for a select clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
protected function compileComponents(Builder $query)
|
||||
{
|
||||
$sql = [];
|
||||
|
||||
foreach ($this->selectComponents as $component) {
|
||||
// To compile the query, we'll spin through each component of the query and
|
||||
// see if that component exists. If it does we'll just call the compiler
|
||||
// function for the component which is responsible for making the SQL.
|
||||
if (! is_null($query->$component)) {
|
||||
$method = 'compile'.ucfirst($component);
|
||||
|
||||
$sql[$component] = $this->$method($query, $query->$component);
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an aggregated select clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $aggregate
|
||||
* @return string
|
||||
*/
|
||||
protected function compileAggregate(Builder $query, $aggregate)
|
||||
{
|
||||
$column = $this->columnize($aggregate['columns']);
|
||||
|
||||
// If the query has a "distinct" constraint and we're not asking for all columns
|
||||
// we need to prepend "distinct" onto the column name so that the query takes
|
||||
// it into account when it performs the aggregating operations on the data.
|
||||
if ($query->distinct && $column !== '*') {
|
||||
$column = 'distinct '.$column;
|
||||
}
|
||||
|
||||
return 'select '.$aggregate['function'].'('.$column.') as aggregate';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "select *" portion of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $columns
|
||||
* @return string|null
|
||||
*/
|
||||
protected function compileColumns(Builder $query, $columns)
|
||||
{
|
||||
// If the query is actually performing an aggregating select, we will let that
|
||||
// compiler handle the building of the select clauses, as it will need some
|
||||
// more syntax that is best handled by that function to keep things neat.
|
||||
if (! is_null($query->aggregate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$select = $query->distinct ? 'select distinct ' : 'select ';
|
||||
|
||||
return $select.$this->columnize($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "from" portion of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
protected function compileFrom(Builder $query, $table)
|
||||
{
|
||||
return 'from '.$this->wrapTable($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "join" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $joins
|
||||
* @return string
|
||||
*/
|
||||
protected function compileJoins(Builder $query, $joins)
|
||||
{
|
||||
return collect($joins)->map(function ($join) use ($query) {
|
||||
$table = $this->wrapTable($join->table);
|
||||
|
||||
return trim("{$join->type} join {$table} {$this->compileWheres($join)}");
|
||||
})->implode(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "where" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected 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
|
||||
// and maintainable since each clause has a very small method that it uses.
|
||||
if (is_null($query->wheres)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// If we actually have some where clauses, we will strip off the first boolean
|
||||
// operator, which is added by the query builders for convenience so we can
|
||||
// avoid checking for the first clauses in each of the compilers methods.
|
||||
if (count($sql = $this->compileWheresToArray($query)) > 0) {
|
||||
return $this->concatenateWhereClauses($query, $sql);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of all the where clauses for the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
protected function compileWheresToArray($query)
|
||||
{
|
||||
return collect($query->wheres)->map(function ($where) use ($query) {
|
||||
return $where['boolean'].' '.$this->{"where{$where['type']}"}($query, $where);
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the where clause statements into one string.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $sql
|
||||
* @return string
|
||||
*/
|
||||
protected function concatenateWhereClauses($query, $sql)
|
||||
{
|
||||
$conjunction = $query instanceof JoinClause ? 'on' : 'where';
|
||||
|
||||
return $conjunction.' '.$this->removeLeadingBoolean(implode(' ', $sql));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a raw where clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereRaw(Builder $query, $where)
|
||||
{
|
||||
return $where['sql'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a basic where clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereBasic(Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
return $this->wrap($where['column']).' '.$where['operator'].' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where in" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereIn(Builder $query, $where)
|
||||
{
|
||||
if (! empty($where['values'])) {
|
||||
return $this->wrap($where['column']).' in ('.$this->parameterize($where['values']).')';
|
||||
}
|
||||
|
||||
return '0 = 1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where not in" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNotIn(Builder $query, $where)
|
||||
{
|
||||
if (! empty($where['values'])) {
|
||||
return $this->wrap($where['column']).' not in ('.$this->parameterize($where['values']).')';
|
||||
}
|
||||
|
||||
return '1 = 1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where in sub-select clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereInSub(Builder $query, $where)
|
||||
{
|
||||
return $this->wrap($where['column']).' in ('.$this->compileSelect($where['query']).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where not in sub-select clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNotInSub(Builder $query, $where)
|
||||
{
|
||||
return $this->wrap($where['column']).' not in ('.$this->compileSelect($where['query']).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where null" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNull(Builder $query, $where)
|
||||
{
|
||||
return $this->wrap($where['column']).' is null';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where not null" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNotNull(Builder $query, $where)
|
||||
{
|
||||
return $this->wrap($where['column']).' is not null';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "between" where clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereBetween(Builder $query, $where)
|
||||
{
|
||||
$between = $where['not'] ? 'not between' : 'between';
|
||||
|
||||
return $this->wrap($where['column']).' '.$between.' ? and ?';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where date" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereDate(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('date', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where time" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereTime(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('time', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where day" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereDay(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('day', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where month" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereMonth(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('month', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where year" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereYear(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('year', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a date based where clause.
|
||||
*
|
||||
* @param string $type
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function dateBasedWhere($type, Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
return $type.'('.$this->wrap($where['column']).') '.$where['operator'].' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where clause comparing two columns..
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereColumn(Builder $query, $where)
|
||||
{
|
||||
return $this->wrap($where['first']).' '.$where['operator'].' '.$this->wrap($where['second']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a nested where clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNested(Builder $query, $where)
|
||||
{
|
||||
// Here we will calculate what portion of the string we need to remove. If this
|
||||
// is a join clause query, we need to remove the "on" portion of the SQL and
|
||||
// if it is a normal query we need to take the leading "where" of queries.
|
||||
$offset = $query instanceof JoinClause ? 3 : 6;
|
||||
|
||||
return '('.substr($this->compileWheres($where['query']), $offset).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where condition with a sub-select.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereSub(Builder $query, $where)
|
||||
{
|
||||
$select = $this->compileSelect($where['query']);
|
||||
|
||||
return $this->wrap($where['column']).' '.$where['operator']." ($select)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where exists clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereExists(Builder $query, $where)
|
||||
{
|
||||
return 'exists ('.$this->compileSelect($where['query']).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a where exists clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereNotExists(Builder $query, $where)
|
||||
{
|
||||
return 'not exists ('.$this->compileSelect($where['query']).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "group by" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $groups
|
||||
* @return string
|
||||
*/
|
||||
protected function compileGroups(Builder $query, $groups)
|
||||
{
|
||||
return 'group by '.$this->columnize($groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "having" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $havings
|
||||
* @return string
|
||||
*/
|
||||
protected function compileHavings(Builder $query, $havings)
|
||||
{
|
||||
$sql = implode(' ', array_map([$this, 'compileHaving'], $havings));
|
||||
|
||||
return 'having '.$this->removeLeadingBoolean($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a single having clause.
|
||||
*
|
||||
* @param array $having
|
||||
* @return string
|
||||
*/
|
||||
protected function compileHaving(array $having)
|
||||
{
|
||||
// If the having clause is "raw", we can just return the clause straight away
|
||||
// without doing any more processing on it. Otherwise, we will compile the
|
||||
// clause into SQL based on the components that make it up from builder.
|
||||
if ($having['type'] === 'Raw') {
|
||||
return $having['boolean'].' '.$having['sql'];
|
||||
}
|
||||
|
||||
return $this->compileBasicHaving($having);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a basic having clause.
|
||||
*
|
||||
* @param array $having
|
||||
* @return string
|
||||
*/
|
||||
protected function compileBasicHaving($having)
|
||||
{
|
||||
$column = $this->wrap($having['column']);
|
||||
|
||||
$parameter = $this->parameter($having['value']);
|
||||
|
||||
return $having['boolean'].' '.$column.' '.$having['operator'].' '.$parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "order by" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $orders
|
||||
* @return string
|
||||
*/
|
||||
protected function compileOrders(Builder $query, $orders)
|
||||
{
|
||||
if (! empty($orders)) {
|
||||
return 'order by '.implode(', ', $this->compileOrdersToArray($query, $orders));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the query orders to an array.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder
|
||||
* @param array $orders
|
||||
* @return array
|
||||
*/
|
||||
protected function compileOrdersToArray(Builder $query, $orders)
|
||||
{
|
||||
return array_map(function ($order) {
|
||||
return ! isset($order['sql'])
|
||||
? $this->wrap($order['column']).' '.$order['direction']
|
||||
: $order['sql'];
|
||||
}, $orders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the random statement into SQL.
|
||||
*
|
||||
* @param string $seed
|
||||
* @return string
|
||||
*/
|
||||
public function compileRandom($seed)
|
||||
{
|
||||
return 'RANDOM()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "limit" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param int $limit
|
||||
* @return string
|
||||
*/
|
||||
protected function compileLimit(Builder $query, $limit)
|
||||
{
|
||||
return 'limit '.(int) $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "offset" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param int $offset
|
||||
* @return string
|
||||
*/
|
||||
protected function compileOffset(Builder $query, $offset)
|
||||
{
|
||||
return 'offset '.(int) $offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "union" queries attached to the main query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUnions(Builder $query)
|
||||
{
|
||||
$sql = '';
|
||||
|
||||
foreach ($query->unions as $union) {
|
||||
$sql .= $this->compileUnion($union);
|
||||
}
|
||||
|
||||
if (! empty($query->unionOrders)) {
|
||||
$sql .= ' '.$this->compileOrders($query, $query->unionOrders);
|
||||
}
|
||||
|
||||
if (isset($query->unionLimit)) {
|
||||
$sql .= ' '.$this->compileLimit($query, $query->unionLimit);
|
||||
}
|
||||
|
||||
if (isset($query->unionOffset)) {
|
||||
$sql .= ' '.$this->compileOffset($query, $query->unionOffset);
|
||||
}
|
||||
|
||||
return ltrim($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a single union statement.
|
||||
*
|
||||
* @param array $union
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUnion(array $union)
|
||||
{
|
||||
$conjuction = $union['all'] ? ' union all ' : ' union ';
|
||||
|
||||
return $conjuction.$union['query']->toSql();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an exists statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileExists(Builder $query)
|
||||
{
|
||||
$select = $this->compileSelect($query);
|
||||
|
||||
return "select exists({$select}) as {$this->wrap('exists')}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an insert statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileInsert(Builder $query, array $values)
|
||||
{
|
||||
// Essentially we will force every insert to be treated as a batch insert which
|
||||
// simply makes creating the SQL easier for us since we can utilize the same
|
||||
// basic routine regardless of an amount of records given to us to insert.
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
if (! is_array(reset($values))) {
|
||||
$values = [$values];
|
||||
}
|
||||
|
||||
$columns = $this->columnize(array_keys(reset($values)));
|
||||
|
||||
// We need to build a list of parameter place-holders of values that are bound
|
||||
// to the query. Each insert should have the exact same amount of parameter
|
||||
// bindings so we will loop through the record and parameterize them all.
|
||||
$parameters = collect($values)->map(function ($record) {
|
||||
return '('.$this->parameterize($record).')';
|
||||
})->implode(', ');
|
||||
|
||||
return "insert into $table ($columns) values $parameters";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an insert and get ID statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param string $sequence
|
||||
* @return string
|
||||
*/
|
||||
public function compileInsertGetId(Builder $query, $values, $sequence)
|
||||
{
|
||||
return $this->compileInsert($query, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an update statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpdate(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 = collect($values)->map(function ($value, $key) {
|
||||
return $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
|
||||
// If the query has any "join" clauses, we will setup the joins on the builder
|
||||
// and compile them so we can attach them to this update, as update queries
|
||||
// can get join statements to attach to other tables when they're needed.
|
||||
$joins = '';
|
||||
|
||||
if (isset($query->joins)) {
|
||||
$joins = ' '.$this->compileJoins($query, $query->joins);
|
||||
}
|
||||
|
||||
// Of course, update queries may also be constrained by where clauses so we'll
|
||||
// need to compile the where clauses and attach it to the query so only the
|
||||
// intended records are updated by the SQL statements we generate to run.
|
||||
$wheres = $this->compileWheres($query);
|
||||
|
||||
return trim("update {$table}{$joins} set $columns $wheres");
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the bindings for an update statement.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function prepareBindingsForUpdate(array $bindings, array $values)
|
||||
{
|
||||
$bindingsWithoutJoin = Arr::except($bindings, 'join');
|
||||
|
||||
return array_values(
|
||||
array_merge($bindings['join'], $values, Arr::flatten($bindingsWithoutJoin))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileDelete(Builder $query)
|
||||
{
|
||||
$wheres = is_array($query->wheres) ? $this->compileWheres($query) : '';
|
||||
|
||||
return trim("delete from {$this->wrapTable($query->from)} $wheres");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a truncate table statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
public function compileTruncate(Builder $query)
|
||||
{
|
||||
return ['truncate '.$this->wrapTable($query->from) => []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the lock into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param bool|string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function compileLock(Builder $query, $value)
|
||||
{
|
||||
return is_string($value) ? $value : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the grammar supports savepoints.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsSavepoints()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL statement to define a savepoint.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function compileSavepoint($name)
|
||||
{
|
||||
return 'SAVEPOINT '.$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL statement to execute a savepoint rollback.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function compileSavepointRollBack($name)
|
||||
{
|
||||
return 'ROLLBACK TO SAVEPOINT '.$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate an array of segments, removing empties.
|
||||
*
|
||||
* @param array $segments
|
||||
* @return string
|
||||
*/
|
||||
protected function concatenate($segments)
|
||||
{
|
||||
return implode(' ', array_filter($segments, function ($value) {
|
||||
return (string) $value !== '';
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the leading boolean from a statement.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function removeLeadingBoolean($value)
|
||||
{
|
||||
return preg_replace('/and |or /i', '', $value, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the grammar specific operators.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOperators()
|
||||
{
|
||||
return $this->operators;
|
||||
}
|
||||
}
|
||||
300
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php
vendored
Executable file
300
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/MySqlGrammar.php
vendored
Executable file
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Grammars;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Database\Query\JsonExpression;
|
||||
|
||||
class MySqlGrammar extends Grammar
|
||||
{
|
||||
/**
|
||||
* The components that make up a select clause.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selectComponents = [
|
||||
'aggregate',
|
||||
'columns',
|
||||
'from',
|
||||
'joins',
|
||||
'wheres',
|
||||
'groups',
|
||||
'havings',
|
||||
'orders',
|
||||
'limit',
|
||||
'offset',
|
||||
'lock',
|
||||
];
|
||||
|
||||
/**
|
||||
* Compile a select query into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileSelect(Builder $query)
|
||||
{
|
||||
$sql = parent::compileSelect($query);
|
||||
|
||||
if ($query->unions) {
|
||||
$sql = '('.$sql.') '.$this->compileUnions($query);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a single union statement.
|
||||
*
|
||||
* @param array $union
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUnion(array $union)
|
||||
{
|
||||
$conjuction = $union['all'] ? ' union all ' : ' union ';
|
||||
|
||||
return $conjuction.'('.$union['query']->toSql().')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the random statement into SQL.
|
||||
*
|
||||
* @param string $seed
|
||||
* @return string
|
||||
*/
|
||||
public function compileRandom($seed)
|
||||
{
|
||||
return 'RAND('.$seed.')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the lock into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param bool|string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function compileLock(Builder $query, $value)
|
||||
{
|
||||
if (! is_string($value)) {
|
||||
return $value ? 'for update' : 'lock in share mode';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an update statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpdate(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($values);
|
||||
|
||||
// If the query has any "join" clauses, we will setup the joins on the builder
|
||||
// and compile them so we can attach them to this update, as update queries
|
||||
// can get join statements to attach to other tables when they're needed.
|
||||
$joins = '';
|
||||
|
||||
if (isset($query->joins)) {
|
||||
$joins = ' '.$this->compileJoins($query, $query->joins);
|
||||
}
|
||||
|
||||
// Of course, update queries may also be constrained by where clauses so we'll
|
||||
// need to compile the where clauses and attach it to the query so only the
|
||||
// intended records are updated by the SQL statements we generate to run.
|
||||
$where = $this->compileWheres($query);
|
||||
|
||||
$sql = rtrim("update {$table}{$joins} set $columns $where");
|
||||
|
||||
// If the query has an order by clause we will compile it since MySQL supports
|
||||
// order bys on update statements. We'll compile them using the typical way
|
||||
// of compiling order bys. Then they will be appended to the SQL queries.
|
||||
if (! empty($query->orders)) {
|
||||
$sql .= ' '.$this->compileOrders($query, $query->orders);
|
||||
}
|
||||
|
||||
// Updates on MySQL also supports "limits", which allow you to easily update a
|
||||
// single record very easily. This is not supported by all database engines
|
||||
// so we have customized this update compiler here in order to add it in.
|
||||
if (isset($query->limit)) {
|
||||
$sql .= ' '.$this->compileLimit($query, $query->limit);
|
||||
}
|
||||
|
||||
return rtrim($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile all of the columns for an update statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUpdateColumns($values)
|
||||
{
|
||||
return collect($values)->map(function ($value, $key) {
|
||||
if ($this->isJsonSelector($key)) {
|
||||
return $this->compileJsonUpdateColumn($key, new JsonExpression($value));
|
||||
} else {
|
||||
return $this->wrap($key).' = '.$this->parameter($value);
|
||||
}
|
||||
})->implode(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a JSON column being updated using the JSON_SET function.
|
||||
*
|
||||
* @param string $key
|
||||
* @param \Illuminate\Database\Query\JsonExpression $value
|
||||
* @return string
|
||||
*/
|
||||
protected function compileJsonUpdateColumn($key, JsonExpression $value)
|
||||
{
|
||||
$path = explode('->', $key);
|
||||
|
||||
$field = $this->wrapValue(array_shift($path));
|
||||
|
||||
$accessor = '"$.'.implode('.', $path).'"';
|
||||
|
||||
return "{$field} = json_set({$field}, {$accessor}, {$value->getValue()})";
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the bindings for an update statement.
|
||||
*
|
||||
* Booleans, integers, and doubles are inserted into JSON updates as raw values.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function prepareBindingsForUpdate(array $bindings, array $values)
|
||||
{
|
||||
$values = collect($values)->reject(function ($value, $column) {
|
||||
return $this->isJsonSelector($column) &&
|
||||
in_array(gettype($value), ['boolean', 'integer', 'double']);
|
||||
})->all();
|
||||
|
||||
return parent::prepareBindingsForUpdate($bindings, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileDelete(Builder $query)
|
||||
{
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
$where = is_array($query->wheres) ? $this->compileWheres($query) : '';
|
||||
|
||||
return isset($query->joins)
|
||||
? $this->compileDeleteWithJoins($query, $table, $where)
|
||||
: $this->compileDeleteWithoutJoins($query, $table, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete query that does not use joins.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $table
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function compileDeleteWithoutJoins($query, $table, $where)
|
||||
{
|
||||
$sql = trim("delete from {$table} {$where}");
|
||||
|
||||
// When using MySQL, delete statements may contain order by statements and limits
|
||||
// so we will compile both of those here. Once we have finished compiling this
|
||||
// we will return the completed SQL statement so it will be executed for us.
|
||||
if (! empty($query->orders)) {
|
||||
$sql .= ' '.$this->compileOrders($query, $query->orders);
|
||||
}
|
||||
|
||||
if (isset($query->limit)) {
|
||||
$sql .= ' '.$this->compileLimit($query, $query->limit);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete query that uses joins.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $table
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function compileDeleteWithJoins($query, $table, $where)
|
||||
{
|
||||
$joins = ' '.$this->compileJoins($query, $query->joins);
|
||||
|
||||
$alias = strpos(strtolower($table), ' as ') !== false
|
||||
? explode(' as ', $table)[1] : $table;
|
||||
|
||||
return trim("delete {$alias} from {$table}{$joins} {$where}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a single string in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapValue($value)
|
||||
{
|
||||
if ($value === '*') {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// If the given value is a JSON selector we will wrap it differently than a
|
||||
// traditional value. We will need to split this path and wrap each part
|
||||
// wrapped, etc. Otherwise, we will simply wrap the value as a string.
|
||||
if ($this->isJsonSelector($value)) {
|
||||
return $this->wrapJsonSelector($value);
|
||||
}
|
||||
|
||||
return '`'.str_replace('`', '``', $value).'`';
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given JSON selector.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapJsonSelector($value)
|
||||
{
|
||||
$path = explode('->', $value);
|
||||
|
||||
$field = $this->wrapValue(array_shift($path));
|
||||
|
||||
return sprintf('%s->\'$.%s\'', $field, collect($path)->map(function ($part) {
|
||||
return '"'.$part.'"';
|
||||
})->implode('.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given string is a JSON selector.
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function isJsonSelector($value)
|
||||
{
|
||||
return Str::contains($value, '->');
|
||||
}
|
||||
}
|
||||
331
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php
vendored
Executable file
331
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/PostgresGrammar.php
vendored
Executable file
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Grammars;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class PostgresGrammar extends Grammar
|
||||
{
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators = [
|
||||
'=', '<', '>', '<=', '>=', '<>', '!=',
|
||||
'like', 'not like', 'between', 'ilike',
|
||||
'&', '|', '#', '<<', '>>',
|
||||
'@>', '<@', '?', '?|', '?&', '||', '-', '-', '#-',
|
||||
];
|
||||
|
||||
/**
|
||||
* Compile a "where date" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereDate(Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
return $this->wrap($where['column']).'::date '.$where['operator'].' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a date based where clause.
|
||||
*
|
||||
* @param string $type
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function dateBasedWhere($type, Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
return 'extract('.$type.' from '.$this->wrap($where['column']).') '.$where['operator'].' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the lock into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param bool|string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function compileLock(Builder $query, $value)
|
||||
{
|
||||
if (! is_string($value)) {
|
||||
return $value ? 'for update' : 'for share';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compileInsert(Builder $query, array $values)
|
||||
{
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
return empty($values)
|
||||
? "insert into {$table} DEFAULT VALUES"
|
||||
: parent::compileInsert($query, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an insert and get ID statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @param string $sequence
|
||||
* @return string
|
||||
*/
|
||||
public function compileInsertGetId(Builder $query, $values, $sequence)
|
||||
{
|
||||
if (is_null($sequence)) {
|
||||
$sequence = 'id';
|
||||
}
|
||||
|
||||
return $this->compileInsert($query, $values).' returning '.$this->wrap($sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an update statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpdate(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($values);
|
||||
|
||||
$from = $this->compileUpdateFrom($query);
|
||||
|
||||
$where = $this->compileUpdateWheres($query);
|
||||
|
||||
return trim("update {$table} set {$columns}{$from} {$where}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the columns for the update statement.
|
||||
*
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUpdateColumns($values)
|
||||
{
|
||||
// When gathering the columns for an update statement, we'll wrap each of the
|
||||
// columns and convert it to a parameter value. Then we will concatenate a
|
||||
// list of the columns that can be added into this update query clauses.
|
||||
return collect($values)->map(function ($value, $key) {
|
||||
return $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "from" clause for an update with a join.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string|null
|
||||
*/
|
||||
protected function compileUpdateFrom(Builder $query)
|
||||
{
|
||||
if (! isset($query->joins)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return ' from '.implode(', ', $froms);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 prepareBindingsForUpdate(array $bindings, array $values)
|
||||
{
|
||||
// Update statements with "joins" in Postgres use an interesting syntax. We need to
|
||||
// take all of the bindings and put them on the end of this array since they are
|
||||
// added to the end of the "where" clause statements as typical where clauses.
|
||||
$bindingsWithoutJoin = Arr::except($bindings, 'join');
|
||||
|
||||
return array_values(
|
||||
array_merge($values, $bindings['join'], Arr::flatten($bindingsWithoutJoin))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileDelete(Builder $query)
|
||||
{
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
return isset($query->joins)
|
||||
? $this->compileDeleteWithJoins($query, $table)
|
||||
: parent::compileDelete($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete query that uses joins.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $table
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function compileDeleteWithJoins($query, $table)
|
||||
{
|
||||
$using = ' USING '.collect($query->joins)->map(function ($join) {
|
||||
return $this->wrapTable($join->table);
|
||||
})->implode(', ');
|
||||
|
||||
$where = count($query->wheres) > 0 ? ' '.$this->compileUpdateWheres($query) : '';
|
||||
|
||||
return trim("delete from {$table}{$using}{$where}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a truncate table statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
public function compileTruncate(Builder $query)
|
||||
{
|
||||
return ['truncate '.$this->wrapTable($query->from).' restart identity' => []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a single string in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapValue($value)
|
||||
{
|
||||
if ($value === '*') {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// If the given value is a JSON selector we will wrap it differently than a
|
||||
// traditional value. We will need to split this path and wrap each part
|
||||
// wrapped, etc. Otherwise, we will simply wrap the value as a string.
|
||||
if (Str::contains($value, '->')) {
|
||||
return $this->wrapJsonSelector($value);
|
||||
}
|
||||
|
||||
return '"'.str_replace('"', '""', $value).'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the given JSON selector.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapJsonSelector($value)
|
||||
{
|
||||
$path = explode('->', $value);
|
||||
|
||||
$field = $this->wrapValue(array_shift($path));
|
||||
|
||||
$wrappedPath = $this->wrapJsonPathAttributes($path);
|
||||
|
||||
$attribute = array_pop($wrappedPath);
|
||||
|
||||
if (! empty($wrappedPath)) {
|
||||
return $field.'->'.implode('->', $wrappedPath).'->>'.$attribute;
|
||||
}
|
||||
|
||||
return $field.'->>'.$attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the attributes of the give JSON path.
|
||||
*
|
||||
* @param array $path
|
||||
* @return array
|
||||
*/
|
||||
protected function wrapJsonPathAttributes($path)
|
||||
{
|
||||
return array_map(function ($attribute) {
|
||||
return "'$attribute'";
|
||||
}, $path);
|
||||
}
|
||||
}
|
||||
188
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php
vendored
Executable file
188
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SQLiteGrammar.php
vendored
Executable file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Grammars;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class SQLiteGrammar extends Grammar
|
||||
{
|
||||
/**
|
||||
* The components that make up a select clause.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $selectComponents = [
|
||||
'aggregate',
|
||||
'columns',
|
||||
'from',
|
||||
'joins',
|
||||
'wheres',
|
||||
'groups',
|
||||
'havings',
|
||||
'orders',
|
||||
'limit',
|
||||
'offset',
|
||||
'lock',
|
||||
];
|
||||
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators = [
|
||||
'=', '<', '>', '<=', '>=', '<>', '!=',
|
||||
'like', 'not like', 'between', 'ilike',
|
||||
'&', '|', '<<', '>>',
|
||||
];
|
||||
|
||||
/**
|
||||
* Compile a select query into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileSelect(Builder $query)
|
||||
{
|
||||
$sql = parent::compileSelect($query);
|
||||
|
||||
if ($query->unions) {
|
||||
$sql = 'select * from ('.$sql.') '.$this->compileUnions($query);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a single union statement.
|
||||
*
|
||||
* @param array $union
|
||||
* @return string
|
||||
*/
|
||||
protected function compileUnion(array $union)
|
||||
{
|
||||
$conjuction = $union['all'] ? ' union all ' : ' union ';
|
||||
|
||||
return $conjuction.'select * from ('.$union['query']->toSql().')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where date" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereDate(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('%Y-%m-%d', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where day" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereDay(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('%d', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where month" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereMonth(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('%m', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where year" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereYear(Builder $query, $where)
|
||||
{
|
||||
return $this->dateBasedWhere('%Y', $query, $where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a date based where clause.
|
||||
*
|
||||
* @param string $type
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function dateBasedWhere($type, Builder $query, $where)
|
||||
{
|
||||
$value = str_pad($where['value'], 2, '0', STR_PAD_LEFT);
|
||||
|
||||
$value = $this->parameter($value);
|
||||
|
||||
return "strftime('{$type}', {$this->wrap($where['column'])}) {$where['operator']} {$value}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an insert statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileInsert(Builder $query, array $values)
|
||||
{
|
||||
// Essentially we will force every insert to be treated as a batch insert which
|
||||
// simply makes creating the SQL easier for us since we can utilize the same
|
||||
// basic routine regardless of an amount of records given to us to insert.
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
if (! is_array(reset($values))) {
|
||||
$values = [$values];
|
||||
}
|
||||
|
||||
// If there is only one record being inserted, we will just use the usual query
|
||||
// grammar insert builder because no special syntax is needed for the single
|
||||
// row inserts in SQLite. However, if there are multiples, we'll continue.
|
||||
if (count($values) == 1) {
|
||||
return parent::compileInsert($query, reset($values));
|
||||
}
|
||||
|
||||
$names = $this->columnize(array_keys(reset($values)));
|
||||
|
||||
$columns = [];
|
||||
|
||||
// SQLite requires us to build the multi-row insert as a listing of select with
|
||||
// unions joining them together. So we'll build out this list of columns and
|
||||
// then join them all together with select unions to complete the queries.
|
||||
foreach (array_keys(reset($values)) as $column) {
|
||||
$columns[] = '? as '.$this->wrap($column);
|
||||
}
|
||||
|
||||
$columns = array_fill(0, count($values), implode(', ', $columns));
|
||||
|
||||
return "insert into $table ($names) select ".implode(' union all select ', $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a truncate table statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
public function compileTruncate(Builder $query)
|
||||
{
|
||||
return [
|
||||
'delete from sqlite_sequence where name = ?' => [$query->from],
|
||||
'delete from '.$this->wrapTable($query->from) => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
442
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
vendored
Executable file
442
vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/SqlServerGrammar.php
vendored
Executable file
@@ -0,0 +1,442 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Grammars;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class SqlServerGrammar extends Grammar
|
||||
{
|
||||
/**
|
||||
* All of the available clause operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $operators = [
|
||||
'=', '<', '>', '<=', '>=', '!<', '!>', '<>', '!=',
|
||||
'like', 'not like', 'between', 'ilike',
|
||||
'&', '&=', '|', '|=', '^', '^=',
|
||||
];
|
||||
|
||||
/**
|
||||
* Compile a select query into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileSelect(Builder $query)
|
||||
{
|
||||
if (! $query->offset) {
|
||||
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 = ['*'];
|
||||
}
|
||||
|
||||
return $this->compileAnsiOffset(
|
||||
$query, $this->compileComponents($query)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "select *" portion of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $columns
|
||||
* @return string|null
|
||||
*/
|
||||
protected function compileColumns(Builder $query, $columns)
|
||||
{
|
||||
if (! is_null($query->aggregate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$select = $query->distinct ? 'select distinct ' : 'select ';
|
||||
|
||||
// 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.' ';
|
||||
}
|
||||
|
||||
return $select.$this->columnize($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "from" portion of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
protected function compileFrom(Builder $query, $table)
|
||||
{
|
||||
$from = parent::compileFrom($query, $table);
|
||||
|
||||
if (is_string($query->lock)) {
|
||||
return $from.' '.$query->lock;
|
||||
}
|
||||
|
||||
if (! is_null($query->lock)) {
|
||||
return $from.' with(rowlock,'.($query->lock ? 'updlock,' : '').'holdlock)';
|
||||
}
|
||||
|
||||
return $from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a "where date" clause.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $where
|
||||
* @return string
|
||||
*/
|
||||
protected function whereDate(Builder $query, $where)
|
||||
{
|
||||
$value = $this->parameter($where['value']);
|
||||
|
||||
return 'cast('.$this->wrap($where['column']).' as date) '.$where['operator'].' '.$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a full ANSI offset clause for the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $components
|
||||
* @return string
|
||||
*/
|
||||
protected function compileAnsiOffset(Builder $query, $components)
|
||||
{
|
||||
// An ORDER BY clause is required to make this offset query work, so if one does
|
||||
// not exist we'll just create a dummy clause to trick the database and so it
|
||||
// does not complain about the queries for not having an "order by" clause.
|
||||
if (empty($components['orders'])) {
|
||||
$components['orders'] = 'order by (select 0)';
|
||||
}
|
||||
|
||||
// We need to add the row number to the query so we can compare it to the offset
|
||||
// and limit values given for the statements. So we will add an expression to
|
||||
// the "select" that will give back the row numbers on each of the records.
|
||||
$components['columns'] .= $this->compileOver($components['orders']);
|
||||
|
||||
unset($components['orders']);
|
||||
|
||||
// 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.
|
||||
$sql = $this->concatenate($components);
|
||||
|
||||
return $this->compileTableExpression($sql, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the over statement for a table expression.
|
||||
*
|
||||
* @param string $orderings
|
||||
* @return string
|
||||
*/
|
||||
protected function compileOver($orderings)
|
||||
{
|
||||
return ", row_number() over ({$orderings}) as row_num";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a common table expression for a query.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected function compileTableExpression($sql, $query)
|
||||
{
|
||||
$constraint = $this->compileRowConstraint($query);
|
||||
|
||||
return "select * from ({$sql}) as temp_table where row_num {$constraint}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the limit / offset row constraint for a query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
protected function compileRowConstraint($query)
|
||||
{
|
||||
$start = $query->offset + 1;
|
||||
|
||||
if ($query->limit > 0) {
|
||||
$finish = $query->offset + $query->limit;
|
||||
|
||||
return "between {$start} and {$finish}";
|
||||
}
|
||||
|
||||
return ">= {$start}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the random statement into SQL.
|
||||
*
|
||||
* @param string $seed
|
||||
* @return string
|
||||
*/
|
||||
public function compileRandom($seed)
|
||||
{
|
||||
return 'NEWID()';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "limit" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param int $limit
|
||||
* @return string
|
||||
*/
|
||||
protected function compileLimit(Builder $query, $limit)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the "offset" portions of the query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param int $offset
|
||||
* @return string
|
||||
*/
|
||||
protected function compileOffset(Builder $query, $offset)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the lock into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param bool|string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function compileLock(Builder $query, $value)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an exists statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileExists(Builder $query)
|
||||
{
|
||||
$existsQuery = clone $query;
|
||||
|
||||
$existsQuery->columns = [];
|
||||
|
||||
return $this->compileSelect($existsQuery->selectRaw('1 [exists]')->limit(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return string
|
||||
*/
|
||||
public function compileDelete(Builder $query)
|
||||
{
|
||||
$table = $this->wrapTable($query->from);
|
||||
|
||||
$where = is_array($query->wheres) ? $this->compileWheres($query) : '';
|
||||
|
||||
return isset($query->joins)
|
||||
? $this->compileDeleteWithJoins($query, $table, $where)
|
||||
: trim("delete from {$table} {$where}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a delete statement with joins into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $table
|
||||
* @param string $where
|
||||
* @return string
|
||||
*/
|
||||
protected function compileDeleteWithJoins(Builder $query, $table, $where)
|
||||
{
|
||||
$joins = ' '.$this->compileJoins($query, $query->joins);
|
||||
|
||||
$alias = strpos(strtolower($table), ' as ') !== false
|
||||
? explode(' as ', $table)[1] : $table;
|
||||
|
||||
return trim("delete {$alias} from {$table}{$joins} {$where}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a truncate table statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @return array
|
||||
*/
|
||||
public function compileTruncate(Builder $query)
|
||||
{
|
||||
return ['truncate table '.$this->wrapTable($query->from) => []];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile an update statement into SQL.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $values
|
||||
* @return string
|
||||
*/
|
||||
public function compileUpdate(Builder $query, $values)
|
||||
{
|
||||
list($table, $alias) = $this->parseUpdateTable($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 = collect($values)->map(function ($value, $key) {
|
||||
return $this->wrap($key).' = '.$this->parameter($value);
|
||||
})->implode(', ');
|
||||
|
||||
// If the query has any "join" clauses, we will setup the joins on the builder
|
||||
// and compile them so we can attach them to this update, as update queries
|
||||
// can get join statements to attach to other tables when they're needed.
|
||||
$joins = '';
|
||||
|
||||
if (isset($query->joins)) {
|
||||
$joins = ' '.$this->compileJoins($query, $query->joins);
|
||||
}
|
||||
|
||||
// Of course, update queries may also be constrained by where clauses so we'll
|
||||
// need to compile the where clauses and attach it to the query so only the
|
||||
// intended records are updated by the SQL statements we generate to run.
|
||||
$where = $this->compileWheres($query);
|
||||
|
||||
if (! empty($joins)) {
|
||||
return trim("update {$alias} set {$columns} from {$table}{$joins} {$where}");
|
||||
}
|
||||
|
||||
return trim("update {$table}{$joins} set $columns $where");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table and alias for the given table.
|
||||
*
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
protected function parseUpdateTable($table)
|
||||
{
|
||||
$table = $alias = $this->wrapTable($table);
|
||||
|
||||
if (strpos(strtolower($table), '] as [') !== false) {
|
||||
$alias = '['.explode('] as [', $table)[1];
|
||||
}
|
||||
|
||||
return [$table, $alias];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the bindings for an update statement.
|
||||
*
|
||||
* @param array $bindings
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function prepareBindingsForUpdate(array $bindings, array $values)
|
||||
{
|
||||
// Update statements with joins in SQL Servers utilize an unique syntax. We need to
|
||||
// take all of the bindings and put them on the end of this array since they are
|
||||
// added to the end of the "where" clause statements as typical where clauses.
|
||||
$bindingsWithoutJoin = Arr::except($bindings, 'join');
|
||||
|
||||
return array_values(
|
||||
array_merge($values, $bindings['join'], Arr::flatten($bindingsWithoutJoin))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the grammar supports savepoints.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function supportsSavepoints()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL statement to define a savepoint.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function compileSavepoint($name)
|
||||
{
|
||||
return 'SAVE TRANSACTION '.$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL statement to execute a savepoint rollback.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function compileSavepointRollBack($name)
|
||||
{
|
||||
return 'ROLLBACK TRANSACTION '.$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the format for database stored dates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat()
|
||||
{
|
||||
return 'Y-m-d H:i:s.000';
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a single string in keyword identifiers.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapValue($value)
|
||||
{
|
||||
return $value === '*' ? $value : '['.str_replace(']', ']]', $value).']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a table in keyword identifiers.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Expression|string $table
|
||||
* @return string
|
||||
*/
|
||||
public function wrapTable($table)
|
||||
{
|
||||
return $this->wrapTableValuedFunction(parent::wrapTable($table));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a table in keyword identifiers.
|
||||
*
|
||||
* @param string $table
|
||||
* @return string
|
||||
*/
|
||||
protected function wrapTableValuedFunction($table)
|
||||
{
|
||||
if (preg_match('/^(.+?)(\(.*?\))]$/', $table, $matches) === 1) {
|
||||
$table = $matches[1].']'.$matches[2];
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
100
vendor/laravel/framework/src/Illuminate/Database/Query/JoinClause.php
vendored
Executable file
100
vendor/laravel/framework/src/Illuminate/Database/Query/JoinClause.php
vendored
Executable file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query;
|
||||
|
||||
use Closure;
|
||||
|
||||
class JoinClause extends Builder
|
||||
{
|
||||
/**
|
||||
* The type of join being performed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* The table the join clause is joining to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $table;
|
||||
|
||||
/**
|
||||
* The parent query builder instance.
|
||||
*
|
||||
* @var \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
private $parentQuery;
|
||||
|
||||
/**
|
||||
* Create a new join clause instance.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $parentQuery
|
||||
* @param string $type
|
||||
* @param string $table
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Builder $parentQuery, $type, $table)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->table = $table;
|
||||
$this->parentQuery = $parentQuery;
|
||||
|
||||
parent::__construct(
|
||||
$parentQuery->getConnection(), $parentQuery->getGrammar(), $parentQuery->getProcessor()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an "on" clause to the join.
|
||||
*
|
||||
* On clauses can be chained, e.g.
|
||||
*
|
||||
* $join->on('contacts.user_id', '=', 'users.id')
|
||||
* ->on('contacts.info_id', '=', 'info.id')
|
||||
*
|
||||
* will produce the following SQL:
|
||||
*
|
||||
* on `contacts`.`user_id` = `users`.`id` and `contacts`.`info_id` = `info`.`id`
|
||||
*
|
||||
* @param \Closure|string $first
|
||||
* @param string|null $operator
|
||||
* @param string|null $second
|
||||
* @param string $boolean
|
||||
* @return $this
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function on($first, $operator = null, $second = null, $boolean = 'and')
|
||||
{
|
||||
if ($first instanceof Closure) {
|
||||
return $this->whereNested($first, $boolean);
|
||||
}
|
||||
|
||||
return $this->whereColumn($first, $operator, $second, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an "or on" clause to the join.
|
||||
*
|
||||
* @param \Closure|string $first
|
||||
* @param string|null $operator
|
||||
* @param string|null $second
|
||||
* @return \Illuminate\Database\Query\JoinClause
|
||||
*/
|
||||
public function orOn($first, $operator = null, $second = null)
|
||||
{
|
||||
return $this->on($first, $operator, $second, 'or');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new instance of the join clause builder.
|
||||
*
|
||||
* @return \Illuminate\Database\Query\JoinClause
|
||||
*/
|
||||
public function newQuery()
|
||||
{
|
||||
return new static($this->parentQuery, $this->type, $this->table);
|
||||
}
|
||||
}
|
||||
70
vendor/laravel/framework/src/Illuminate/Database/Query/JsonExpression.php
vendored
Normal file
70
vendor/laravel/framework/src/Illuminate/Database/Query/JsonExpression.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
class JsonExpression extends Expression
|
||||
{
|
||||
/**
|
||||
* The value of the expression.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* Create a new raw query expression.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $this->getJsonBindingParameter($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the given value into the appropriate JSON binding parameter.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function getJsonBindingParameter($value)
|
||||
{
|
||||
switch ($type = gettype($value)) {
|
||||
case 'boolean':
|
||||
return $value ? 'true' : 'false';
|
||||
case 'integer':
|
||||
case 'double':
|
||||
return $value;
|
||||
case 'string':
|
||||
return '?';
|
||||
case 'object':
|
||||
case 'array':
|
||||
return '?';
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('JSON value is of illegal type: '.$type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the expression.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the expression.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->getValue();
|
||||
}
|
||||
}
|
||||
19
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/MySqlProcessor.php
vendored
Normal file
19
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/MySqlProcessor.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Processors;
|
||||
|
||||
class MySqlProcessor extends Processor
|
||||
{
|
||||
/**
|
||||
* Process the results of a column listing query.
|
||||
*
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
public function processColumnListing($results)
|
||||
{
|
||||
return array_map(function ($result) {
|
||||
return with((object) $result)->column_name;
|
||||
}, $results);
|
||||
}
|
||||
}
|
||||
41
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/PostgresProcessor.php
vendored
Executable file
41
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/PostgresProcessor.php
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Processors;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class PostgresProcessor extends Processor
|
||||
{
|
||||
/**
|
||||
* Process an "insert get ID" query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $sql
|
||||
* @param array $values
|
||||
* @param string $sequence
|
||||
* @return int
|
||||
*/
|
||||
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
|
||||
{
|
||||
$result = $query->getConnection()->selectFromWriteConnection($sql, $values)[0];
|
||||
|
||||
$sequence = $sequence ?: 'id';
|
||||
|
||||
$id = is_object($result) ? $result->{$sequence} : $result[$sequence];
|
||||
|
||||
return is_numeric($id) ? (int) $id : $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the results of a column listing query.
|
||||
*
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
public function processColumnListing($results)
|
||||
{
|
||||
return array_map(function ($result) {
|
||||
return with((object) $result)->column_name;
|
||||
}, $results);
|
||||
}
|
||||
}
|
||||
49
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php
vendored
Executable file
49
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php
vendored
Executable file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Processors;
|
||||
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class Processor
|
||||
{
|
||||
/**
|
||||
* Process the results of a "select" query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
public function processSelect(Builder $query, $results)
|
||||
{
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an "insert get ID" query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $sql
|
||||
* @param array $values
|
||||
* @param string $sequence
|
||||
* @return int
|
||||
*/
|
||||
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
|
||||
{
|
||||
$query->getConnection()->insert($sql, $values);
|
||||
|
||||
$id = $query->getConnection()->getPdo()->lastInsertId($sequence);
|
||||
|
||||
return is_numeric($id) ? (int) $id : $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the results of a column listing query.
|
||||
*
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
public function processColumnListing($results)
|
||||
{
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
19
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/SQLiteProcessor.php
vendored
Normal file
19
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/SQLiteProcessor.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Processors;
|
||||
|
||||
class SQLiteProcessor extends Processor
|
||||
{
|
||||
/**
|
||||
* Process the results of a column listing query.
|
||||
*
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
public function processColumnListing($results)
|
||||
{
|
||||
return array_map(function ($result) {
|
||||
return with((object) $result)->name;
|
||||
}, $results);
|
||||
}
|
||||
}
|
||||
69
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/SqlServerProcessor.php
vendored
Executable file
69
vendor/laravel/framework/src/Illuminate/Database/Query/Processors/SqlServerProcessor.php
vendored
Executable file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database\Query\Processors;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class SqlServerProcessor extends Processor
|
||||
{
|
||||
/**
|
||||
* Process an "insert get ID" query.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query
|
||||
* @param string $sql
|
||||
* @param array $values
|
||||
* @param string $sequence
|
||||
* @return int
|
||||
*/
|
||||
public function processInsertGetId(Builder $query, $sql, $values, $sequence = null)
|
||||
{
|
||||
$connection = $query->getConnection();
|
||||
|
||||
$connection->insert($sql, $values);
|
||||
|
||||
if ($connection->getConfig('odbc') === true) {
|
||||
$id = $this->processInsertGetIdForOdbc($connection);
|
||||
} else {
|
||||
$id = $connection->getPdo()->lastInsertId();
|
||||
}
|
||||
|
||||
return is_numeric($id) ? (int) $id : $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an "insert get ID" query for ODBC.
|
||||
*
|
||||
* @param \Illuminate\Database\Connection $connection
|
||||
* @return int
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function processInsertGetIdForOdbc(Connection $connection)
|
||||
{
|
||||
$result = $connection->selectFromWriteConnection(
|
||||
'SELECT CAST(COALESCE(SCOPE_IDENTITY(), @@IDENTITY) AS int) AS insertid'
|
||||
);
|
||||
|
||||
if (! $result) {
|
||||
throw new Exception('Unable to retrieve lastInsertID for ODBC.');
|
||||
}
|
||||
|
||||
$row = $result[0];
|
||||
|
||||
return is_object($row) ? $row->insertid : $row['insertid'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the results of a column listing query.
|
||||
*
|
||||
* @param array $results
|
||||
* @return array
|
||||
*/
|
||||
public function processColumnListing($results)
|
||||
{
|
||||
return array_map(function ($result) {
|
||||
return with((object) $result)->name;
|
||||
}, $results);
|
||||
}
|
||||
}
|
||||
78
vendor/laravel/framework/src/Illuminate/Database/QueryException.php
vendored
Normal file
78
vendor/laravel/framework/src/Illuminate/Database/QueryException.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Database;
|
||||
|
||||
use PDOException;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class QueryException extends PDOException
|
||||
{
|
||||
/**
|
||||
* The SQL for the query.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sql;
|
||||
|
||||
/**
|
||||
* The bindings for the query.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bindings;
|
||||
|
||||
/**
|
||||
* Create a new query exception instance.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $bindings
|
||||
* @param \Exception $previous
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sql, array $bindings, $previous)
|
||||
{
|
||||
parent::__construct('', 0, $previous);
|
||||
|
||||
$this->sql = $sql;
|
||||
$this->bindings = $bindings;
|
||||
$this->code = $previous->getCode();
|
||||
$this->message = $this->formatMessage($sql, $bindings, $previous);
|
||||
|
||||
if ($previous instanceof PDOException) {
|
||||
$this->errorInfo = $previous->errorInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the SQL error message.
|
||||
*
|
||||
* @param string $sql
|
||||
* @param array $bindings
|
||||
* @param \Exception $previous
|
||||
* @return string
|
||||
*/
|
||||
protected function formatMessage($sql, $bindings, $previous)
|
||||
{
|
||||
return $previous->getMessage().' (SQL: '.Str::replaceArray('?', $bindings, $sql).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL for the query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSql()
|
||||
{
|
||||
return $this->sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bindings for the query.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getBindings()
|
||||
{
|
||||
return $this->bindings;
|
||||
}
|
||||
}
|
||||
69
vendor/laravel/framework/src/Illuminate/Database/README.md
vendored
Executable file
69
vendor/laravel/framework/src/Illuminate/Database/README.md
vendored
Executable file
@@ -0,0 +1,69 @@
|
||||
## Illuminate Database
|
||||
|
||||
The Illuminate Database component is a full database toolkit for PHP, providing an expressive query builder, ActiveRecord style ORM, and schema builder. It currently supports MySQL, Postgres, SQL Server, and SQLite. It also serves as the database layer of the Laravel PHP framework.
|
||||
|
||||
### Usage Instructions
|
||||
|
||||
First, create a new "Capsule" manager instance. Capsule aims to make configuring the library for usage outside of the Laravel framework as easy as possible.
|
||||
|
||||
```PHP
|
||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
|
||||
$capsule = new Capsule;
|
||||
|
||||
$capsule->addConnection([
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => 'database',
|
||||
'username' => 'root',
|
||||
'password' => 'password',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
]);
|
||||
|
||||
// Set the event dispatcher used by Eloquent models... (optional)
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Container\Container;
|
||||
$capsule->setEventDispatcher(new Dispatcher(new Container));
|
||||
|
||||
// Make this Capsule instance available globally via static methods... (optional)
|
||||
$capsule->setAsGlobal();
|
||||
|
||||
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
|
||||
$capsule->bootEloquent();
|
||||
```
|
||||
|
||||
> `composer require "illuminate/events"` required when you need to use observers with Eloquent.
|
||||
|
||||
Once the Capsule instance has been registered. You may use it like so:
|
||||
|
||||
**Using The Query Builder**
|
||||
|
||||
```PHP
|
||||
$users = Capsule::table('users')->where('votes', '>', 100)->get();
|
||||
```
|
||||
Other core methods may be accessed directly from the Capsule in the same manner as from the DB facade:
|
||||
```PHP
|
||||
$results = Capsule::select('select * from users where id = ?', array(1));
|
||||
```
|
||||
|
||||
**Using The Schema Builder**
|
||||
|
||||
```PHP
|
||||
Capsule::schema()->create('users', function ($table) {
|
||||
$table->increments('id');
|
||||
$table->string('email')->unique();
|
||||
$table->timestamps();
|
||||
});
|
||||
```
|
||||
|
||||
**Using The Eloquent ORM**
|
||||
|
||||
```PHP
|
||||
class User extends Illuminate\Database\Eloquent\Model {}
|
||||
|
||||
$users = User::where('votes', '>', 1)->get();
|
||||
```
|
||||
|
||||
For further documentation on using the various database facilities this library provides, consult the [Laravel framework documentation](https://laravel.com/docs).
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user