I want to create a ¨dynamic¨ route group in Slim framework but I´m getting
Warning: Missing argument 1 for {closure}() i
this is my code:
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
$app->group('/:segment1/:segment2', function ($segment1, $segment2) use ($app) {
$app->map('/', function () use ($app) {
})->via('GET', 'POST');
$app->map('/:id', function ($id) use ($app) {
})->via('GET', 'PUT', 'DELETE');
});
$app->run();
If i change:
$app->group('/:segment1/:segment2', function ($segment1, $segment2) use ($app)
to:
$app->group('/segment1/segment2', function () use ($app)
it starts working but I need those segments to be dynamic. how can I do that?
You have to add group parameters to their child routes function:
$app->group('/:segment1/:segment2', function () use ($app) {
$app->map('/', function ($segment1, $segment2) use ($app) {
// something
})->via('GET', 'POST');
$app->map('/:id', function ($segment1, $segment2, $id) use ($app) {
// something
})->via('GET', 'PUT', 'DELETE');
});
Also look at this issue.
Related
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.
I don't find my error. I can't access of the session variable.
I try this:
$app = new Silex\Application();
$app['debug']=true;
$app->register(new Silex\Provider\SessionServiceProvider());
$app->get("/", function(Request $request) use($app)
{
return $app["session"]->get('is_admin');
});
$app->run();
use Symfony\Component\HttpFoundation\Request;
$app->before(function (Request $request, Silex\Application $app){
$app['session']->set('is_admin', true);
});
I did this to solve the problem (thank you Stepashka):
$app = new Silex\Application();
$app['debug']=true;
use Silex\Provider\SessionServiceProvider;
$app->register(new SessionServiceProvider());
$app->before(function() use ($app){
$app['session']->start();
$app['session']->set('is_admin', "dfghjdf");
});
$app->get("/", function() use($app)
{
return print_r($app['session']->get('is_admin'));
});
$app->run();
Thing is that your providers are not initialised before you do $app->run(). You should assign the value either in controller or at least after $app->run().
There also is a Middleware feature in Silex, so you can do your assignment like this:
$app->before(function (Request $request, Application $app) {
$app['session']->set('is_admin', true);
});
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;
}
}
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');
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';
});
});