Laravel/Eloquent: Неустранимая ошибка: вызов функции функции-члена() на не-объекте

Я создаю пакет в 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

Я считаю, что мне не хватает чего-то фундаментального и под носом. Спасибо за любую помощь!

EDIT:

Вот класс, который создает экземпляр ChatHistory и вызывает запись:

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

Тот факт, что БД недоступен, свидетельствует о том, что Eloquent не загружается вверх?

Ответ 1

Ответ

Загрузите свой пакет в свой сервис-провайдер boot.


Объяснение

Поскольку вы разрабатываете пакет, который будет использоваться с Laravel, нет смысла создавать собственный экземпляр Capsule. Вы можете просто использовать Eloquent напрямую.

Ваша проблема, похоже, связана с тем, что DB/Eloquent еще не настроен к тому времени, когда ваш код попадает на него.

Вы не показали нам своего поставщика услуг, но я предполагаю, что вы используете его и делаете все это в методе register.

Поскольку ваш пакет зависит от другого поставщика услуг (DatabaseServiceProvider), который должен быть подключен до его собственного исполнения, правильное место для загрузки вашего пакета находится в вашем методе поставщика услуг boot.

Вот цитата из документов:

Метод register вызывается немедленно, когда поставщик услуг зарегистрирован, а команда boot вызывается только до того, как запрос маршрутизируется.

Итак, если действия вашего поставщика услуг полагаются на другого уже зарегистрированного поставщика услуг [...], вы должны использовать метод boot.

Ответ 2

Если вы работаете с Lumen, вы можете столкнуться с одинаковой проблемой. В этом случае просто раскомментируйте:

// $app->withFacades();

// $app->withEloquent();

in bootstrap\app.php

Ответ 3

@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();

Ответ 4

Что я сделал, было просто, я просто забыл раскомментировать $app->withFacades(); $app->withEloquent(); в моем загрузочном /app.php.

Теперь отлично работает

Ответ 5

Попробуйте включить фасад 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;)