Laravel rest API middleware - rest

I have a rest API where a lot of routes will be prefixed by /org/{id}. This prefix will scope the nested data and also the user will need to be checked if they are a member of the org. Would middleware be the best place to run these checks and also initialise an orgcontext class that can be accessed throughout the rest of the request?

A middleware is probably the perfect place to do those checks:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Repositories\Eloquent\UserRepository;
class CanAccessOrg
{
public function handle($request, Closure $next, UserRepository $userRepository)
{
if (! $userRepository->currentUserCanAccessOrg(Session::get('org'))) {
Auth::logout();
return redirect()->route('login')->withErrors(['msg', 'You dont have access to this org']);;
}
return $next($request);
}
}

Related

Proper way to access the container from a class not in a slim controller

I have a regular php class outside of a controller, so it doesn't benefit from automatic injection of container. I need to access the response object from that class, and I guess I should get it from the container.
What's the proper way to access it ? Just pass it as argument so the outside class can use it ? Is there a better way ?
You need to use middleware for that because the response object is immutable so "changing" it will not update the response which will be used by slim.
$app->add(function($request, $response, $next) {
if($shouldRedirect === true) {
return $response->withRedirect('myurl'); // do not execute next middleware/route and redirect
}
return $next($request, $response); // execute next middleware/ the route
});
For more information about middleware have a look at this.
If you need to send a subrequest, Slim provides such functionality. Use it carefully though, as in some situations its result is not obvious.
<?php
class MySortOfOutsideClass
{
/**
* If you need to send a subrequest, you have to access application instance,
* so let's inject it here.
*/
public function __construct(\Slim\App $app)
{
$this->$app = $app;
}
/**
* Method that makes a subrequest, and returns the result of it.
*/
public function myMethod()
{
if ($subRequestIsRequired) {
return $this->app->subRequest('GET', '/hello');
}
}
}

Zend Expressive Dependency Injection

If you want to have another middleware/object in a middleware
you have to use a factory like
namespace App\Somnething;
use Interop\Container\ContainerInterface;
class MyMiddlewareFactory
{
public function __invoke(ContainerInterface $container, $requestedName)
{
return new $requestedName(
$container->get(\App\Path\To\My\Middleware::class)
);
}
}
So MyMiddleware would have been injected with \App\Path\To\My\Middleware and we would be able to access it.
Question:
would it be wrong to inject the middleware with the app itself or the container? Like:
namespace App\Somnething;
use Interop\Container\ContainerInterface;
use Zend\Expressive\Application;
class MyMiddlewareFactory
{
public function __invoke(ContainerInterface $container, $requestedName)
{
return new $requestedName(
$container->get(Application::class)
);
}
}
This way it would be possible to get anything ~on the fly.
Like
namespace App\Somnething;
use Zend\Expressive\Application;
class MyMiddleware
{
/** #var Application $app */
protected $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function __invoke($some, $thing)
{
if ($some and $thing) {
$ever = $this->app
->getContainer()
->get(\Path\To\What\Ever::class);
$ever->doSome();
}
}
}
You don't inject middleware into other middleware. You inject dependencies like services or repositories. Each middleware takes care of a specifc task like authentication, authorization, localization negotiation, etc. They are executed one after the other. They mess around with the request and pass the request to the next middleware. Once the middleware stack has been exhausted, the response is returned all the way back through all the middleware in reverse order until it finally reaches the outer layer which displays the output. You can find a flow overview in the expressive docs.
I wouldn't advice to inject the container and certainly not the app itself. Although it might be easy during development, your application becomes untestable. If you inject only the services that are needed into a middleware, action or service you can easily mock those during tests. After a while you get used to writing factories where needed and it goes pretty fast.
The same goes for injecting the entity manager (if you use doctrine). It's easier to test an application if you only inject the needed repositories, which you can easily mock.
Having said this, if you are looking for an easy way to inject dependencies, zend-servicemanager can do that. Take a look at abstract factories. With an abstract factory you can create one factory for all your action classes:
<?php
namespace App\Action;
use Interop\Container\ContainerInterface;
use ReflectionClass;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
class AbstractActionFactory implements AbstractFactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
// Construct a new ReflectionClass object for the requested action
$reflection = new ReflectionClass($requestedName);
// Get the constructor
$constructor = $reflection->getConstructor();
if (is_null($constructor)) {
// There is no constructor, just return a new class
return new $requestedName;
}
// Get the parameters
$parameters = $constructor->getParameters();
$dependencies = [];
foreach ($parameters as $parameter) {
// Get the parameter class
$class = $parameter->getClass();
// Get the class from the container
$dependencies[] = $container->get($class->getName());
}
// Return the requested class and inject its dependencies
return $reflection->newInstanceArgs($dependencies);
}
public function canCreate(ContainerInterface $container, $requestedName)
{
// Only accept Action classes
if (substr($requestedName, -6) == 'Action') {
return true;
}
return false;
}
}
I wrote a blog post about that.
At the end of the day it's your own decision, but best practice is not injecting the app, container or the entity manager. It will make your life easier if you need to debug your middleware and / or write tests for it.
Injecting the application or container in your middleware is possible but it is not good idea at all:
1) Inversion Of Control (IoC)
It violated the inversion of control principle, your class must not have any knowledge about the IoC container.
2) Dependency Inversion Principle (DIP)
Dependency inversion principle states that "high-level modules should not depend on low-level modules", so your higher level middleware class depends on the infrastructure/framework.
3) Law of Demeter (LoD)
According to the law of demeter, the unit should have limited knowledge about other units, it should know only about its closely related units.
The MyMiddleware::class has too much knowledge other units, first of all, it knows about the Application::class, then it knows that the Application knows about the Container, then it knows that the Container knows about the What\Ever::class and so on.
This kind of code violates some of the most important OOP principles, leads to horrible coupling with the framework, it has implicit dependencies and least but not last, it is hard to be read and understood.

