Skip to content
View as Markdown

Routing

FluentCRM Core Intermediate

FluentCRM's router is available via the fluentcrm_loaded action. All routes you register are served under /wp-json/fluent-crm/v2/.

Registering Routes

Hook into fluentcrm_loaded to access the $app->router:

php
add_action('fluentcrm_loaded', function ($app) {
    $app->router->get('/my-endpoint', 'MyPlugin\Controllers\MyController@index');
});

This registers a GET endpoint at /wp-json/fluent-crm/v2/my-endpoint.

HTTP Methods

The router supports all standard HTTP verbs:

php
$router->get($uri, $callback);
$router->post($uri, $callback);
$router->put($uri, $callback);
$router->patch($uri, $callback);
$router->delete($uri, $callback);
$router->any($uri, $callback);   // responds to all HTTP methods

TIP

FluentCRM's JavaScript REST client sends PUT, PATCH, and DELETE as POST requests with an X-HTTP-Method-Override header. The framework handles this automatically.

Route Callbacks

Callbacks can be a Controller@method string or a closure:

php
// Controller string (recommended)
$router->get('/items', 'MyPlugin\Controllers\ItemController@index');

// Closure
$router->get('/ping', function () {
    return ['status' => 'ok'];
});

Route Groups

Group routes that share a prefix, policy, or namespace:

php
add_action('fluentcrm_loaded', function ($app) {
    $app->router
        ->prefix('my-plugin')
        ->namespace('MyPlugin\Controllers')
        ->withPolicy('MyPlugin\Policies\MyPolicy')
        ->group(function ($router) {
            $router->get('/', 'ItemController@index');         // GET  /my-plugin/
            $router->get('/items', 'ItemController@list');      // GET  /my-plugin/items
            $router->post('/items', 'ItemController@create');   // POST /my-plugin/items
            $router->put('/items/{id}', 'ItemController@update'); // PUT  /my-plugin/items/{id}
            $router->delete('/items/{id}', 'ItemController@delete'); // DELETE /my-plugin/items/{id}
        });
});

Group Methods

MethodDescription
prefix($prefix)Prepends a URL prefix to all routes in the group
namespace($ns)Sets the controller namespace so you can use short class names
withPolicy($class)Applies a policy class for authorization (see Policies)
group($callback)Defines the route group; receives $router as argument

All group methods are optional and chainable. You can register routes without a group:

php
$app->router->post('/my-endpoint', 'MyPlugin\Controllers\MyController@create');

Route Parameters

Define dynamic segments using {param} syntax:

php
$router->get('/contacts/{id}', 'ContactController@show');

Parameters are passed as arguments to the controller method:

php
public function show($id)
{
    $contact = Subscriber::findOrFail($id);
    return $this->sendSuccess(['contact' => $contact]);
}

Parameter Constraints

Chain constraint methods to validate parameter formats:

MethodAccepts
int($param)Integers only
alpha($param)Alphabetic characters only
alphaNum($param)Alphanumeric characters
alphaNumDash($param)Alphanumeric, dashes, and underscores
where($param, $regex)Custom regex pattern
php
// Single constraint
$router->get('/contacts/{id}', 'ContactController@show')->int('id');

// Multiple constraints
$router->get('/contacts/{id}/{slug}', 'ContactController@show')
    ->int('id')
    ->alpha('slug');

// Custom regex
$router->get('/reports/{type}', 'ReportController@show')
    ->where('type', '[a-z_]+');

Without Groups

Routes registered without prefix() or group() are available directly under the FluentCRM base URL:

php
add_action('fluentcrm_loaded', function ($app) {
    $app->router->get('/health-check', function () {
        return ['status' => 'ok', 'timestamp' => current_time('mysql')];
    });
});
// Accessible at: /wp-json/fluent-crm/v2/health-check

Nested Groups

You can nest groups for more complex URL structures:

php
$app->router
    ->prefix('my-plugin')
    ->withPolicy('MyPlugin\Policies\MyPolicy')
    ->group(function ($router) {
        $router->get('/', 'MyPlugin\Controllers\DashboardController@index');

        $router->prefix('reports')->group(function ($router) {
            $router->get('/', 'MyPlugin\Controllers\ReportController@index');
            $router->get('/{id}', 'MyPlugin\Controllers\ReportController@show')->int('id');
        });
    });
// Routes:
//   GET /my-plugin/
//   GET /my-plugin/reports/
//   GET /my-plugin/reports/{id}

Source: vendor/wpfluent/framework/src/WPFluent/Http/Router.php, vendor/wpfluent/framework/src/WPFluent/Http/Route.php