Skip to content

Instantly share code, notes, and snippets.

@jishcem
Created September 8, 2015 09:07
Show Gist options
  • Save jishcem/e8febe0ce2d2146e690e to your computer and use it in GitHub Desktop.
Save jishcem/e8febe0ce2d2146e690e to your computer and use it in GitHub Desktop.
PHP League Router Custom Strategy
{
"require": {
"league/route": "^1.2",
"twig/twig": "~1.0",
"illuminate/database": "5.0",
"symfony/validator": "^2.7",
"intervention/image": "^2.3",
"jasongrimes/paginator": "~1.0",
"symfony/filesystem": "^2.7"
},
"autoload": {
"psr-4": {
"MyApp\\Controllers\\": "app\\Controllers\\",
"MyApp\\Strategies\\": "app\\Strategy\\"
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Create</title>
<!-- Latest compiled and minified CSS & JS -->
<link rel="stylesheet" media="screen" href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="//code.jquery.com/jquery.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</head>
<body>
<div style="padding-top: 50px; padding-bottom: 50px;" class="container">
<div class="row">
<div class="col-md-6 col-md-offset-1">
<legend>Create Deal</legend>
<br/><br/>
<form action="/admin/deals/create" method="POST" role="form">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Name" value="{% if input.name %}{{ input.name }}{% endif %}">
</div>
<div class="form-group">
<label for="price">Price</label>
<input type="text" class="form-control" id="price" name="price" placeholder="Price" value="{% if input.price %}{{ input.price }}{% endif %}">
</div>
<div class="form-group">
<label for="old_price">Old Price</label>
<input type="text" class="form-control" id="old_price" name="old_price" placeholder="Old Price" value="{% if input.old_price %}{{ input.old_price }}{% endif %}">
</div>
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" name="title" placeholder="Title" value="{% if input.title %}{{ input.title }}{% endif %}">
</div>
<div class="form-group">
<label for="small_description">Small Description</label>
<input type="text" class="form-control" id="small_description" name="small_description" placeholder="Small Description" value="{% if input.small_description %}{{ input.small_description }}{% endif %}">
</div>
<div class="form-group">
<label for="description">Description</label>
<br/>
<textarea name="description" id="description" cols="30" rows="10">{% if input.description %}{{ input.description }}{% endif %}</textarea>
</div>
<div class="form-group">
<label for="link">Link</label>
<input type="url" class="form-control" id="link" name="link" placeholder="Link" value="{% if input.link %}{{ input.link }}{% endif %}">
</div>
<div class="form-group">
<label>Is Featured</label>
<div class="radio">
<label>
<input type="radio" name="is_featured" value="0" {% if not input.is_featured %}checked{% endif %} >
Is Not Featured
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="is_featured" value="1" {% if input.is_featured %}checked{% endif %} >
Is Featured
</label>
</div>
</div>
<div class="form-group">
<label>Is Popular</label>
<div class="radio">
<label>
<input type="radio" name="is_popular" value="0" {% if not input.is_popular %}checked{% endif %} >
Is Not Popular
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="is_popular" value="1" {% if input.is_popular %}checked{% endif %} >
Is Popular
</label>
</div>
</div>
<div class="form-group">
<label>Is Best Rated</label>
<div class="radio">
<label>
<input type="radio" name="is_best_rated" value="0" {% if not input.is_best_rated %}checked{% endif %} >
Is Not Best Rated
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="is_best_rated" value="1" {% if input.is_best_rated %}checked{% endif %} >
Is Best Rated
</label>
</div>
</div>
<!-- Uploaded Files -->
<input name="files" id="files" type="hidden"/>
<!-- Uploaded Files -->
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
<?php
namespace MyApp\Strategies;
use League\Route\Strategy\AbstractStrategy;
use League\Route\Strategy\StrategyInterface;
class CustomStrategy extends AbstractStrategy implements StrategyInterface {
/**
* Dispatch the controller, the return value of this method will bubble out and be
* returned by \League\Route\Dispatcher::dispatch, it does not require a response, however,
* beware that there is no output buffering by default in the router
*
* $controller can be one of three types but based on the type you can infer what the
* controller actually is:
* - string (controller is a named function)
* - array (controller is a class method [0 => ClassName, 1 => MethodName])
* - \Closure (controller is an anonymous function)
*
* @param string|array|\Closure $controller
* @param array $vars - named wildcard segments of the matched route
* @return mixed
*/
public function dispatch($controller, array $vars)
{
if (is_array($controller)) {
$controller = [
$this->container->get($controller[0]),
$controller[1]
];
}
$response = $this->container->call($controller, $vars);
return $this->determineResponse($response);
}
}
<?php
namespace MyApp\Controllers;
use Symfony\Component\HttpFoundation\Response as Response;
use Symfony\Component\HttpFoundation\Request as Request;
class DealController {
public function __construct()
{
$loader = new \Twig_Loader_Filesystem('templates');
$this->twig = new \Twig_Environment($loader);
$this->response = Response::create();
$this->request = Request::createFromGlobals();
}
public function create()
{
$this->response->setContent($this->twig->render('create.twig'));
return $this->response;
}
public function createAction($request, $response, $args)
{
echo '<pre>'; var_dump($request);
echo '<pre>'; var_dump($response);
echo '<pre>'; var_dump($args);
exit;
}
}
<?php
require 'vendor/autoload.php';
use MyApp\Strategies\CustomStrategy;
use Illuminate\Database\Capsule\Manager as Capsule;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// Routing
$router = new League\Route\RouteCollection;
$router->setStrategy(new CustomStrategy);
$router->addRoute('GET', '/admin/deals/create', '\MyApp\Controllers\DealController::create');
$router->addRoute('POST', '/admin/deals/create', '\MyApp\Controllers\DealController::createAction');
$dispatcher = $router->getDispatcher();
$request = Request::createFromGlobals();
$response = $dispatcher->dispatch($request->getMethod(), $request->getPathInfo());
$response->send();
@jishcem
Copy link
Author

jishcem commented Sep 8, 2015

Here is the error displayed -

Warning: array_map(): An error occurred while invoking the map callback in C:\laragon\www\asdasd\vendor\league\container\src\Container.php on line 495

( ! ) Fatal error: Uncaught exception 'RuntimeException' with message 'Cannot resolve argument [request], it should be provided within an array of arguments passed to [League\Container\Container::call], have a default value or be type hinted' in C:\laragon\www\asdasd\vendor\league\container\src\Container.php on line 488

( ! ) RuntimeException: Cannot resolve argument [request], it should be provided within an array of arguments passed to [League\Container\Container::call], have a default value or be type hinted in C:\laragon\www\asdasd\vendor\league\container\src\Container.php on line 488

This happens while the route $router->addRoute('POST', '/admin/deals/create', '\MyApp\Controllers\DealController::createAction');
is executed.

@philipobenito
Copy link

Your custom strategy is using the League\Container\Container::call method which attempts to resolve the arguments of the method it is invoking. The problem here is that your MyApp\Controllers\DealController::createAction just accepts $request and $response. If you were to type hint the request and response objects then this would work.

public function createAction(Request $request, Response $response, array $args = [])
{
    echo '<pre>'; var_dump($request);
    echo '<pre>'; var_dump($response);
    echo '<pre>'; var_dump($args);
    exit;
}

@jishcem
Copy link
Author

jishcem commented Sep 8, 2015

👍 It worked.

I used the RequestResponseStrategy in the CustomStrategy's dispatch method, and it worked as well 👍

Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment