I need feedback on my Bootstrap for the MVC architecture that I follow. I load the routes via yaml. Here is an example:
feed:
path: /{controller}/{action}{slash}
requirements:
id: "[1-9][0-9]*"
slash: "[/]{0,1}"
methods: [GET,POST]
#Explore Controller
explore:
path: /{controller}{slash}
requirements:
id: "[1-9][0-9]*"
slash: "[/]{0,1}"
methods: [GET,POST]
And here is my Bootstrap class:
class Bootstrap
{
public function __construct()
{
$request = Request::createFromGlobals();
$locator = new FileLocator(__DIR__ . '/../../../config');
// DI container
$container = new DependencyInjection\ContainerBuilder;
$loader = new DependencyInjection\Loader\YamlFileLoader($container, $locator);
$loader->load('config-development.yml');
$container->compile();
// routing
$loader = new Routing\Loader\YamlFileLoader($locator);
$context = new Routing\RequestContext();
$context->fromRequest($request);
$matcher = new Routing\Matcher\UrlMatcher(
$loader->load('routing.yml'),
$context
);
try{
$parameters = $matcher->match($request->getPathInfo());
foreach ($parameters as $key => $value) {
$request->attributes->set($key, $value);
}
$command = $request->getMethod() . $request->get('action');
$resource = "controller.{$request->get('controller')}";
$controller = $container->get($resource);
$data = $controller->{$command}($request);
}catch(\Error $e){
$data = [
'status'=>404,
'message'=>'Not found',
'info'=>$e->getMessage()
];
}catch(\Symfony\Component\Routing\Exception\MethodNotAllowedException $e){
$data = [
'status'=>404,
'message'=>'Not found',
'info'=>$e->getMessage()
];
}catch(ResourceNotFoundException $e){
$data = [
'status'=>404,
'message'=>'Not found',
'info'=>$e->getMessage()
];
}
if(is_array($data)){
$response = new JsonResponse($data);
}else{
$response = new Response($data);
}
//Set cors headers
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS,POST,PUT,DELETE');
$response->headers->set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->send();
}
I load the controllers and services via yaml. I'm interested if you would change anything and if you see any possible issues that this kind of structure might have.
I'm seeking for improvements in my code.
1 Answer 1
Disclaimer: I haven't really used YAMLFileLoader but the advice should apply for the sake of improving PHP code.
Catching Exceptions
I would consolidate the exception catching, since apparently the value of $data
is always the same (other than the fact that the info
value is assigned the exception message). Unless the goal is to only catch \Symfony\Component\Routing\Exception\MethodNotAllowedException
and ResourceNotFoundException
instances, why not just catch all Exception
instances? Something like this:
catch(\Throwable $e){
$data = [
'status'=>404,
'message'=>'Not found',
'info'=>$e->getMessage()
];
}
And for the sake of D.R.Y. code, you could abstract setting $data
in those exception handling blocks to a separate method that returns that array. Something like:
function GetFallbackDataForException(Throwable $e) {
return [
'status'=>404,
'message'=>'Not found',
'info'=>$e->getMessage()
];
}
I hadn't learned until testing out this code but an Error can be thrown and caught - I thought that was only possible with instances of Exception but both implement Throwable...ergo...
Method length
The method is quite long - especially considering it is a constructor. It would be advisable to break up the pieces into separate methods - e.g. one to create the request, one to take the return value from the request and send the response, etc. That way the constructor can be shorter as it calls those methods, plus those methods would hopefully lend themselves to unit testing each component of the process.
I considered suggesting that the foreach
to set attributes be replaced with a call to array_walk()
but that might require flipping the array keys and values, making a Callable out of the method, etc. all to save 1-2 lines...
-
\$\begingroup\$ Well not the kind of answer i would accept but if no body gives a better answer il accept your. Definitely some things i will include.Do you mind that i lay down my whole architecture and that you give feedback on it? \$\endgroup\$DaAmidza– DaAmidza2017年12月05日 21:16:54 +00:00Commented Dec 5, 2017 at 21:16
-
\$\begingroup\$ Hmm... "lay down" - does that mean adding more contents to your post? I guess as long as it isn't too much ... As you likely know, it is off-topic to add links to external sites but if you can add the core elements then that should suffice. P.S. my nickname is Nobody ;) \$\endgroup\$2017年12月05日 21:26:03 +00:00Commented Dec 5, 2017 at 21:26
-
\$\begingroup\$ Sorry i ment il write it down ahahha I'm not an native english speaker in my language it makes sense.... Don't get that part about nobody \$\endgroup\$DaAmidza– DaAmidza2017年12月05日 21:29:25 +00:00Commented Dec 5, 2017 at 21:29
-
1\$\begingroup\$ Oh you mean include it in your code? sure! And the nickname Nobody is a joke about using indefinite pronouns as proper nouns - e.g. the Not my job joke. \$\endgroup\$2017年12月05日 21:53:39 +00:00Commented Dec 5, 2017 at 21:53
-
\$\begingroup\$ hhaha good one.I like you man :D I'm writing it now \$\endgroup\$DaAmidza– DaAmidza2017年12月05日 22:20:34 +00:00Commented Dec 5, 2017 at 22:20
7.1
u can group multiple catch blocks: wiki.php.net/rfc/multiple-catch \$\endgroup\$Error
,\Symfony\Component\Routing\Exception\MethodNotAllowedException
andResourceNotFoundException
but not other Exceptions? \$\endgroup\$