Closed cleartext closed 9 years ago
Here's some middleware that assumes that you're using Twig-View and the you have registered the Twig-View object in the Container as 'view':
function ($request, $response, $next){
$path = $request->getUri()->getPath();
$metaData = Orm::for_table(/*..*/);
$this->get('view')->getEnvironment()->addGlobal('metadata', $metadata);
return $next($request, $response);
}
(Buyer beware: code written off the top of my head...)
Hi @cleartext the code above should work. Also thanks for the feedback, I think this is something we will need to get sorted in the documentation, because as you say it feels somewhat harder to get into Slim 3 than it was with Slim 2, I would like to get some more of your feedback on anything else you are finding issues with so we can write some Cookbook style documentation around those areas.
Thanks guys, that doesn't work as is. I don't see an addGlobal in Twig-View at all, although the pointer to $this->get('view') helps a lot in that at least now I have a valid View object. Will keep trying.
Will also feedback any other issues I have, with my amateur hat on :)
The addGlobal() is in Twig_Environment which is why we getEnvironment() from the Twig-View
Or you should be able to do
$this->get('view')['metadata'] = $metadata;
There's something very odd happening here, I have;
// Create container $container = new \Slim\Container();
// Register component on container $container['view'] = function ($c) { $view = new \Slim\Views\Twig('views/'); $view->addExtension(new \Slim\Views\TwigExtension( $c['router'], $c['request']->getUri() )); return $view; };
// Create app $app = new \Slim\App($container);
$app->add(function ($request, $response, $next) { $response = $next($request, $response); $host = $request->getUri()->getHost(); $this->get('view')->getEnvironment()->addGlobal( 'host', $host ); return $response; });
Then in my template;
Just to test for now... still no joy. All runs fine, but 'host' appears to be empty.
Just ran a composer update to be sure I have the latest, I did get a small twig update, but no change. I think I need to leave this for a day and come back to it, been spending too long thinking too hard I think!
You are calling $next
too early in your middleware - i.e. before you set the global.
Change to:
$app->add(function ($request, $response, $next) {
$host = $request->getUri()->getHost();
$this->get('view')->getEnvironment()->addGlobal( 'host', $host );
$response = $next($request, $response);
return $response;
});
This way the 'host' value is added to Twig's global registry before you render it within your .twig file.
Ah, that fixed it. I knew I'd been looking at this far too long.
I should probably get into the habit of returning $next($request, $response) maybe?
A disadvantage of working from home, no-one close by to turn around to and ask for a quick look, thanks for spending the time on this for me Rob and Andrew.
You are very welcome :)
Have a look at https://speakerdeck.com/akrabat/building-an-api-with-slim-3?slide=30 for the general skeleton of a piece of middleware.
Personally I like to use return $next($request, $response);
when the middleware does something before dispatch.
That helps, penny drops on 'middleware' now, that's the first time I've seen it explicitly said that 'is code that sits between request and response'. v3 Docs could explain this a bit better, I will re-read v2 docs as well. rgrds, David.
I know im a bit late to the parttt-ehhhh, but I just wanted to share some config with y'all.
in the init code for Twig-View...
foreach ($c['twigConfig'] as $name => $value) {
$view->getEnvironment()->addGlobal($name, $value);
}
And in the container...
'twigConfig' => [
'title' => 'My Site Title',
'description' => '',
'author' => '',
//...
],
This is actually one of the main things holding me back from upgrading to Slim 3 (everything else looks really great!)
If there is some equivalency between hooks and middleware, would it be possible to implement generic Slim2-style hooking functionality as a piece of Slim3 middleware?
@alexweissman sadly no. Middleware are a type of hook though, the only thing you get in slim 3 is BEFORE or AFTER the route is executed.
Keep in mind that middleware is executed as a stack, so you can still setup which middleware gets called in what order.
Hmm, so, for those of us building applications that require a means of hooking-in functionality (to support plugins, themes, etc), should we implement our own hooks then? Is there a good third-party package for this?
I have no idea why you need hooks to be honest.
Can you provide an example of why you can't use a middleware and require a hook?
Well, you said so yourself - middleware ⊂ hooks, but not the other way around. Lets take my framework UserFrosting, for example, which is built on Slim. I have a "register account" route, which might have the following pseudocode:
$app->post('/account/register/?', function () use ($app) {
// Validate user data
...
// Hash new user password
...
// Create new User model
...
// Store new user to database
...
// Send confirmation email to new user
...
});
Suppose I want to allow third-party developers to easily hook into register
, and modify some aspect of the registration process before sending the email to the new user (let's take, as an example, setting up a gravatar icon or something). In Slim 2, this was easily done via:
// Store new user to database
...
// Send confirmation email to new user
...
$app->applyHook('registration.send_confirmation_email.before');
// Send confirmation email to new user
...
You can pretty easily implement this by using https://packagist.org/packages/symfony/event-dispatcher .
Thanks! That looks like a good alternative. Maybe this package could be an official recommendation in the Slim3 docs, as a replacement for those who truly need hooks?
Maybe this package could be an official recommendation in the Slim3 docs, as a replacement for those who truly need hooks?
We'd love a PR to Slim-Website! At a guess, this would be good to note in the /docs/start/upgrade.md
file.
I'm glad you got this resolved. I hadn't realized people were using Hooks as an event dispatcher. Very interesting!
Ahhh, I see! Like many things, this is an issue of vocabulary ;-) I'm not sure if the use of the word "hook" in this way was invented by Wordpress, but it certainly was popularized by it:
Many WordPress Plugins accomplish their goals by connecting to one or more WordPress Plugin "hooks". The way Plugin hooks work is that at various times while WordPress is running, WordPress checks to see if any Plugins have registered functions to run at that time, and if so, the functions are run. These functions modify the default behavior of WordPress.
Not that WP is a paragon of good programming and software design practices (it's definitely not), but WP refugees are everywhere, and would likely understand "hook" to mean "event dispatcher".
Hi All,
Loved SLIM 2, so easy to get started for an occasional developer like me but v3 is proving a bit harder to get to grips with.
In v2 I had a hook to pull page meta data from a table, based on the URL request, which was then dropped in via a Twig page header template, like this;
$app->hook('slim.before.router', function () use ($app) { $req = $app->request; $path_is = $req->getPath(); $metadata = ORM::for_table('metadata') ->select('*') ->where('url', $path_is) ->find_one(); $app->view->setData( array( 'metadata' => $metadata )); });
Now that Hooks have gone I've spent some time on middleware, and seeing that setData is going to be dropped I've been looking at Set on the View class. However so far I've not been able to reproduce the Hook using middleware.
Any help would be appreciated, even if it's 'read this' and a URL :)
thanks,
David. PS - It's great to see open source projects that are simple and easy to get into, they are essential for those of us who aren't full time developers but like to keep our hand in.