Jump to content
Sign in to follow this  
NotionCommotion

Directly accessing a method in the Slim container

Recommended Posts

I typically implement slim as follows:
 
<?php

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';

function getConfig() {
    //...
    return $config;
}
$c = new \Slim\Container(['settings' => array_merge([
    'displayErrorDetails'=>true,                // set to false in production
    'addContentLengthHeader'=>false,            // Allow the web server to send the content-length header
    'determineRouteBeforeAppMiddleware'=>true
    ],getConfig())]
);

$c['view'] = function ($c) {
    $view = new \Slim\Views\Twig(__DIR__.'/../src/templates', [
        //'cache' => 'path/to/cache'    // See auto_reload option
        'debug' => true,
        'strict_variables'=> true
    ]);
    $view->addExtension(new \Slim\Views\TwigExtension(
        $c['router'],
        $c['request']->getUri()
    ));
    $view->addExtension(new \Twig_Extension_Debug());
    //$view->getEnvironment()->addGlobal('path', $uri->getPath());  //If desired on all pages
    return $view;
};

$c['someClass'] = function($c) {
    return new \SomeClass($c['settings']['server']);
};
$c['someOtherClass'] = function($c) {
    return new \SomeOtherClass();
};

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

$app->post('/someEndpoint', function (Request $request, Response $response) {
    $rsp=$this->get('someClass')->someMethod([]);   //Returns array with content and HTTP status code.
    return $response->withJson($rsp[0],$rsp[1]);
});

$app->get('/someEndpoint', function (Request $request, Response $response) {/*...*/});
$app->get('/someOtherEndpoint', function (Request $request, Response $response) {/*...*/});

$app->add(function(Request $request, Response $response, $next) {
    //Add middleware
});

$app->run();
I know need an endpoint which based on a ContentType parameter will either render a page which contains text obtained from another API or will download a file based on this other API, and am using the following:
 
$app->get('/guids/{guid}/logs/{id:[0-9]+}', function (Request $request, Response $response, $args) {
    switch($request->getQueryParam('ContentType')) {
        case 'text':
            return $this->view->render($response, 'log.html', [
                'server'=>$this->get('base')->getServer(),
                'menu_main'=>$this->get('base')->getMenu('/guids'),
                'backupDate'=>$this->get('base')->restApi('get', _VER_.'/backup')[0],
                'content'=>$this->get('base')->restApi('get', _VER_."/guids/$args[guid]/logs/$args[id]",['ContentType'=>'text'])[0],
            ]);
            break;
        case 'file':
            $config=$this->get('settings')['server'];
            $query=$request->getUri()->getQuery();
            $query=$query?"?$query":null;
            $url=$config['ip']._VER_."/guids/$args[guid]/logs/$args[id]$query";
            $context = stream_context_create(['http'=>['header'=>'X-User-Key: '.$config['key']]]);
            $fh = fopen($url, 'rb', false, $context);  //r or rb?
            $stream = new \Slim\Http\Stream($fh);
            $headers = $stream->getMetadata()['wrapper_data'];
            $forwardHeader=[
                'Content-Description'=>'File Transfer',
                'Content-Type'=>'application/octet-stream',
                'Content-Transfer-Encoding'=>'binary',
                'Content-Disposition'=>'attachment; filename="replaced_name"',
                'Expires'=>0,
                'Cache-Control'=>'must-revalidate, post-check=0, pre-check=0',
                'Pragma'=>'public',
                'Content-Length'=>false,   //Possible to get stream length?
            ];
            foreach ($headers as $header) {
                $header=explode(':',$header);
                if($header && count($header)==2 && isset($forwardHeader[$header[0]])){
                    //Should I really be modifying the $response?
                    $response=$response->withHeader($header[0],trim($header[1]));
                    unset($forwardHeader[$header[0]]);
                }
            }
            //Is this necessary?
            foreach ($forwardHeader as $key=>$value) {
                if($value!==false){
                    $response=$response->withHeader($key,$value);
                }
            }
            return $response->withBody($stream);
            break;
        default:
            return $response->withJson('Invalid requested content type',422);
    }
});

To improve readability, I desire my endpoint scripts to be very concise as shown in my previous script, and perhaps I need need to use this script for other endpoints, so I wish to more it to a separate method.  I guess I could (and maybe should) make a separate class with a single method, but I was trying to move it to another function in the container instead and am having issues.  I was thinking of something like the following:

$c['ContentType'] = function ($c) {
    return function($request, $response, $args) {
        switch($request->getQueryParam('ContentType')) {
            case 'text':
                return $this->view->render($response, 'log.html', [
                    //....
                ]);
                break;
            case 'file':
                //....
                return $response->withBody($stream);
                break;
            default:
                return $response->withJson('Invalid requested content type',422);
        }
    };
};

$app->get('/guids/{guid}/logs/{id:[0-9]+}', function (Request $request, Response $response, $args) {
    return $this->ContentType($request, $response, $args);
});

However, no matter what I tried, I either find that ContentType is not a valid method or that I am trying to pass one parameter instead of the expected three to it.  How can this be implemented?

 

Thanks

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.