I'm in Laravel 5.1, for reference.
I'm looking to extend the Log feature in such a way that running it from any point in the code (including in the built in vendor libraries) will also trigger an additional method of my choosing. How would I go about doing this?
Laravel fires an event named illuminate.log when logging the data. So your can listen to that event and can call your extra methods.
For example:
Add following code in your boot() method of class App\Providers\AppServiceProvider:
public function boot()
{
\Event::listen('illuminate.log', function ($level, $message, $context) {
// call your extra functions
});
}
Related
I have an api and some routes are public some need to be protected via auth. I want to have them in one controller class as they are related. I can extend the controller and have beforeRoute function but it runs for any route that is in that controller. is it possible to add a middleware only to specific routes? I'm a js dev and in express I can just pass middleware functions for any route, even multiple middlewares.
class Clanky /*extends \controllers\ProtectedController */{
public function post_novy_clanek(\Base $base) {
//needs to be protected
}
public function get_clanky(\Base $base) {
}
public function get_clanek(\base $base) {
}
public function get_kategorie(\Base $base) {
}
}
PHP is new to me, I just want to know how I can implement the concepts I know from other languages and frameworks in this weird fatfree framework. Thanks.
Use can use f3-access plugin for that purpose https://github.com/xfra35/f3-access
Fatfree is not opinionated about how to do this.. other options to solve this ask might be:
Use php8 attributes on the method and check these in beforeroute.
Consider an own named route naming schema like #admin_routename and apply checking auth in beforeroute
Use f3-middleware plugin and add auth there
Extend an other admin controller that provides auth in beforeroute or use a trait.
I am reading through the Laravel documentation to get a deeper understanding and this would be the second time I run into a bit of confusion.
Not long ago, I was working through a Laracasts video in which we implement a View composer in our AppServicesProvider register method.
Which looks like this:
public function register()
{
view()->composer('layouts.sidebar', function ($view) {
$archives = \App\Post::archives();
$tags = \App\Tag::has('posts')->pluck('name');
$view->with(compact('archives', 'tags'));
});
}
What this does, is it makes archives and tags available for our sidebar view, which is available in almost every page. (The Laracast videos involved building a blog from scratch)
So far so good.
Today, as I am reading through the documentation of a view composer, I encounter this example:
/**
* Register bindings in the container.
*
* #return void
*/
public function boot()
{
// Using class based composers...
View::composer(
'profile', 'App\Http\ViewComposers\ProfileComposer'
);
// Using Closure based composers...
View::composer('dashboard', function ($view) {
//
});
}
Now, I THINK I understand creating your own ComposerServiceProvider and class based composers vs closure based. The source of my confusion is that this is being done in the boot() method vs the register() method.
It's totally possible that I wrote this in the wrong place. If I think about it, it almost doesn't make sense for it to be in the register() method, since register should only be used to register services. The boot is called after ALL the register methods are called. If someone could clear this up for me I would appreciate it!
Does view composer belong in the register() method or boot() method? And
if it belongs in the register() method, is it just a coincidence that
it still works for me?
Citing the answer given by a user in this question:
Difference between boot and register method?
I actually just learned the difference last night from Taylor's book.
Here is an excerpt about it:
“After all providers have been registered, they are “booted”. This
will fire the boot method on each provider. A common mistake when
using service providers is attempting to use the services provided by
another provider in the register method. Since, within the register
method, we have no guarantee all other providers have been loaded, the
service you are trying to use may not be available yet. So, service
provider code that uses other services should always live in the boot
method. The register method should only be used for, you guessed it,
registering services with the container. Within the boot method, you
may do whatever you like: register event listeners, include a routes
file, register filters, or anything else you can imagine.”
So the register one is just for binding. The boot one is to actually
trigger something to happen.
They should be placed in the boot method. The register method does not guarantee dependencies will be resolved when you may need them. With the boot method you have that guarantee. And as you mentioned, ideally you should create a separate service provider for the view composers.
I have a question! I have a library, whenever I need to call, I'll include it into & new Class() like the link below.
Now, I want to include it to use with Lumen framework & call usually inton Controller, then how to register service, class in Lumen to make it comfortable so that when needing, just call new FileMaker();
http://laravel.io/bin/E3d9x
Thank you so much!
What you're looking for is a Service Provider. Instead of including files in your Controllers, and then new'ing up instances of a class it is better to register the class within a service provider and then resolve the object out of the IoC container.
An example of how you can register a provider:
public function register()
{
$this->app->singleton('Full\Vendor\Namespace\FileMaker', function($app) {
return new FileMaker('someparameters');
});
}
Doing it this way means that you can inject dependencies into your Controllers and Laravel, or Lumen in this case will automatically resolve the object without you needing to instantiate the object.
For example, in your controller:
public function someControllerMethod(FileMaker $filemaker)
{
// The $filemaker instance is available to use
}
I'm using the Revisionable package in my laravel app to log edits to a model.
In addition I have also implemented an observer class to listen for specific model events (update, delete, create etc) and perform actions (such as clear caches etc). This observer is instantiated in the model using the boot() method as follows:
class Client {
use \Venturecraft\Revisionable\RevisionableTrait;
public static function boot()
{
parent::boot();
Client::observe(new App\Observers\ClientObserver);
}
}
What I find is that when I define a boot() method in my model the Revisionable Trait stops working and does not log changes - presumably because it too uses a boot method that is being overridden by the one in the model.
How would I fix this to allow listening for model events as well as utilizing the Revisionable package?
this link helped me
https://github.com/VentureCraft/revisionable/issues/175
I used in laravel 5.1 i hope it will work to you
use RevisionableTrait, UuidTrait {
UuidTrait::boot insteadof RevisionableTrait;
}
In Slim is it possible to get the current route within middleware?
class Auth extends \Slim\Middleware{
public function call(){
$currentRoute = $this->app->getRoute(); // Something like this?
}
}
I know you can call $app->router()->getCurrentRoute() after the slim.before.dispatch hook is called, but when you call this from middleware it returns a non-object. Any help would be greatly appreciated.
Yes and no. If you look at the source code for Slim, you will see that registered Middlewares are called in LIFO order when the Slim::run method is called, and then Slim runs it's own "call" method where the processing of the request begins. It is in this method that Slim parses and processes the route. In which case, you cannot access $app->router()->getCurrentRoute() in the Middleware::call method because it won't have been parsed and defined yet.
The only way to do this is to register a listener on slim.before.dispatch inside your Middleware, and implement whatever you want to do in that method.
From the name of your class I assume you are trying to create a basic authentication module? I've done something similar to this before, and it went something like this:
class AuthMiddleware extends \Slim\Middleware
{
public function call()
{
$this->app->hook('slim.before.dispatch', array($this, 'onBeforeDispatch'));
$this->next->call();
}
public function onBeforeDispatch()
{
$route = $this->app->router()->getCurrentRoute();
//Here I check if the route is "protected" some how, and if it is, check the
//user has permission, if not, throw either 404 or redirect.
if (is_route_protected() && !user_has_permission())
{
$this->app->redirect('/login?return=' . urlencode(filter_input(INPUT_SERVER, 'REQUEST_URI')));
}
}
}
In this example, the onBeforeDispatch method will be run before of the route handlers are invoked. If you look at the source code, you can see the events are fired inside a try/catch block that is listening for the exceptions thrown by $app->redirect() and $app->pass(), etc. This means we can implement our check/redirect logic here just as if this was a route handler function.
Above is_route_protected and user_has_permission are just pseudo-code to illustrate how my auth middleware worked. I structured the class so that you could specify a list of routes or regex for routes in the Middleware constructor that were protected, as well as passing a service object that implemented the user permission checking, etc. Hope this helps.
There is an alternative method of doing this, as I've been in the same situation. What I wanted to avoid was matching anything by route and wanted to use route names instead, so you could try the following:
public function call() {
$routeIWantToCheckAgainst = $this->slimApp->router()->urlFor('my.route.name');
$requestRoute = $this->slimApp->request()->getPathInfo();
if ($routeIWantToCheckAgainst !== $requestRoute) {
// Do stuff you need to in here
}
$this->next->call();
}
You could even have an array of routes you DON'T want the middleware to run on and then just check if it's in_array() etc and if not, do what you need to.
You should use app->request()->getPathInfo() instead of app->getRoute().
class Auth extends \Slim\Middleware{
public function call(){
$currentRoute = $this->app->request()->getPathInfo();
}
}