Jump to content

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

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

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.