Question

Ok, to me this one is rather odd. But I'm probably just missing something.

I have a REST API using Slim with about 20 routes. Each route loads a MySQL class with a db config passed to the construct.

But, any time I'm adding a new route with a new db connection config (that I havent yet setup in the db), it throws a "bad db config" exception even though I am not calling the new/unfinished route.

So, it seems that the MySQL class in EVERY ROUTE is being instantiated whenever I make an API call.

Ummm..?

CODE SAMPLE PER REQUEST:

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

require('config/mysql.settings.php');
$db = new MySQL($dbconfig['pages']);

  $app->get('/:site/:page', function ($site, $page)  use ($app, $db) {
    ...
  });


});     

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

require('config/mysql.settings.php');
$db = new MySQL($dbconfig['docs']);

  $app->get('/:doc', function ($doc)  use ($app, $db) {
    ...
  });

});     

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

require('config/mysql.settings.php');
$db = new MySQL($dbconfig['price']);

  $app->get('/:doc', function ($doc)  use ($app, $db) {
    ...
  });

});     

If the user for the "price" configuration hasnt been added to the db, and I make a call to /library/get, I get a db error. Once I add the price user to the db, the error stops.

It has done this with every new db user I specify in a route - until its actually added to the db.

Was it helpful?

Solution

The Problem

This is a PHP thing, not a Slim thing. We both know that a PHP script executes from top to bottom, acting upon and evaluating whatever it finds as it goes. While it's true that code within Slim routes isn't executed until a route is matched, your MySQL class instantiation is happening within a route group definition, not within a route.

An Example

This example, based on the Slim Skeleton, is what I worked up to verify what I figured was happening.

<?php

require '../vendor/autoload.php';

// Prepare app
$app = new \Slim\Slim();

var_dump('app');

// Define routes
$app->get('/', function () use ($app) {
    echo "/";
});

$app->group('/v1', function () use ($app) {

    var_dump('/v1/var_dump');

    $app->get('/home', function () use ($app) {
        echo "/v1/home";
    });
});

$app->group('/v2', function () use ($app) {

    var_dump('/v2/var_dump');

    $app->get('/home', function () use ($app) {
        echo "/v2/home";
    });
});

// Run app
$app->run();

No matter which route you hit, all three calls to var_dump will be executed before the route code is executed.

A Recommendation

If this were my app, I'd consider using Slim's resource locator to configure your DB connections.

$app->dbConfig = $dbconfig;
$app->docsDb = function () use ($app) {
    return new MySQL($app->dbconfig['docs']);
};

Then, within the appropriate route, you can use the connection like so (assuming you have a findAll() method on your MySQL class):

$app->get('/example', function () use ($app) {
    $allDocs = $app->docsDb->findAll(); 
});

There are myriad benefits to that, not the least of which is avoiding having code in your index.php that's being unexpectedly executed out of turn.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top