【问题标题】:Laravel/Eloquent: Fatal error: Call to a member function connection() on a non-objectLaravel/Eloquent:致命错误:在非对象上调用成员函数 connection()
【发布时间】:2014-12-28 03:07:39
【问题描述】:

我正在 Laravel 4 中构建一个包,但在尝试访问似乎是正确实例化对象的 db 时出现非对象错误。这是设置:

有问题的配置和类:

composer.json:

...
"autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ],
        "psr-0": {
            "Vendor\\Chat": "src/vendor/chat/src"
        }  
    }
...

班级:

namespace Vendor\Chat;

use Illuminate\Database\Eloquent\Model as Eloquent;


class ChatHistory extends Eloquent
{
    protected $table = 'chat_history';

    protected $fillable = array('message', 'user_id', 'room_token');

    public function __construct($attributes = array())
    {
        parent::__construct($attributes);
    }

}

来电:

$message = new Message($msg);

$history = new ChatHistory;
$history->create(array(
                 'room_token' => $message->getRoomToken(),
                 'user_id' => $message->getUserId(),
                 'message' => $message->getMessage(),
              ));

错误:

PHP Fatal error:  Call to a member function connection() on a non-object in /home/vagrant/project/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 2894

我相信我在我的眼皮子底下漏掉了一些基本的东西。感谢您的所有帮助!

编辑:

这是实例化 ChatHistory 并调用 write 的类:

namespace Vendor\Chat;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

use Vendor\Chat\Client;
use Vendor\Chat\Message;
use Vendor\Chat\ChatHistory;

use Illuminate\Database\Model;

class Chat implements MessageComponentInterface {

    protected $app;

    protected $clients;

    public function __construct() 
    {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen(ConnectionInterface $conn) 
    {
        $client = new Client;
        $client->setId($conn->resourceId);
        $client->setSocket($conn);

        $this->clients->attach($client);
    }

    public function onMessage(ConnectionInterface $conn, $msg) 
    {
        $message = new Message($msg);

        $history = new ChatHistory;
        ChatHistory::create(array(
                     'room_token' => $message->getRoomToken(),
                     'user_id' => $message->getUserId(),
                     'message' => $message->getMessage(),
                  ));
        /* error here */
        /* ... */ 
    }

    public function onClose(ConnectionInterface $conn) 
    {
        $this->clients->detach($conn);
    }

    public function onError(ConnectionInterface $conn, \Exception $e) 
    {
        $conn->close();
    }

    protected function getClientByConn(ConnectionInterface $conn)
    {
        foreach($this->clients as $client) {
            if($client->getSocket() === $conn) {
                return $client;
            } 
        } 

        return null;
    }
}

DB 不可用的事实表明 Eloquent 没有被加载到顶部?

【问题讨论】:

  • 您在哪一行收到此错误?是为了历史还是使用$message的方法。我们当然不知道,也不知道Message 是什么
  • 道歉。在 ChatHistory 上调用 create() 时会触发该错误。 Message 是一个表示套接字消息的简单类。
  • 你是否尝试过像laracasts.com/forum/?p=969-codeception-and-laravel/0 中描述的那样启动 Laravel?
  • 你使用的是 Laravel 4.1 还是 4.2?
  • @J.LaRosee 除了create() 用于静态使用这一事实之外,问题可能与$history 对象无关。相反,似乎没有设置连接解析器(Model 的静态属性)。如果您依赖 DatabaseServiceProvider,它可能没有正确启动。

标签: php laravel package eloquent composer-php


【解决方案1】:

@matpop 和 @TonyStark 走在了正确的轨道上:Capsule\Manager 没有被启动。

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;
$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'project',
    'username'  => 'root',
    '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();

我可以在启动后扩展 Eloquent。我认为另一种解决方案可能类似于(但未经测试):

include __DIR__ . '/../../vendor/autoload.php';
$app = require_once __DIR__ . '/../../bootstrap/start.php';
$app->boot();

【讨论】:

  • 您是在开发一个使用 Eloquent 的独立包,还是在构建一个专门用于 Laravel 的包?
  • 这是一个专门针对 Laravel 的包。
  • @matpop 你的建议让我走上了正轨,所以我想给你赏金。鉴于您尚未提供答案,不知道该怎么做。
  • 感谢您的赞赏,它比 SO rep 更有价值,所以不用担心。实际上,在这个阶段,我认为还没有人值得这个赏金,因为看起来你现在解决了 Capsule 的问题,而且我相信这不是 Laravel 特定包的最佳方式。如果一切设置正确,这些包的服务提供者将由底层 Laravel 应用程序“正常”服务提供者已经启动(包括 DatabaseServiceProvider)之后加载,所以你不需要 Capsule 也不需要显式调用$app->boot()(已调用)。
  • 你关注the official guide了吗?抱歉,如果我暂时不在,我的时区在大洋的另一边:)
