Laravel/Eloquent:致命错误:在非对象上调用成员函数 connection()

2021-12-26 00:00:00 package php laravel composer-php eloquent

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

I'm building a package in Laravel 4 but am getting a non-object error when attempting to access the db from which seems to be a properly instantiated object. Here's the setup:

有问题的配置和类:

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 VendorChat;

use IlluminateDatabaseEloquentModel 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

我相信我遗漏了一些基本的东西.感谢您的任何帮助!

I believe I'm missing something fundamental and under my nose. Thanks for any and all help!

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

Here is the class that's instantiating ChatHistory and calling the write:

namespace VendorChat;

use RatchetMessageComponentInterface;
use RatchetConnectionInterface;

use VendorChatClient;
use VendorChatMessage;
use VendorChatChatHistory;

use IlluminateDatabaseModel;

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 没有被加载到顶部?

The fact that DB isn't available suggest that Eloquent isn't being loaded up top?

推荐答案

答案:

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

Bootstrap your package in your service provider's boot method.

说明:

既然你正在开发一个与 Laravel 一起使用的包,那么制作你自己的 Capsule 实例是没有意义的.你可以直接使用 Eloquent.

Since you're developing a package to be used with Laravel, there's no point in making your own Capsule instance. You can just use Eloquent directly.

您的问题似乎源于 DB/Eloquent 在您的代码命中时尚未设置.

Your problem seems to stem from DB/Eloquent not being set up yet by the time your code hits it.

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

You have not shown us your service provider, but I'm guessing you're using one and doing it all in the register method.

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

Since your package depends on a different service provider (DatabaseServiceProvider) to be wired up prior to its own execution, the correct place to bootstrap your package is in your service provider's boot method.

这里引用了 文档:

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

The register method is called immediately when the service provider is registered, while the boot command is only called right before a request is routed.

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

So, if actions in your service provider rely on another service provider already being registered [...] you should use the boot method.

相关文章