Using my own service with Laravel4

In my app, I was testing Google Directions API with ajax, but since I was just testing all the logic was in the routes.php file. Now I want to do things the proper way and have three layers: route, controller and service.
So in the routes I tell Laravel which method should be executed:
Route::get('/search', 'DirectionsAPIController#search');
And the method just returns what the service is supposed to return:
class DirectionsAPIController extends BaseController {
public function search() {
$directionsSearchService = new DirectionsSearchService();
return $directionsSearchService->search(Input::all());
}
}
I created the service in app/libraries/Services/Directions and called it DirectionsSearchService.php and copied all the logic I developed in routes:
class DirectionsSearchService {
public function search($input = array()) {
$origin = $input['origin'];
$destination = $input['destination'];
$mode = $input['mode'];
// do stuf...
return $data;
}
}
I read the docs and some place else (and this too) and did what I was supposed to do to register a service:
class DirectionsAPIController extends BaseController {
public function search() {
App::register('libraries\Services\Directions\DirectionsSearchService');
$directionsSearchService = new DirectionsSearchService();
return $directionsSearchService->search(Input::all());
}
}
// app/libraries/Services/Directions/DirectionsSearchService.php
use Illuminate\Support\ServiceProvider;
class DirectionsSearchService extends ServiceProvider {
}
I also tried adding libraries\Services\Directions\DirectionsSearchService to the providers array in app/config/app.php.
However, I am getting this error:
HP Fatal error: Class
'libraries\Services\Directions\DirectionsSearchService' not found in
/home/user/www/my-app-laravel/bootstrap/compiled.php on line 549
What am I doing wrong? And what is the usual way to use your own services? I don't want to place all the logic in the controller...
2 main things that you are missing:
There is a difference between a ServiceProvider and your class. A service provider in Laravel tells Laravel where to go look for the service, but it does not contain the service logic itself. So DirectionsSearchService should not be both, imho.
You need to register your classes with composer.json so that autoloader knows that your class exists.
To keep it simple I'll go with Laravel IoC's automatic resolution and not using a service provider for now.
app/libraries/Services/Directions/DirectionsSearchService.php:
namespace Services\Directions;
class DirectionsSearchService
{
public function search($input = array())
{
// Your search logic
}
}
You might notice that DirectionsSearchService does not extend anything. Your service becomes very loosely coupled.
And in your DirectionsAPIController.php you do:
class DirectionsAPIController extends BaseController
{
protected $directionsSearchService;
public function __construct(Services\Directions\DirectionsSearchService $directionsSearchService)
{
$this->directionsSearchService = $directionsSearchService;
}
public function search()
{
return $this->directionsSearchService->search(Input::all());
}
}
With the code above, when Laravel tries to __construct() your controller, it will look for Services\Directions\DirectionsSearchService and injects into the controller for you automatically. In the constructor, we simply need to set it to an instance variable so your search() can use it when needed.
The second thing that you are missing is to register your classes with composer's autoload. Do this by adding to composer.json's autoload section:
"autoload": {
"classmap": [
... // Laravel's default classmap autoloads
],
"psr-4": {
"Services\\": "app/libraries/Services"
}
}
And do a composer dump-autoload after making changes to composer.json. And your code should be working again.
The suggestion above can also be better with a service provider and coding to the interface. It would make it easier to control what to inject into your controller, and hence easier to create and inject in a mock for testing.
It involves quite a few more steps so I won't mention that here, but you can read more in Exploring Laravel’s IoC container and Laravel 4 Controller Testing.

ZF2 Use Redirect in outside of controller

