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';
});
});
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 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.
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;
}
}
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.
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');