Eloquent bez Laravela

W pierwszym poście 2015 roku chciałbym pokrótce omówić temat używania ORM znanego z frameworka Laravel, czyli Eloquent, we własnym projekcie PHP, bez wykorzystania całego Laravela. Nie zawsze jest łatwo — natknąłem się na sytuację, której debugowanie przysporzyło mi trochę problemów. Ale da się.

Na początek polecam obejrzenie sobie screencasta, który popełnił Jeffrey Way na Laracasts. Stanowi on świetne wprowadzenie do tematu, a niniejszy wpis jest niejako uzupełnieniem.

Samo użycie Eloquenta nie jest specjalnie trudne. Zasysamy composerem paczkę illuminate/database (swoją drogą, dlaczego komponenty Laravela mają zupełnie inne nazwy niż ich repozytoria?) i wpisujemy następujący kawałek kodu:

$capsule = new \Illuminate\Database\Capsule\Manager();
$capsule->addConnection($connection);
$capsule->setAsGlobal();
$capsule->bootEloquent();

Oczywiście zmienna $connection zawierać powinna tablicę z danymi połączenia z bazą danych: hosta, nazwę bazy, użytkownika itd.

W moim przypadku wyglądało to jednak tak, że powyższy kod został umieszczony w usłudze odkrywczo nazwanej db. Ponieważ użyłem frameworka Silex, wyglądało to następująco:

​$app["db"] = $app->share(function ($app) {
    $capsule = new \Illuminate\Database\Capsule\Manager();
    $capsule->addConnection($app["dbConnection"]);
    $capsule->setAsGlobal();
    $capsule->bootEloquent();
    return $capsule;
});

Niby prawie nic się nie zmieniło, poza faktem, że zamiast wykonywać się zawsze, kod startujący Eloquenta był uruchamiany na żądanie, w momencie, gdy pierwszy raz chciałem użyć bazy danych. Usługa pięknie działała i udało się z jej wykorzystaniem zbudować kilka poleceń konsolowych — jedno tworzyło tabele bazy danych, drugie je dropowało, jeszcze trzecie dodawało nowego użytkownika do bazy. Słowem, żyć, nie umierać.

Ale w pewnym momencie stworzyłem sobie również model. Bo stworzonego użytkownika trzeba przecież kiedyś pobrać, a po co wykorzystywać do tego gołe połączenie do bazy, jeśli zasadniczo powinny się tym zajmować modele (czy też repozytoria encji w przypadku Doctrine)? I tu zaczęły się schody: gdy gdzieś w kontrolerze stworzyłem sobie instancję modelu i spróbowałem wyszukać użytkownika, dostałem taki oto błąd:

PHP Fatal error: Call to a member function connection() on a non-object in /home/mingos/www/uConnect/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php on line 2920

No i szukaj wiatru w polu. Stack trace nie wskazywał nic szczególnego: ot, dało się wyśledzić tylko tyle, że błąd spowodowało wywołanie metody find() na instancji mojego modelu. Ki diabeł? Przecież bazę stworzyłem normalnie, bez problemów dodałem użytkownika, a tu takie kwiatki?

Po pewnym czasie odkryłem problem: Eloquent nie został uruchomiony. Ale zaraz, jak to nie został? Przecież jest usługa, która za to odpowiada! No właśnie, jest — ale nie została użyta. Samo zainstancjonowanie modelu nie sprawia jeszcze, że usługa stworzona w Silexie została wywołana, a tym samym, że Eloquent został odpalony. Morał zatem jest taki: Eloquenta nie można odpalać warunkowo, czy, jak w moim przypadku, za pomocą lazy loading. Kod, który przygotowuje bazę danych do użycia poza Laravelem, musi zostać uruchomiony zanim faktycznie użyjemy ORMa.


Napisz komentarz


Szukaj wpisów


Chmura tagów