I don't know the terminology for my problem so I am asking here for the solution since I can't find it by searching.
I am making a simple rest API where I have specified my Routes.php
In my index.php I call the routes:
$routes = new Routes();
$routes->getRoutes();
app/Routes.php
<?php
/* All default application routes go here. Flow specific routes are implemented in the specific flows directory. */
class Routes extends Controller
{
function __construct()
{
/* Inherit stuff from Controller */
parent::__construct();
}
public function getRoutes()
{
/* Routes */
$this->app->group('/api', function () use ($app)
{
$this->app->get('/cron/run', 'Cron:run');
});
}
}
Now I want it to support standalone "modules".
So we add a module and its routes in here:
app/MyModule/Routes.php
Imagine multiple modules in here with their own routes.
Here is the problem.
How can I add routes in all these modules to be included automatically in the application routes?
I do not want to override.
I am using Slim PHP framework if that helps.
You simply need to instantiate each module's Routes class in turn within your bootstrapping process (i.e. before you call run()).
As long as each module defines a unique string for the group's URL (/api in your example), then they won't clash.
Related
I have an api and some routes are public some need to be protected via auth. I want to have them in one controller class as they are related. I can extend the controller and have beforeRoute function but it runs for any route that is in that controller. is it possible to add a middleware only to specific routes? I'm a js dev and in express I can just pass middleware functions for any route, even multiple middlewares.
class Clanky /*extends \controllers\ProtectedController */{
public function post_novy_clanek(\Base $base) {
//needs to be protected
}
public function get_clanky(\Base $base) {
}
public function get_clanek(\base $base) {
}
public function get_kategorie(\Base $base) {
}
}
PHP is new to me, I just want to know how I can implement the concepts I know from other languages and frameworks in this weird fatfree framework. Thanks.
Use can use f3-access plugin for that purpose https://github.com/xfra35/f3-access
Fatfree is not opinionated about how to do this.. other options to solve this ask might be:
Use php8 attributes on the method and check these in beforeroute.
Consider an own named route naming schema like #admin_routename and apply checking auth in beforeroute
Use f3-middleware plugin and add auth there
Extend an other admin controller that provides auth in beforeroute or use a trait.
I'm setting up a small application with Ubiquity Framework in PHP, and I'm trying to disable the default routing system (controller/action/parameters).
The routing system is based on annotations (documented here).
I have a controller with a few routes, which works (don't forget to reset the router cache).
namespace controllers;
class FooController extends ControllerBase
{
/**
* #get("foo")
*/
public function index()
{
echo "I'm on /foo";
}
/**
* #get("bar/{p}")
*/
public function bar($p='default p')
{
echo "I'm on bar/".$p;
}
}
the addresses /foo, /bar and /bar/xxx are accessible, but I would like to disable the default routing system that allows access to the action of an existing controller (without route).
I want to disable the following urls:
/FooController
/FooController/index
/FooController/bar
/FooController/bar/xxx
I didn't find my answer in the doc.
I know the framework is not known (I discovered it through phpbenchmarks website), but the routing system is pretty classic, and it's still php.
If you have any ideas....
Versions:
php 7.3
Ubiquity 2.2.0
I found a solution, indirectly in the doc.
The priority attribute of a route allows you to assign the order in which it will be defined (and therefore requested).
To disable the call of actions on existing controllers, it is therefore possible to define a generic route in the last position returning a 404 error.
namespace controllers;
use Ubiquity\utils\http\UResponse;
class FooController extends ControllerBase
{
...
/**
* #route("{url}","priority"=>-1000)
*/
public function route404($url)
{
UResponse::setResponseCode(404);
echo "Page {$url} not found!";
}
}
If we still want to activate some controllers (the Admin part for example), we must add the requirements attribute, which allows to specify a regex.
namespace controllers;
use Ubiquity\utils\http\UResponse;
class FooController extends ControllerBase
{
...
/**
* #route("{url}","priority"=>-1000,"requirements"=>["url"=>"(?!(a|A)dmin).*?"])
*/
public function route404($url)
{
UResponse::setResponseCode(404);
echo "Page {$url} not found!";
}
}
In this case, the only routes accessible are those defined with annotations + those corresponding to the actions of the Admin controller
With routing problems, routing solution.
I have been declaring all the routes for my application inside web.php , but it is now getting quite large. I find that I am losing a lot of time shifting between web.php and each controller and this is hurting productivity.
I feel like it would be better to define routes inside of the controller, perhaps ideally delegating some URL to a controller and then allowing the controller to handle the "sub routes" since this would allow me to use inheritance when I have two similar controllers with similar routes.
It is not possible given how laravel works. Every request is passed onto router to find its designated spot viz. the controller with the method. If it fails to find the route within the router, it just throws the exception. So the request never reaches any controller if the route is not found. It was possible in earlier versions on Symphony where you would configure the route in the comment of a particular controller method.
Sadly with laravel it works how it works.
But for me, I just like to have the routes in a separate file.
Alternate solution, easier way to sort all the routes.
You can move your route registration into controllers if you use static methods for this. The code below is checked in Laravel 7
In web.php
use App\Http\Controllers\MyController;
.....
MyController::registerRoutes('myprefix');
In MyController.php
(I use here additional static methods from the ancestor controller also posted below)
use Illuminate\Support\Facades\Route;
.....
class MyController extends Controller {
......
static public function registerRoutes($prefix)
{
Route::group(['prefix' => $prefix], function () {
Route::any("/foo/{$id}", self::selfRouteName("fooAction"));
Route::resource($prefix, self::selfQualifiedPath());
}
public function fooAction($id)
{
........
}
In Controller.php
class Controller extends BaseController {
....
protected static function selfAction($actionName, $parameters = [], $absolute = false)
{
return action([static::class, $actionName], $parameters, $absolute);
}
protected static function selfQualifiedPath()
{
return "\\".static::class;
}
protected static function selfRouteName($actionName)
{
//classic string syntax return "\\".static::class."#".$actionName;
// using tuple syntax for clarity
return [static::class, $actionName];
}
}
selfAction mentioned here is not related to your question, but mentioned just because it allows making correct urls for actions either by controller itself or any class using it. This approach helps making action-related activity closer to the controller and avoiding manual url-making. I even prefer making specific functions per action, so for example for fooAction
static public function fooActionUrl($id)
{
return self::selfAction('foo', ['id' => $id]);
}
Passing prefix into registerRoutes makes controller even portable in a sense, so allows inserting it into another site with a different prefix in case of conflict
I am using CAKEPHP for creating my Application apis,
Currently I have few controllers in `
app/controllers/{UsersController, AdminController, StoresController}
` etc
I am accessing my controllers as //users/
However I want to add versioning system in cakephp
Something like
<ip>/<foldername>/v1/users/<action>
<ip>/<foldername>/v2/users/<action>
I tried creating a Folder inside Controllers/ as Controllers/v1/UsersController.php
However I am unable to access it.
How can i configure my routes
I'm quite confused about CakePHP version you are using (you tagged cakephp-3.0, and folder structure you used in question resembles that of 2.x), but both 2.x and 3.x versions have common concept called Prefix Routing, which is what you should use here. Below example assumes CakePHP 3.x:
You need to create directories (v1, v2) inside your Controller directory. Next, create individual controllers in that folder, remembering that namespace should also reflect this structure:
<?php
namespace App\Controller\v1;
use App\Controller\AppController;
class UsersController extends AppController {
//...
}
Final step is to configure routing in your routes.php. Example below:
Router::prefix("v1", function (RouteBuilder $routes){
$routes->fallbacks(DashedRoute::class);
});
More info can be found here:
Prefix Routing
For CakePHP 2.x things are little different:
In v2.x, you should NOT create folders inside Controller directory. All prefixed and unprefixed functions will reside in single controllers, eg.
class UsersController extends AppController {
/**
* Unprefixed function
*/
public function login(){
}
/**
* Prefix v1
*/
public function v1_login(){
}
/**
* Prefix v2
*/
public function v2_login(){
}
}
Next, you need to configure these prefixes in your app/Config/core.php file like so:
Configure::write('Routing.prefixes', array('v1', 'v2'));
After this, you should be able to access your actions with v1 and v2 prefixes, eg yourapp/v1/users/login will map to UsersController::v1_login() and yourapp/v2/users/login to UsersController::v2_login().
More info in documentation for 2.x: Prefix Routing v2.x
I'm using hostname routes to direct requests to the appropriate modules, so clients.xxx.com routes to the clients module. Now I'm trying to create some phpunit tests and I'm not sure how to dispatch to the proper module?
I've circumvented this issue by adding the default routes onto the router in the test case. Say you wanted to test the foo module, index controller, index action.
/**
* #test
*/
public function indexAction()
{
$frontController = $this->getFrontController();
$router = $frontController->getRouter();
$router->addDefaultRoutes();
$this->dispatch('foo/index/index');
}
You could add the default routes in the setup method to prevent repeating the code.