Container->get('route') method in slim framework - php

What does Container->get('route') method returns and why
It is used in twig extension with slim

The Slim Twig extension requires the router (not the route) instance for the custom template functions like path_for() and base_url().
Example:
// Register Twig View helper
$container['view'] = function ($c) {
$view = new \Slim\Views\Twig('path/to/templates', [
'cache' => 'path/to/cache'
]);
// Instantiate and add Slim specific extension
$router = $c->get('router');
$uri = \Slim\Http\Uri::createFromEnvironment(new \Slim\Http\Environment($_SERVER));
$view->addExtension(new \Slim\Views\TwigExtension($router, $uri));
return $view;
};
Please read the slimphp/Twig-View documentation.

Related

how to add twig-view in slimframework v4

I'm trying to add twig-view in slim v4
In slim v3, we add twig-view in container
$container['view'] = function ($c) {
$view = new \Slim\Views\Twig('path/to/templates', [
'cache' => 'path/to/cache'
]);
// Instantiate and add Slim specific extension
$router = $c->get('router');
$uri = \Slim\Http\Uri::createFromEnvironment(new \Slim\Http\Environment($_SERVER));
$view->addExtension(new \Slim\Views\TwigExtension($router, $uri));
return $view;
};
but I can't add twig like that in slim v4
Update: Twig-View has reached a stable version and the docs are updated to address Slim 4 integration.
If you are still using an unstable version of Twig-View, please consider upgrading.
First, you need to add Twig-View package to your project:
composer require slim/twig-view
And assuming the following directory structure:
composer.json
cache/
public/
|--index.php
templates/
|--hello.twig
vendor/
|--autoload.php
The followings are two working examples:
If you use a container (which is optional according to Slim 4 docs), you can add Tiwg creation definition to the container and use it when required. (I'm using php-di/php-di in this example, but you can use any PSR compatible dependency container.)
index.php, using a container:
<?php
use DI\Container;
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
require __DIR__ . '/../vendor/autoload.php';
// Create Container
$container = new Container();
AppFactory::setContainer($container);
// Set view in Container
$container->set('view', function() {
return Twig::create(__DIR__ . '/../templates',
['cache' => __DIR__ . '/../cache']);
});
// Create App
$app = AppFactory::create();
// Add Twig-View Middleware
$app->add(TwigMiddleware::createFromContainer($app));
// Example route
$app->get('/hello/{name}', function ($request, $response, $args) {
return $this->get('view')->render($response, 'hello.twig', [
'name' => $args['name']
]);
});
// Run the app
$app->run();
You can also skip the container creation, but in that case you need to create the Twig instance before trying to render a template.
index.php, without a container:
<?php
use Slim\Factory\AppFactory;
use Slim\Views\Twig;
use Slim\Views\TwigMiddleware;
require __DIR__ . '/../vendor/autoload.php';
// Create App
$app = AppFactory::create();
// Create Twig
$twig = Twig::create(__DIR__ . '/../templates',
['cache' => __DIR__ . '/../cache']);
// Add Twig-View Middleware
$app->add(TwigMiddleware::create($app, $twig));
// Example route
// Please note how $view is created from the request
$app->get('/hello/{name}', function ($request, $response, $args) {
$view = Twig::fromRequest($request);
return $view->render($response, 'hello.twig', [
'name' => $args['name']
]);
});
// Run the app
$app->run();
hello.twig:
Hello {{ name }}
Now try visiting /hello/slim4 in your browser and the output will be:
Hello slim4
SlimTwigView is at 3.0.0 beta (at least as of October 12, 2019), and some things have changed. The few online tutorials I've seen, as well as the official documentation no longer work.
TwigMiddleware no longer takes an instance of the $container as an argument, so you must first put Twig on the Container manually such as:
$container->set('view', function() {
// Of course put correct path to your views here
return new Twig('../views', ['cache' => false]);
});
You then you can add TwigMiddleware to your Slim App using the class' new createFromContainer method, like so:
$app->add(TwigMiddleware::createFromContainer($app));
// which is equivalent to:
// $app->add(TwigMiddleware::createFromContainer($app, 'view'));
At that point, you can render a Twig view like so:
$app->get('/', function (Request $request, Response $response, $args) {
return $this->get('view')->render($response, 'home.twig');
});
When using the Slim specific middleware, you now have access to the additional Twig extensions:
url_for
full_url_for
is_current_url
current_url
get_uri
Well! In my case I was using Slim 4.0 and Twig ^2.5. All I added to my code was
$container->set('view', function () use ($container) {
$view = new \Slim\Views\Twig(
__DIR__ .'/Templates'
, [ 'cache' => false ] //you can turn on caching by providing string path to cache or set to false
);
return $view;
});

Symfony Routing Component not routing url

I have mvc php cms like this folder structure:
application
---admin
--------controller
--------model
--------view
--------language
---catalog
--------controller
------------------IndexController.php
--------model
--------view
--------language
core
--------controller.php
//...more
public
--------index.php
vendor
I install symfony/router component for help my route url using composer json:
{
"autoload": {
"psr-4": {"App\\": "application/"}
},
"require-dev":{
"symfony/routing" : "*"
}
}
Now with route documents I add this code for routing in index.php:
require '../vendor/autoload.php';
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$route = new Route('/index', array('_controller' => 'App\Catalog\Controller\IndexController\index'));
$routes = new RouteCollection();
$routes->add('route_name', $route);
$context = new RequestContext('/');
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match('/index');
In My IndexController I have :
namespace App\Catalog\Controller;
class IndexController {
public function __construct()
{
echo 'Construct';
}
public function index(){
echo'Im here';
}
}
Now in Action I work in this url: localhost:8888/mvc/index and can't see result : Im here IndexController.
How do symfony routing url work and find controller in my mvc structure? thank for any practice And Help.
The request context should be populated with the actual URI that's hitting the application. Instead of trying to do this yourself you can use the HTTP Foundation package from symfony to populate this:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContext;
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
It's also documented here: https://symfony.com/doc/current/components/routing.html#components-routing-http-foundation
After the matching ($parameters = $matcher->match('/index');) you can use the _controller key of the parameters to instantiate the controller and dispatch the action. My suggestion would be to replace the last \ with a different symbol for easy splitting, like App\Controller\Something::index.
You can then do the following:
list($controllerClassName, $action) = explode($parameters['_controller']);
$controller = new $controllerClassName();
$controller->{$action}();
Which should echo the response you have in your controller class.

Plates Template Engine - URI extension same as Twig 'pathFor'?

I'm working thru a tutorial on the Slim framework. The author uses Twig, and I'd prefer to use the Plates template engine. I've been able to modify all lessons to use the Plates template, until the author started using baseUrl and pathFor extensions.
I see that Plates has an extension called URI, which I think is synonymous with Twig's pathFor.
Unfortunately, I can't for the life of me figure out how to get it enabled. Reading the documentation, I thought the following code would do it, but so far no luck.
require 'vendor/autoload.php';
$app = new Slim\App([
'settings' => [
'displayErrorDetails' => true
]
]);
$container = $app->getContainer();
$container['view'] = function ($container) {
$plates = new League\Plates\Engine(__DIR__ . '/templates');
$plates->loadExtension(new League\Plates\Extension\URI($_SERVER['PATH_INFO']));
return $plates;
};
$app->get('/contact', function($request, $response) {
return $this->view->render('contact');
});
$app->post('/contact', function($request, $response) {
return $response->withRedirect('http://slim-local.com/contact/confirm');
})->setName('contact');
$app->get('/contact/confirm', function($request, $response) {
return $this->view->render('contact_confirm');
});
$app->run();
And then in the template, the author used the pathFor extension to populate a form's action parameter. I am trying to use Plates' URI extention to do the same like so:
<form action="<?=$this->uri('contact')?>" method="post">
Has anybody used this template engine and the URI extension with Slim specifically? Am I mistaken that it is basically synonymous with Twig's pathFor extension? Should I give up and just use Twig? thanks for your advice.
You can use the URI from the environment.
Slim 3 example:
$container['view'] = function ($container) {
$plates = new \League\Plates\Engine(__DIR__ . '/templates');
$uri = \Slim\Http\Uri::createFromEnvironment(new \Slim\Http\Environment($_SERVER));
$plates->loadExtension(new \League\Plates\Extension\URI($uri->__toString()));
return $plates;
};

Symfony3 Hook Up Annotation Routes

I'm writing my own PHP framework built on top of Symfony components as a learning exercise. I followed the tutorial found at http://symfony.com/doc/current/create_framework/index.html to create my framework.
I'd now like to wire up my routes against my controllers using annotations. I currently have the following code to setup the routing:
// Create the route collection
$routes = new RouteCollection();
$routes->add('home', new Route('/{slug}', [
'slug' => '',
'_controller' => 'Controllers\HomeController::index',
]));
// Create a context using the current request
$context = new RequestContext();
$context->fromRequest($request);
// Create the url matcher
$matcher = new UrlMatcher($routes, $context);
// Try to get a matching route for the request
$request->attributes->add($matcher->match($request->getPathInfo()));
I have come across the following class to load the annotations but I'm not sure how to use it:
https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php
I'd appreciate it if someone could help.
Thanks
I've finally managed to get this working. First I changed where I included the autoload.php file to the following:
use Doctrine\Common\Annotations\AnnotationRegistry;
$loader = require __DIR__ . '/../vendor/autoload.php';
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
Then I changed the routes collection bit (in the question) to:
$reader = new AnnotationReader();
$locator = new FileLocator();
$annotationLoader = new AnnotatedRouteControllerLoader($reader);
$loader = new AnnotationDirectoryLoader($locator, $annotationLoader);
$routes = $loader->load(__DIR__ . '/../Controllers'); // Path to the app's controllers
Here's the code for the AnnotatedRouteControllerLoader:
class AnnotatedRouteControllerLoader extends AnnotationClassLoader {
protected function configureRoute(Route $route, ReflectionClass $class, ReflectionMethod $method, $annot) {
$route->setDefault('_controller', $class->getName() . '::' . $method->getName());
}
}
This has been taken from https://github.com/sensiolabs/SensioFrameworkExtraBundle/blob/master/Routing/AnnotatedRouteControllerLoader.php. You may wish to modify it to support additional annotations.
I hope this helps.

Set template directory using Slim Framework 3

Using Slim Framework 2 you could set the template directory using this code:
// Views
$view = $app->view();
$view->setTemplateDirectory('../app/views');
How can I do this using Slim Framework 3?
Currently I'm getting this error:
Fatal error: Call to a member function setTemplateDirectory() on null
Does anybody know how to do this in Slim Framework 3?
You can do it using a \Slim\Container instance:
// Create container
$container = new \Slim\Container;
// Register component on container
$container['view'] = function ($c) {
$view = new \Slim\Views\Twig('your/path/to/templates');
$view->addExtension(new \Slim\Views\TwigExtension(
$c['router'],
$c['request']->getUri()
));
return $view;
};
Then you can use it:
$app = new \Slim\App($container);
// The route
$app->get('/foo', function (ServerRequestInterface $request, ResponseInterface $response) {
return $this->view->render($response, 'index.html', [
'name' => 'name'
]);
});
$app->run();
Check the official documentation (Mika Tuupola's suggestion).

Categories