Jump to content


Photo

Directly accessing a method in the Slim container


  • Please log in to reply
No replies to this topic

#1 NotionCommotion

NotionCommotion
  • Members
  • PipPipPip
  • Advanced Member
  • 1,601 posts

Posted 08 May 2018 - 11:16 AM

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


NotionCommotion




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users