获取数据库实例的正确语法是什么?

What is the proper syntax to get a db instance?

我在laravel之外使用eloquent。

这是负责它的文件:

class DbSql
{

    public function db()
    {
        $capsule = new Capsule;
        $capsule->addConnection( [
            'driver'    => Settings::DATABASE_DRIVER,
            'host'      => Settings::DATABASE_HOST,
            'database'  => Settings::DATABASE_NAME,
            'username'  => Settings::DATABASE_USERNAME,
            'password'  => Settings::DATABASE_PASSWORD,
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => ''
        ] );

        # Make this Capsule instance available globally
        $capsule->setAsGlobal();


        return $capsule;
    }

}

在控制器中,我实例化了一次实例,并可能在控制器中多次使用它:

    $dbInstance = ( new DbSql() )->db(); // Create the instance

    // Instance usages:
    $images = $dbInstance->table( 'images_attachments' )->where...
    $files = $dbInstance->table( 'files' )->where...
    .....

我应该实例化:

$dbInstance = ( new DbSql() )->db(); 如上面的代码

或与:

$dbInstance = ( new DbSql() )->db()->getConnection();

正确的方法是什么?

首先,没有必要将 Capsule(这是一个 Illuminate\Database\Capsule\Manager 实例)包装在另一个 class 中以便于检索它。事实上,Illuminate\Database\Capsule\Manager 提供了一个单例实例和简单的访问器。

一旦你打电话

$capsule->setAsGlobal();

Capsule 实例可以通过 Capsule:: 从任何地方静态访问。 这是因为 setAsGlobal() 方法在幕后只是简单地执行以下操作:

static::$instance = $this;

将实例保存在静态 class 变量中,以便在后续调用 Capsule:: 时检索它。 因此,一旦调用 setAsGlobal(),就可以执行,例如:

Capsule::select('select * from user');

您将获得对先前创建的连接的查询结果。

但是,您可以看到 Manager(别名 Capsule)class 上不存在 select 方法。 为什么它有效? 因为 Manager class 覆盖 __callStatic() php magic method

class Manager
{
    use CapsuleManagerTrait;

    // ...

    public static function __callStatic($method, $parameters)
    {
        return static::connection()->$method(...$parameters);
    }
}

因此对 select() 方法的调用被重定向到底层 \Illuminate\Database\Connection 实例 自动.

这意味着:

  • 不需要将 Manager/Capsule 包装在外部 class 中,因为它已经是 Connection class 的包装器.无需添加另一个包装器。
  • 但是,如果您更喜欢包装它,我建议您返回 Manager/Capsule 实例而不是底层连接,因为文档中建议的方法是直接使用Manager