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