您的位置 首页 php

Laravel的数据库操作

Laravel作为PHP的一款开发框架,在开发者中有大量的粉丝。

Laravel提供了强大的功能及灵活的组件供开发者使用,今天来看下数据库操作在laravel中是如何实现的。

配置

数据库相关的配置文件在config/database.php中,connections数组可以配置自己需要的数据源,这里可以灵活选择

 <?php

// 默认数据库配置
DB::table('user')
    ->where(['id' => 1])
    ->get();

// 选择其他数据库配置
DB::connection('mysql1')
    ->table('people')
    ->where(['id' => 2])
    ->get();  

查询构造器

重要的类:laravel/framework/src/Illuminate/Database/Query/Builder.php

laravel的数据库操作很多是通过它来完成的,这里面封装了对数据库查询的各种操作。

当我们调用各种方法之后,总要通过get() 或者 first() 或者 find()等方法获取结果,这里以get为例,

 /**
     * Execute the query as a "select" statement.
     *
     * @param  array|string  $columns
     * @return \Illuminate\Support\Collection
     */
    public function get($columns = ['*'])
    {
        return collect($this->onceWithColumns(Arr::wrap($columns), function () {
            return $this->processor->processSelect($this, $this->runSelect());
        }));
    }

/**
     * Run the query as a "select" statement against the connection.
     *
     * @return array
     */
    protected function runSelect()
    {
        return $this->connection->select(
            $this->toSql(), $this->getBindings(), ! $this->useWritePdo
        );
    }

  

通过调用connection->select后获取执行结果

重要类:Illuminate/Database/Connection.php

 /**
     * Run a select statement against the database.
     *
     * @param  string  $query
     * @param  array  $bindings
     * @param  bool  $useReadPdo
     * @return array
     */
    public function select($query, $bindings = [], $useReadPdo = true)
    {
        return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {
            if ($this->pretending()) {
                return [];
            }

            // For select statements, we'll simply execute the query and return an array
            // of the database result set. Each element in the array will be a single
            // row from the database table, and will either be an array or objects.
            $statement = $this->prepared(
                $this->getPdoForSelect($useReadPdo)->prepare($query)
            );

            $this->bindValues($statement, $this->prepareBindings($bindings));

            $statement->execute();

            return $statement->fetchAll();
        });
    }  

猛一看,其实还是pdo的操作。

Eloquent Orm

如果你对查询构造器不满意,还可以通过Orm的方式进行数据操作,Laravel中我们可以通过Model的形式进行。

重要类:

Model基类:src/Illuminate/Database/Eloquent/Model.php

src/Illuminate/Database/Eloquent/Builder.php

Eloquent/Builder中的$query实际上还是查询构造器:Database/Query/Builder.php

Model中通过__call及__callStatic的代理去执行各种方法:

 /**
 * Dynamically handle calls into the query instance.
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public function __call($method, $parameters)
{
    if ($method === 'macro') {
        $this->localMacros[$parameters[0]] = $parameters[1];

        return;
    }

    if ($this->hasMacro($method)) {
        array_unshift($parameters, $this);

        return $this->localMacros[$method](...$parameters);
    }

    if (static::hasGlobalMacro($method)) {
        $callable = static::$macros[$method];

        if ($callable instanceof Closure) {
            $callable = $callable->bindTo($this, static::class);
        }

        return $callable(...$parameters);
    }

    if ($this->hasNamedScope($method)) {
        return $this->callNamedScope($method, $parameters);
    }

    if (in_array($method, $this->passthru)) {
        return $this->toBase()->{$method}(...$parameters);
    }

    $this->forwardCallTo($this->query, $method, $parameters);

    return $this;
}  
 <?php
/**
     * Dynamically handle calls into the query instance.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public static function __callStatic($method, $parameters)
    {
        if ($method === 'macro') {
            static::$macros[$parameters[0]] = $parameters[1];

            return;
        }

        if ($method === 'mixin') {
            return static::registerMixin($parameters[0], $parameters[1] ?? true);
        }

        if (! static::hasGlobalMacro($method)) {
            static::throwBadMethodCallException($method);
        }

        $callable = static::$macros[$method];

        if ($callable instanceof Closure) {
            $callable = $callable->bindTo(null, static::class);
        }

        return $callable(...$parameters);
    }  

 /**
 * Dynamically handle calls into the query instance.
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public function __call($method, $parameters)
{
    if ($method === 'macro') {
        $this->localMacros[$parameters[0]] = $parameters[1];

        return;
    }

    if ($this->hasMacro($method)) {
        array_unshift($parameters, $this);

        return $this->localMacros[$method](...$parameters);
    }

    if (static::hasGlobalMacro($method)) {
        $callable = static::$macros[$method];

        if ($callable instanceof Closure) {
            $callable = $callable->bindTo($this, static::class);
        }

        return $callable(...$parameters);
    }

    if ($this->hasNamedScope($method)) {
        return $this->callNamedScope($method, $parameters);
    }

    if (in_array($method, $this->passthru)) {
        return $this->toBase()->{$method}(...$parameters);
    }

    $this->forwardCallTo($this->query, $method, $parameters);

    return $this;
}  

所以EloquentOrm的多数方法还是通过$this->query去执行也就是,QueryBuilder

DB Facade

我们一般通过DB::table(‘xxx’)就可以去执行数据库操作,那这是如何实现的呢, 这要通过DBFacade及DatabaseServiceProvider去看

重要类:

src/Illuminate/Database/DatabaseServiceProvider.php

src/Illuminate/Support/Facades/DB.php

 <?php

class DB extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'db';
    }
}


class DatabaseServiceProvider extends ServiceProvider
{
/**
     * 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();
        });

        $this->app->singleton('db.transactions', function ($app) {
            return new DatabaseTransactionsManager;
        });
    }
  
  
}  

框架启动的时候会通过DatabaserServiceProvider->register自动完成db的绑定,db是啥,其实就是DatabaseManager对象, DatabaseManager还是通过__call代理去调用Connection的方法

 /**
 * @mixin \Illuminate\Database\Connection
 */
class DatabaseManager implements ConnectionResolverInterface
{
		/**
     * 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);
    }
  
}    

总结一下:

使用手册:

文章来源:智云一二三科技

文章标题:Laravel的数据库操作

文章地址:https://www.zhihuclub.com/152915.shtml

关于作者: 智云科技

热门文章

网站地图