【解决方案2】:

尝试包括 DB 外观以及 Eloquent...

use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Model as Eloquent;

...然后查看您是否可以访问DB::table('chat_history')

(另请注意,在您的课堂上,您对use Illuminate\Database\Model; 的调用应该是Illuminate\Database\Eloquent\Model;

【讨论】:

    【解决方案3】:

    回答

    在您的服务提供商的boot 方法中引导您的包。


    说明

    由于您正在开发一个与 Laravel 一起使用的包,因此创建自己的 Capsule 实例毫无意义。你可以直接使用Eloquent

    您的问题似乎源于 DB/Eloquent 在您的代码运行时尚未设置。

    您尚未向我们展示您的服务提供商,但我猜您正在使用一个并在 register 方法中完成所有操作。

    由于您的包依赖于不同的服务提供商 (DatabaseServiceProvider) 在其自己的执行之前进行连接,因此引导您的包的正确位置是在您的服务提供商的 boot 方法中。

    这是来自the docs的引述:

    register 方法在服务提供者注册时立即调用,而boot 命令仅在请求被路由之前调用。

    因此,如果您的服务提供者中的操作依赖于另一个已注册的服务提供者 [...],您应该使用 boot 方法。

    【讨论】:

    • 赏金来了!我确实猜想我们只是在文档中遗漏了一些声明……请务必仔细阅读!
    • 使用 Capsule “修复”了问题,但它似乎不是最佳解决方案 (github.com/illuminate/database)。我一直在寻找引导程序包,看起来,尽管 Capsule 解决方案通过向我展示代码不是问题,我加载和使用代码的顺序不正确,帮助我走上了正确的道路.
    【解决方案4】:

    如果您使用 Lumen,您可能会遇到同样的问题。在这种情况下,只需取消注释:

    // $app->withFacades();
    
    // $app->withEloquent();
    

    bootstrap\app.php

    【讨论】:

    • 就是这样 :) 非常感谢。
    【解决方案5】:

    我所做的很简单,我只是忘记在我的 bootstrap/app.php 中取消注释 $app->withFacades(); $app->withEloquent();

    现在可以正常使用

    【讨论】:

    • 这为我解决了这个问题,但这是为 Lumen 准备的。
    【解决方案6】:

    你必须使用

    $capsule->`bootEloquent`();
    

    database.php/你的连接之后。

    这是您的完整代码:

    <?php
    
    use Illuminate\Database\Capsule\Manager as Capsule;
    
    $capsule = new Capsule;
    
    $capsule->`addConnection`([
        'driver' => `'mysql'`,
        'host' => 'localhost',
        'database' => 'test1',
        'username' => 'root',
        'password' => '',
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
    ]);
    
    $capsule->`bootEloquent`();
    

    【讨论】:

      【解决方案7】:
      <?php
      
      namespace App\Providers;
      use App\Setting;
      use Illuminate\Support\ServiceProvider;
      use Illuminate\Support\Facades\Schema;
      
      
      
      class AppServiceProvider extends ServiceProvider
      {
          /**
           * Register any application services.
           *
           * @return void
           */
          public function register()
          {
              Schema::defaultStringLength(191);
      
      
              $settings = Setting::all();
              foreach ($settings as $key => $settings) {
                  if($key === 0) $system_name = $setting->value;
                  elseif($key === 1) $favicon = $setting->value;
                  elseif($key === 2) $front_logo = $setting->value;
                  elseif($key === 3) $admin_logo = $setting->value;
              }
              $shareData = array(
                  'system_name'=>$system_name,
                  'favicon'=>$favicon,
                  'front_logo'=>$front_logo,
                  'admin_logo'=>$admin_logo
              );
              view()->share('shareData',$shareData);
          }
      
          /**
           * Bootstrap any application services.
           *
           * @return void
           */
          public function boot()
          {
              //
          }
      }
      

      【讨论】:

      • A code-only answer is not high quality。虽然此代码可能很有用,但您可以通过说明其工作原理、工作方式、何时应该使用以及它的局限性来改进它。请edit您的回答包括解释和相关文档的链接。
      猜你喜欢
      • 2015-09-15
      • 1970-01-01
      • 2013-11-25
      • 2012-05-30
      • 2016-08-30
      • 2015-02-06
      • 2012-05-14
      • 2013-11-19
      • 2017-04-30
      相关资源
      最近更新 更多