I'm working on an ACL which is called in Module.php and attached to the bootstrap.
Obviously the ACL restricts access to certain areas of the site, which brings the need for redirects. However, when trying to use the controller plugin for redirects it doesn't work as the plugin appears to require a controller.
What's the best way to redirect outside from outside of a controller? The vanilla header() function is not suitable as I need to use defined routes.
Any help would be great!
Cheers-
In general, you want to short-circuit the dispatch process by returning a response. During route or dispatch you can return a response to stop the usual code flow stop and directly finish the result. In case of an ACL check it is very likely you want to return that response early and redirect to the user's login page.
You either construct the response in the controller or you check the plugin's return value and redirect when it's a response. Notice the second method is like how the PRG plugin works.
An example of the first method:
use Zend\Mvc\Controller\AbstractActionController;
class MyController extends AbstractActionController
{
public function fooAction()
{
if (!$this->aclAllowsAccess()) {
// Use redirect plugin to redirect
return $this->redirect('user/login');
}
// normal code flow
}
}
An example like the PRG plugin works:
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Http\Response;
class MyController extends AbstractActionController
{
public function fooAction()
{
$result = $this->aclCheck();
if ($result instanceof Response) {
// Use return value to short-circuit
return $result
}
// normal code flow
}
}
The plugin could then look like this (in the second case):
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
class AclCheck extends AbstractPlugin
{
public function __invoke()
{
// Check the ACL
if (false === $result) {
$controller = $this->getController();
$redirector = $controller->getPluginManager()->get('Redirect');
$response = $redirector->toRoute('user/login');
return $response;
}
}
}
In your question you say:
[...] it doesn't work as the plugin appears to require a controller.
This can be a problem inside the controller plugin when you want to do $this->getController() in the plugin. You either must extend Zend\Mvc\Controller\Plugin\AbstractPlugin or implement Zend\Mvc\Controller\Plugin\PluginInterface to make sure your ACL plugin is injected with the controller.
If you do not want this, there is an alternative you directly return a response you create yourself. It is a bit less flexible and you create a response object while there is already a response object (causing possible conflicts with both responses), but the plugin code would change like this:
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\Http\PhpEnvironment\Response;
class AclCheck extends AbstractPlugin
{
public function __invoke()
{
// Check the ACL
if (false === $result) {
$response = new Response;
$response->setStatusCode(302);
$response->getHeaders()
->addHeaderLine('Location', '/user/login');
return $response;
}
}
}

How to work with dependency injection within SOA?

I'm currently using SOA, I've a bunch of Service, (ArticleService, CommentService, UserService, etc..)
I also have a ConfigurationService which is filled from an XML configuration file.
I'm using Zend Framework.
THis configuration service is needed in some of my service, and I'm using dependency injection, is it a good practice, to add ConfigurationService in constructor of most my Service to be able to fetch global configuration?
Thank you for your feedbacks.
I would say, no, don't pass the config container - neither as a service nor as an array nor a Zend_Config instance - in the constructor of your other services. I would keep the injection (whether by constructor or by setter) for those services focused on the actual objects/collaborators/data they actually need.
So, for example, an ArticleService might depend upon an ArticleRepository interface/object or on an ArticleMapper or on a db adapter. Let the constructor/setter signatures for the ArticleService reflect what it truly needs.
Instead, what I would do is during Bootstrap, create some kind of factory object - perhaps as an application resource - that accepts in its constructor your config data/object/service (or even better, the bootstrap instance itself, from which you could get, not just your config data, but also any application resources, like a db adapter, that were created during the bootstrap process). Then write methods on your factory object that create/deliver the other services you need. Internally, the factory maintains a registry of already created services so that it can lazy-create instances where required.
A snippet of what I have in mind might be as follows:
Bootstrap snippet:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initFactory()
{
$factory = new My_Factory($this);
return $factory;
}
}
Then the factory:
class My_Factory
{
protected $_registry;
protected $_bootstrap;
public function __constructor($bootstrap)
{
$this->_bootstrap = $bootstrap;
}
public function getDbAdapter()
{
if (!isset($this->_registry['dbAdapter']){
$this->_bootstrap->bootstrap('db'); // probably using app resource
$this->_registry['dbAdapter'] = $This->_bootstrap->getResource('db');
}
return $this->_registry['dbAdapter'];
}
public function getArticleService()
{
if (!isset($this->_registry['articleService']){
$dbAdapter = $this->getDbAdapter();
$this->_registry['articleService'] = new My_ArticleService($dbAdapter);
}
return $this->_registry['articleService'];
}
public function getTwitterService()
{
if (!isset($this->_registry['twitterService']){
$options = $this->_bootstrap->getOptions();
$user = $options['twitter']['user'];
$pass = $options['twitter']['pass'];
$this->_registry['twitterService'] = new My_TwitterService($user, $pass);
}
return $this->_registry['twitterService'];
}
}
Then in a controller, you could grab an ArticleService instance:
class SomeController extends Zend_Controller_Action
{
protected $_factory;
public function init()
{
$this->_factory = $this->getInvokeArg('bootstrap')->getResource('factory');
}
public function someAction()
{
$articleService = $this->_factory->getArticleService();
$this->view->articles = $articleService->getRecentArticles(5); // for example
}
}
The upshot here is that each service explicitly identifies the collaborators it needs and the factory is a single place that takes care of creating/injecting all those collaborators.
Finally, I confess that I am just spitballing here. To me, this is essentially a rudimentary dependency injection container; in that sense, using a fully-featured DIC - perhaps the Symfony DIC or the new Zend\Di package in ZF2 - might be better. But after many months of struggling with all the best-practice recommendations to inject your dependencies, this is what I have come up with. If it's goofy or just plain wrong, please (please!) straighten me out. ;-)