2017-07-06 48 views
2

我目前正在用php-activerecord替换自制的hack-y MVC方法的模型组件。我有一个单独的页面,显示数据库服务器关闭的情况,该页面用于显示具有访客头像,名称和角色的用户徽章。代码如下:在没有数据库连接的情况下实例化ActiveRecord模型

if (Auth::$signed_in) 
    echo Auth::$user->getAvatarWrap(); 
else echo (new \App\Models\User([ 
    'name' => 'Guest', 
    'role' => 'guest', 
    'avatar_url' => GUEST_AVATAR 
]))->getAvatarWrap(); 

Auth::$signed_in设为true当用户已登录,其中 - 在DB中断的情况下 - 是不可能的,所以else分支与所述预定义的数据执行。

Pre-ActiveRecord这将简单地将属性添加到对象,并且调用getAvatarWrap方法将执行没有任何问题。现在,模型由ActiveRecord控制,无论出于何种原因,都会发生一系列额外的调用。这可能是因为该模型已定义关系,但我不确定。

ActiveRecord\DatabaseException: PDOException: SQLSTATE[08006] [7] could not connect to server: Connection refused 
    Is the server running on host "localhost" (127.0.0.1) and accepting 
    TCP/IP connections on port 5432? in /var/www/vendor/php-activerecord/php-activerecord/lib/Connection.php:260 
Stack trace: 
#0 /var/www/vendor/php-activerecord/php-activerecord/lib/Connection.php(260): PDO->__construct('pgsql:host=loca...', '<username>', '<password>', Array) 
#1 /var/www/vendor/php-activerecord/php-activerecord/lib/Connection.php(122): ActiveRecord\Connection->__construct(Object(stdClass)) 
#2 /var/www/vendor/php-activerecord/php-activerecord/lib/ConnectionManager.php(33): ActiveRecord\Connection::instance('pgsql://databas...') 
#3 /var/www/vendor/php-activerecord/php-activerecord/lib/Table.php(114): ActiveRecord\ConnectionManager::get_connection('pgsql') 
#4 /var/www/vendor/php-activerecord/php-activerecord/lib/Table.php(90): ActiveRecord\Table->reestablish_connection(false) 
#5 /var/www/vendor/php-activerecord/php-activerecord/lib/Table.php(71): ActiveRecord\Table->__construct('App\\Models\\User') 
#6 /var/www/vendor/php-activerecord/php-activerecord/lib/Model.php(765): ActiveRecord\Table::load('App\\Models\\User') 
#7 /var/www/vendor/php-activerecord/php-activerecord/lib/Model.php(271): ActiveRecord\Model::table() 
#8 /var/www/includes/views/_sidebar.php(20): ActiveRecord\Model->__construct(Array) 
#9 /var/www/includes/views/_layout.php(148): include('/var/www...') 
#10 /var/www/includes/views/fatalerr.php(46): require('/var/www...') 
#11 /var/www/includes/init.php(32): require('/var/www...') 
#12 /var/www/includes/do.php(3): require('/var/www...') 
#13 /var/www/public/index.php(1): require('/var/www...') 
#14 {main} in /var/www/vendor/php-activerecord/php-activerecord/lib/Connection.php on line 262 

我如何告诉ActiveRecord的停止寻找连接时,我知道一个事实,即它不会找到一个,那它应该是内容与我喂养它的数据?在停电期间,我是否必须挥手告别使用我的任何模型?

+0

你可以修改配置以使用sqlite:memory连接吗? – colburton

+0

我完全控制了代码和运行的服务器。 – SeinopSys

+0

然后这可能是一个解决方案。每个查询都会失败,但是无论如何都会发生。 – colburton

回答

0

感谢a comment我发现了SQLite内存数据库,这让我走上了成功的道路。鉴于支持这种数据库的pull request已经收集了近一年的尘埃,我决定将事情交由我亲手处理。
如果您稍后阅读此内容,请务必检查该PR是否已合并,并留下评论,以便我可以更新此答案。

首先,我分叉了GitHub上的original repository存储库。我故意没有链接我的分支,因为它最终可能会过期或被删除,所以我建议你为自己做一个分支。然后,我使用了this answerthis answer的组合,从PR的提交者的分支中获取魔术分支到我的分支中。您可以通过按分叉存储库主页上的“克隆或下载”按钮来获得<url>

$ git clone <url> 
$ git remote add target https://github.com/claytonrcarter/php-activerecord.git 
$ git fetch --all 
$ git checkout master 
$ git merge --squash target/sqlite-memory-support 
$ git commit -m "Add support for SQLite :memory: databases" 
$ git push 

现在,我的叉子有我把我的项目composer.json的最新变化,在我require块改变php-activerecord/php-activerecord的版本"dev-master",然后添加一个repositories块与我在它的叉子。再次使用fork的克隆URL替换<url>

{ 
    // ... 
    "require": { 
     // ... 
     "php-activerecord/php-activerecord": "dev-master", 
     // ... 
    }, 
    "repositories": [ 
     { 
      "type": "vcs", 
      "url": "<url>" 
     } 
    ] 
} 

别急,乐趣还没有结束!既然我们支持内存SQLite数据库适配器,我们实际上必须定义它。因此,修改你的初始配置:

ActiveRecord\Config::initialize(function ($cfg){ 
    $cfg->set_connections([ 
     'pgsql' => 'pgsql://'.DB_USER.':'.DB_PASS.'@'.DB_HOST.'/database?charset=utf8', 

     // Add this line below. 'failsafe' can be changed to something else, of course 
     'failsafe' => 'sqlite://:memory:', 
    ], 'pgsql'); 
}); 

原来这是prettydifficult热插拔默认连接,所以我做了一个最好的事情,并取得了子类是有其$connection设置为前面定义的failsafe。请注意,所需的字段必须手动定义,因为lib无法知道允许您从空数据库使用哪些字段。有趣的是,主类中的$has_many和类似关系对子类的行为没有负面影响,所以我可以保持它相对较短。

namespace App\Models; 

/** @inheritdoc */ 
class FailsafeUser extends User { 
    static $connection = 'failsafe'; 

    public $name, $role, $avatar_url; 
} 

最后,我不得不改变呼叫使用新定义的类:

if (Auth::$signed_in) 
    echo Auth::$user->getAvatarWrap(); 
else echo (new \App\Models\FailsafeUser([ 
    'name' => 'Guest', 
    'role' => 'guest', 
    'avatar_url' => GUEST_AVATAR 
]))->getAvatarWrap(); 

低不料,脚本不再休息,我终于可以得到与ActiveRecord的-ification我的代码库。如果你想自己去经历这种折磨,并有多个模型,你想有一个“离线”变体,那么你可能想要创建一个抽象类来自动设置你在构造函数中传递的属性并预先设置了$connection,使得子实例稍显冗长。

相关问题