[SOLVED] Slim 3 Command Line

Hi,

I’m trying to create some kinds of import to move database info and transform data. In a feture this import needs to be executed by cron every day. I want to use part of my wrote code and reuse some models and controllers. To do this i’m trying to call Slim 3 through command line, but I have some problems.

First of one is commands:

 php cli.php import 

I don’t know how to process argv correctly.

Also, i have NotFound and Error Handlers with response object, but i don’t need response, i need plain text.

To do this i have cli.php:

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

if (PHP_SAPI == 'cli') {
    $argv = $GLOBALS['argv'];
    array_shift($argv);

    $pathInfo       = implode('/', $argv);

    $env = \Slim\Http\Environment::mock(['PATH_INFO' => $pathInfo]);

    $settings = require __DIR__ . '/app/config/settings.php'; // here are return ['settings'=>'']

    //i try adding here path_info but this is wrong, i'm sure
    $settings['environment'] = $env; 

    $app = new \Slim\App($settings);

   $container = $app->getContainer();
   $container['errorHandler'] = function ($c) {
        return function ($request, $response, $exception) use ($c) {
             //this is wrong, i'm not with http
             return $c['response']->withStatus(500)
                  ->withHeader('Content-Type', 'text/text')
                  ->write('Something went wrong!');
        };
    };

     $c['notFoundHandler'] = function ($c) {
        //this is wrong, i'm not with http
        return function ($request, $response) use ($c) {
            return $c['response']
                ->withStatus(404)
                ->withHeader('Content-Type', 'text/text')
                ->write('lalalalal');
        };
    };

    $app->map(['GET'], 'import', function() {
       // do import
    });
}

If i execute this i see a 404 Page not found html.

Any directions?
Thanks

EDIT:
I tryed to changes error handlers after reading some PSR-7 docs without luck:

$container['errorHandler'] = function ($c) {
    return function ($request, $response, $exception) use ($c) {

        $x      = $response->getBody();
        $x->write("error");
        return $response->withBody($x);
    };
};

$c['notFoundHandler'] = function ($c) {
    return function ($request, $response) use ($c) {

        $x      = $response->getBody();
        $x->write("command not found");
        return $response->withBody($x);

    };
};

Command line errors works :smile:

I used $c instead of $container :rage:

$container['errorHandler'] = function ($c) {
    return function ($request, $response, $exception) use ($c) {

        $x      = $response->getBody();
       $x->write("error");
       return $response->withBody($x);
    };
};

$container['notFoundHandler'] = function ($c) {
return function ($request, $response) use ($c) {

    $x      = $response->getBody();
    $x->write("command not found");
    return $response->withBody($x);

   };
};

But not found cli command

To make your example work you can make the following changes:

Change PATH_INFO to REQUEST_URI:
$env = \Slim\Http\Environment::mock(['PATH_INFO' => $pathInfo]);
into:
$env = \Slim\Http\Environment::mock(['REQUEST_URI' => $pathInfo]);

Start each path in the routes with a slash:
$app->map(['GET'], 'import', function() {
into:
$app->map(['GET'], '/import', function() {

Then you can call the import routine from the command line (not the trailing slash, you could also add that in your code):
php cli.php /import

The import route should now be triggered instead of the not found handler.

Note: if you separate the import logic to a separate class, you don’t have to run a route from the command line. You can reuse the class from both the command line and a web interface using Slim.

Hope that helps.

Hi llvdl

It works,

I just modified to add slash in code to avoid adding in call. Something like:

$env = \Slim\Http\Environment::mock(['REQUEST_URI' => '/' . $pathInfo]);

And it’s working
A lot of thanks

P.D.: I was added question in stackoverflow, if you want to answer also http://stackoverflow.com/questions/36935589/slim-3-console-execution-for-cron

Thanks again

Hello Victor,

I am glad to hear (read) it worked out. I don’t have a stackoverflow account yet. Please feel free to add the answer yourself.

Kind regards.

I had to add $app->run() after the map to get it working. Hope it helps someone else.

Victor, thanks for the code, you saved me a day )

1 Like

Little late to the party, but it might be worth to point out that someone made middleware for this:
https://github.com/adrianfalleiro/slim-cli-runner

$container = $app->getContainer();
$container[‘environment’] = function ($container) {

return  \Slim\Http\Environment::mock(['REQUEST_URI' => '/import']);

};
if(PHP_SAPI == ‘cli’) {

$app->get('/import',function () {
		echo "Hello";
});

}