How do I define multiple routes for one request in Silex? - php

Is there a way in Silex to define multiple routes for one request. I need to be able to define two routes for one page (both routes takes to the same page). Here's my current controller:
$app->get('/digital-agency', function() use ($app) {
return $app['twig']->render('digital_agency.html', $data);
});
It works when I duplicate the function like this:
$app->get('/digital-agency', function() use ($app) {
return $app['twig']->render('digital_agency.html', $data);
});
$app->get('/agencia-digital', function() use ($app) {
return $app['twig']->render('digital_agency.html', $data);
});
So, any idea of a more clean way to do it?

You can save the closure to a variable and pass that to both routes:
$digital_agency = function() use ($app) {
return $app['twig']->render('digital_agency.html', $data);
};
$app->get('/digital-agency', $digital_agency);
$app->get('/agencia-digital', $digital_agency);

You can also use the assert method to match certain expressions.
$app->get('/{section}', function() use ($app) {
return $app['twig']->render('digital_agency.html', $data);
})
->assert('section', 'digital-agency|agencia-digital');

Related

How can you create wildcard routes on Lumen?

Let's say I have a controller called TeamsController. Controller has following method, that returns all teams user has access to.
public function findAll(Request $request): JsonResponse
{
//...
}
Then I have bunch of other controllers with the same method. I would like to create a single route, that would work for all controllers, so I would not need to add a line for each controller every time I create a new controller.
I am unable to catch the controller name from URI. This is what I have tried.
$router->group(['middleware' => 'jwt.auth'], function () use ($router) {
// This works
//$router->get('teams', 'TeamsController#findAll');
// This just returns TeamsController#findAll string as a response
$router->get('{resource}', function ($resource) {
return ucfirst($resource) . 'Controller#findAll';
});
});
You return a string instead of calling a controller action:
I believe Laravel loads the controllers this way (not tested)
$router->group(['middleware' => 'jwt.auth'], function () use ($router) {
$router->get('{resource}', function ($resource) {
$app = app();
$controller = $app->make('\App\Http\Controllers\'. ucfirst($resource) . 'Controller');
return $controller->callAction('findAll', $parameters = array());
});
});
But again, I don't really think it's a good idea.

Laravel, pass variable to view

I have a doubt. I have been checking laracasts and they show some examples of passing variable(s) from router to a view:
Route::get('about', function() {
$people = ['Eduardo', 'Paola', 'Chancho'];
return view('about')->with('people', $people);
});
Route::get('about', function() {
$people = ['Eduardo', 'Paola', 'Carlos'];
return view('about')->withPeople($people);
});
The second example, I am not sure how Laravel handle it. I know it works I have test it, but which pattern they use? why is it possible to handle a dynamic variable.
Thanks in advance for your help!
The second one is handled by Laravel through php's __call magic method. This method redirects all methods that start with 'with' to the with method through this code in the Illuminate\View\View class:
public function __call($method, $parameters)
{
if (Str::startsWith($method, 'with')) {
return $this->with(Str::snake(substr($method, 4)), $parameters[0]);
}
throw new BadMethodCallException("Method [$method] does not exist on view.");
}
As you can see if the method starts with 'with' (Str::startsWith($method, 'with'), Laravel redirects it to the with method return $this->with by taking the first param as the string that follows 'with' Str::snake(substr($method, 4)) and the second param as the first param that was passed $parameters[0]
Hope this helps!
Try this to pass data in view
Route::get('about', function() {
$data['people'] = ['Eduardo', 'Paola', 'Chancho'];
return view('about')->withdata($data);
});
Try this, it works.
Route::get('about', function() {
$people = ['Eduardo', 'Paola', 'Chancho'];
return view('about',compact('people'));
});

PHP Silex routing localization

starting with Silex.
Say I want a localised site where all routes have to start with /{_locale} and don't fancy repeating myself as :
$app->match('/{_locale}/foo', function() use ($app) {
return $app['twig']->render('foo.twig');
})
->assert('_locale', implode('|', $app['languages.available']))
->value('_locale', $app['locale.default'])
->bind('foo');
$app->match('/{_locale}/bar', function() use ($app) {
return $app['twig']->render('bar.twig');
})
->assert('_locale', implode('|', $app['languages.available']))
->value('_locale', $app['locale.default'])
->bind('bar');
Ideally, I'd like to create a base route that would match the locale and subclass it in some way but couldn't figure out by myself how to trigger that in an elegant way.
I think you can delegate the local detection with mount function:
You mount a route for each local you want to support, but they redirect to the same controller:
$app->mount('/en/', new MyControllerProvider('en'));
$app->mount('/fr/', new MyControllerProvider('fr'));
$app->mount('/de/', new MyControllerProvider('de'));
And now the local can be an attribute of your controller:
class MyControllerProvider implements ControllerProviderInterface {
private $_locale;
public function __construct($_locale) {
$this->_locale = $_locale;
}
public function connect(Application $app) {
$controler = $app['controllers_factory'];
$controler->match('/foo', function() use ($app) {
return $app['twig']->render('foo.twig');
})
->bind('foo');
$controler->match('/bar', function() use ($app) {
return $app['twig']->render('bar.twig');
})
->bind('bar');
return $controler;
}
}

calling another route for the return value

hello I am new to silex and what I try to do basically is
I have one controller that uses curl to fetch something from another server. Then I have a different route where I want to show something specific from that value(JSON) returned.
I thought of using something like
$app->get('books', function() use ($app) {
$content = $app->get('overview/books/');
$content = json_decode($content);
return ... ;
})
$app->get('overview/books', function() use ($app) {
// do the curl operation and return
})
but obviously that doesn't return what I want.. How can I solve this?
You should put your json-getting code in a service and use that in both controllers.
First, you should create a class that will contain all your relevant code:
class JsonFetcher
{
public function fetch()
{ /* your code here */ }
}
then register it as a service:
$app["json-fetcher"] = $app->share(function () {
return new JsonFetcher();
});
Then use it in your controller:
$app->get("books", function () use ($app) {
$fetcher = $app["json-fetcher"];
$json = $fetcher->fetch();
// your code here
});
Edit:
If your service would be a one-method class, and it has no dependencies, you may simply register a function as a service like this:
$app["json-fetcher"] = $app->share($app->protect(function () {
//fetch and return json
}));
You can read about share and protect in the Pimple docs.

How to prevent including everything into one file?

I'm going to use Slim Framework. The, it seems that it is going to be everything in one single file. I don't want PHP to compile everything. How can I split them?
For example I have
$app->get('/articles/:id', function ($id) use ($app) { })
$app->get('/profiles/:id', function ($id) use ($app) { })
$app->get('/messages/:id', function ($id) use ($app) { })
$app->get('/articles', function ($id) use ($app) { })
$app->get('/search/:foo', function ($id) use ($app) { })
$app->delete('/message/:id', function ($id) use ($app) { })
Should I put include into {} so that only one file be included?
I think this can be a good solution for code comprehension. Slim is a micro-framework, so there is no real file structure, this leaves you free to do almost as you want.
You can read this article for more informations about how to organize your Slim file structure.
I take a similar approach but using group:
index.php
require '../Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
require 'routes/articles.php';
$app->run();
routes/articles.php
$app->group('/articles', function () use ($app) {
$app->get('/:foo', function($foo) use ($app) {
...
});
$app->get('/:foo/:bar', function($foo, $bar) use ($app) {
echo 'Info about all routes';
});
});

Categories