All routes for your web interface should be defined into the routes/web.php file located at project root. You can define custom and WordPress routes. These routes are assigned to the web middleware group, which provides the WordPress conditions bindings and allows you to write routes pointing to WordPress templates.

We recommend developers to no longer define routes in their theme.

The most basic route accepts a URI or a WordPress condition and a Closure:

If you're using the WordPress Customizer, you might want to use the any() method because the Customizer is fetching your pages through a HTTP POST request. So if you're using only the Route::get() method for your theme, you get a blank screen when working with the Customizer.

Finally, there is also the Route::match() method that lets you define which HTTP verbs you want to listen to:

If you are defining a route that redirects to another URI, you may use the Route::redirect method. This method provides a convenient shortcut so that you do not have to define a full route or controller for performing a simple redirect:

If your route only needs to return a view, you may use the Route::view method. Like the redirect method, this method provides a simple shortcut so that you do not have to define a full route or controller. The view method accepts a URI as its first argument and a view name as its second argument. In addition, you may provide an array of data to pass to the view as an optional third argument:

Route parameters are always encased within {} braces and should consist of alphabetic characters, and may not contain a - character. Instead of using the - character, use an underscore _. Route parameters are injected into route callbacks / controllers based on their order - the names of the callback / controller arguments do not matter.

You may constrain the format of your route parameters using the where() method on a route instance. The where() method accepts the name of the parameter and a regular expression defining how the parameter should be constrained:

If you would like a route parameter to always be constrained by a given regular expression, you may use the pattern() method. You should define these patterns in the boot() method of your RouteServiceProvider stored in the app/Providers directory:

If the named route defines parameters, you may pass the parameters as the second argument to the route() function. The given parameters will automatically be inserted into the URL in their correct positions:

If you would like to determine if the current request was routed to a given named route, you may use the named() method on a Route instance. For example, you may check the current route name from a route middleware:

Route groups allow you to share route attributes, such as middleware or namespaces, across a large number of routes without needing to define those attributes on each individual route. Shared attributes are specified in an array format as the first parameter to the Route::group method.

Remember, by default, the RouteServiceProvider includes your route files within a namespace group, allowing you to register controller routes without specifying the full App\Http\Controllers namespace prefix. So, you only need to specify the portion of the namespace that comes after the base App\Http\Controllers namespace.

The name() method may be used to prefix each route name in the group with a given string. For example, you may want to prefix all of the grouped route's names with admin. The given string is prefixed to the route name exactly as it is specified, so we will be sure to provide the trailing . character in the prefix:

When injecting a model ID to a route or controller action, you will often query to retrieve the model that corresponds to that ID. The routing package route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire User model instance that matches the given ID.

Since the $user variable is type-hinted as the App\User Eloquent model and the variable name matches the {user} URI segment, the framework will automatically inject the model instance that has an ID matching the corresponding value from the request URI. If a matching model instance is not found in the database, a 404 HTTP response will automatically be generated.

Make sure to include the \Illuminate\Routing\Middleware\SubstituteBindings::class in your HTTP Kernel class.

To register an explicit binding, use the router's model() method to specify the class for a given parameter. You should define your explicit model bindings in the boot() method of the RouteServiceProvider class:

Since we have bound all {user} parameters to the App\User model, a User instance will be injected into the route. So, for example, a request to profile/1 will inject the User instance from the database which has an ID of 1.

If a matching model instance is not found in the database, a 404 HTTP response will be automatically generated.

If you wish to use your own resolution logic, you may use the Route::bind() method. The Closure you pass to the bind method will receive the value of the URI segment and should return the instance of the class that should be injected into the route:

Using the Route::fallback() method, you may define a route that will be executed when no other route matches the incoming request. Typically, unhandled requests will automatically render a "404" page via your application's exception handler. However, since you may define the fallback route within your routes/web.php file, all middleware in the web middleware group will apply to the route. Of course, you are free to add additional middleware to this route as needed:

Route::fallback(function () {
//
});

The fallback route should always be the last route defined by your application.

We recommend to use the fallback() route instead of the 404 condition provided by WordPress. The 404 route is a catch everything route and may override some of your custom routes.

The Themosis framework provides multiple locations in order to define application routes. Generally, you'll define routes for the web interface into the web.php file stored into the routes directory at project's root.

You can also define application routes from a plugin routes.php file.

If you define a route from a plugin similar to one of your application routes, the route coming from the plugin will have precedence over the one declared into the root web.php file.

Finally we also authorise routes definitions from the theme's routes.php file. Any route defined into the theme has precedence over plugin routes and application routes.

We do not recommend to write routes inside your theme but in a scenario where you need to override a route defined by a plugin, you can use the theme's routes.php file to define such route.

Each WordPress route works by providing a condition instead of a URI. You can find below a list of "condition" terms the framework provides based on WordPress core functions. For example, the condition home refers to the WordPress is_home() function, the page condition to the is_page() function and so on...

Condition terms are defined in the config/app.php file. Feel free to add any custom condition to your project.

Before digging into the routing API, remember that when you're developing with the Themosis framework, you're still doing WordPress development. So in WordPress, in order for a route to work, the data has to exists first (usually by posting content from the WordPress administration).

Please note that routes are read from top to bottom. It may happen that 2 different routes listen to the same URI. For example: a post-type-archive and an archive routes. The router is always returning the first match. As a best practice, we recommend you to put specific routes (in this case, the post-type-archive) on top of your routes.php file and generic routes at the bottom or below (in this case the archive route).

In the WordPress world, there are 2 routes available for the home page of your website/application:

The home route

The front route

1-The home route

This route is mapped to core WordPress function is_home(). Historically we could say it handled the home page, now it's the blog main page. The home route handles the request to the URI that lists the most recent published posts.

So there are 2 cases:

If your website is mainly a blog, you can keep the default behaviour and use it as is for the home page and it listens to requests made to this URI /

If your home page is not a main blog page, a custom WordPress page has been defined to display the list of most recent posts, so the home route won't handle requests made to / URI but perhaps to a /blog URI instead. In order for this scenario to work, you must define a custom page from the WordPress administration -> Settings -> Reading panel.

Here's an example of a route listening to the WordPress home page:

Route::any('home', function() {
return 'Hello World!';
});

2-The front route

The front route listens to requests made on your application home page only if you define a front page in the WordPress administration -> Settings -> Reading panel. Once a custom page is defined, this route condition listens to the / URI:

Route::any('front', function() {
return 'Hello World!';
});

Once the front page is defined, the previous home condition is no longer used to listen to the / URI.

The page route condition is listening to requests made to any WordPress page posts. Meaning that in order to work, as previously explained, some data has to be registered first from the WordPress administration.

The page condition is mapped to the core function is_page(). So by default, the page route without parameters is triggered for all existing WordPress pages URI. Here is an example:

The page route without parameters is a generic route and it is best to register it at the bottom of your routes.php file.

Route to a specific page

Imagine we have a registered WordPress page with a title of Contact. WordPress saves the page post with a post name of contact and makes it accessible at the /contact URI based on its default permalink structure.

In order to listen to requests made on this contact page, you may write this route:

The key is the WordPress conditional tag function signature and the value can be a single string or an array of string conditions. The new API lets you provide multiple names for your condition.

In order to extend available conditions, simply add the signature of your custom conditional tag function and a term. For example, we can now add WooCommerce conditional tags like is_shop or is_product this way: