Slim Php, Eloquent y DB facade

Últimamente he estado usando el microframework Slim Php, junto con varios componentes adicionales,  para realizar algunos proyectos personales. Hasta ahora la experiencia ha sido grata y sencilla pero no exenta de los clásicos problemas al aprender a usar nuevos frameworks.

Un inconveniente con el que me topé, ocurrió cuando quise ejecutar una query personalizada usando SQL (raw queries)  en vez de las funciones definidas por los modelos. A menudo puede utilizarse un constructor o query builder cuya forma de uso depende del ORM. En este caso en particular, me referiré a Eloquent que es usado en el framework Laravel y el cual integré con Slim.

Para instalarlo, de acuerdo a lo que se explica en el blog de slim, se debe agregar como dependencia a composer.json y luego instanciarlo en el bootstrap de la aplicación.  Además para integrarlo mejor fuera de Laravel se instaba a usar un componente “capsule” que funciona como wrapper para este propósito. Esto era más o menos así (omití código por simplicidad):

 

{
    "require": {
        "slim/slim": "2.*",
        "illuminate/database": "*",
        "dhorrigan/capsule": "*"
    }
}

Y la instanciación se realizaba así:

require 'vendor/autoload.php';

$app = new SlimSlim();

// Make a new connection
$app->db = CapsuleDatabaseConnection::make('default', [
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'port'      => 3306,
    'database'  => 'example',
    'username'  => 'root',
    'password'  => 'password',
    'prefix'    => '',
    'charset'   => "utf8",
    'collation' => "utf8_unicode_ci",
], true);

$app->get('/users', function () use ($app) {

    $users = User::all();

    $res = $app->response();
    $res['Content-Type'] = 'application/json';
    $res->body($users);
});

$app->run();

De acuerdo a la documentación oficial, se puede utilizar la fachada (facade) DB, con la sentencia use

use DB;

Luego se pueden usar un conjunto de métodos tales como insert, select, update, raw, delete, etc. Siguiendo con el ejemplo

$users = DB::select('select * from users where active = ?', [1]);

Pero acá comenzaban los problemas. Para empezar el componente de capsule (“dhorrigan/capsule”: “*”) ya no se puede utilizar, lo bueno es que ahora forma parte del núcleo de eloquent por lo que no es necesario incluirlo explícitamente en composer.json.

En segundo lugar al intendar utilizar la fachada DB ocurrían errores del tipo ‘ErrorException’ with message ‘Non-static method Illuminate\Database\Query\Builder::select() should not be called statically, assuming $this from incompatible context’.

 

 La solución para Slim Php, Eloquent y DB facade

Para que todo funcionase correctamente tuve que hacer algunas modificaciones tanto a composer.json como a la manera de instanciar Eloquent.

Lo primero es remover el componente capsule que no se necesita por lo que sólo queda

{
    "require": {
        "slim/slim": "*",
        "illuminate/database": "*"
    }
}

Luego se incluye Eloquent en el bootstrap de la aplicación.

$capsule = new Illuminate\Database\Capsule\Manager;
$capsule->addConnection(array(
    'driver'   => 'mysql',
    'host'     => 'localhost',
    'port'     => '3306',
    'username'     => 'root',
    'password' => 'password',
    'database'     => 'mydb',
    "charset"   => "utf8",
    'collation' => 'utf8_general_ci',
););
$capsule->setEventDispatcher(new Illuminate\Events\Dispatcher(new Illuminate\Container\Container));
$capsule->setAsGlobal();
$capsule->bootEloquent();

Finalmente, se puede usar la fachada DB incluyéndola de una manera ligeramente diferente, por ejemplo en un modelo:

use Illuminate\Database\Capsule\Manager as DB;
class User extends \Illuminate\Database\Eloquent\Model
{
    protected $table = 'user';
  
    public function getUser($id){
        $query = "SELECT * FROM user"; 
        return DB::select(DB::raw($query));		
  }

}

La query es bastante simple pero es para ilustrar el punto de poder realizar la integración deseada.