# Controllers

In HivePress, controllers are PHP classes that are used to define URL routes and implement actions corresponding to them. For example, the `Listing` controller contains all the routes and actions related to listings (e.g. viewing, creating, updating and deleting).

### Creating controllers

If you are developing a HivePress [extension](/developer-docs/tutorials/create-a-custom-hivepress-extension.md) that requires custom URL routes, you should create a new controller. To do this, create a new `class-{extension-name}.php` file (use lowercase letters, numbers, and hyphens only) in the `includes/controllers` extension subdirectory and HivePress will load it automatically.

Then, define the controller PHP class. The class name should be based on the file name but with underscores instead of hyphens and no lowercase restriction (e.g. `Foo_Bar` class for the `class-foo-bar.php` file). Pick a name that is unique enough to avoid conflicts with other HivePress controllers.

```php
<?php
namespace HivePress\Controllers;

use HivePress\Helpers as hp;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

final class Foo_Bar extends Controller {
	public function __construct( $args = [] ) {
		$args = hp\merge_arrays(
			[
				'routes' => [
					// Define custom URL routes here.
				],
			],
			$args
		);

		parent::__construct( $args );
	}
	
	// Implement the route actions here.
}
```

### Adding routes

Each URL route is defined as an array of parameters in the controller's class constructor and can have the redirect and action functions implemented as the class methods.

{% hint style="info" %}
If you add new or change any of the existing URL routes, don't forget to refresh permalinks in the **Settings > Permalinks** section.
{% endhint %}

Once you add a custom route, you can get its URL anywhere by the route name:

```php
$url = hivepress()->router->get_url( 'my_custom_route' );
```

#### Template routes

These routes are used for redirecting and rendering the page [templates](/developer-docs/framework/templates.md). For example, when you visit the listing edit page, the `listing_edit_page` route checks if you have permission to edit this listing (or redirects you otherwise) and then renders the page template.

To define a new URL route, add an array of the following parameters:

* **title** - text used as the page title and [menu](/developer-docs/framework/menus.md) label;
* **path** - the relative route URL path (starts with a slash);
* **base** - the route name to inherit the `path` from;
* **redirect** - points to the route redirect function;
* **action** - points to the route action function.

The code below defines a route with the `/custom-route` URL that checks if the current user is logged in and, if so, redirects to the account page. If not, it renders the login page template.

```php
'custom_route' => [
	'title'    => 'Custom Title',
	'path'     => '/custom-route',
	'redirect' => [ $this, 'custom_redirect' ],
	'action'   => [ $this, 'custom_action' ],
],
```

The redirect and action functions can be implemented below the class constructor:

```php
public function custom_redirect() {

	// Perform checks and return the redirect URL.
	if ( is_user_logged_in() ) {
		return hivepress()->router->get_url( 'user_account_page' );
	}

	// Return false to prevent the redirect.
	return false;
}

public function custom_action() {

	// Return the rendered page template.
	return ( new HivePress\Blocks\Template(
		[
			'template' => 'user_login_page',
		]
	) )->render();
}
```

In the same way, you can add URL routes for any pages required for your extension.

#### REST API routes

These routes are used for receiving HTTP requests, performing specific actions and returning a JSON response. For example, when you edit a listing, the form sends a request to the `listing_update_action` route, updating the listing based on the field values.

To define a new REST API route, add an array with the following parameters:

* **path** - the relative route URL path (starts with a slash);
* **base** - the route name to inherit the `path` from;
* **method** - the accepted HTTP method (e.g. `GET`, `POST`);
* **action** - points to the route action function;
* **rest** - flag required for REST API routes.

The code below defines a REST API route with the `/wp-json/hivepress/v1/custom-route` URL, accepts requests via the `POST` method and calls the `custom_action` function.

```php
'custom_route' => [
	'path'   => '/custom-route',
	'method' => 'POST',
	'action' => [ $this, 'custom_action' ],
	'rest'   => true,
],
```

The action function can be implemented below the class constructor:

```php
public function custom_action( $request ) {
	// Perform some actions based on the request.

	if ( ! $request->get_param( 'custom_parameter' ) ) {

		// Return the error code and message.
		return hp\rest_error( 400, 'Custom error message' );
	}

	// Return the response code and data.
	return hp\rest_response(
		200,
		[
			'custom_result' => 123,
		]
	);
}
```

Similarly, you can add REST API routes for any actions required for your extension.

### Customizing routes

You can customize any of the available URL routes via the `hivepress/v1/routes` filter hook. For example, the code below changes the **Add Listing** page URL:

```php
add_filter(
	'hivepress/v1/routes',
	function( $routes ) {
		$routes['listing_submit_page']['path'] = '/custom-slug-here';

		return $routes;
	}
);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hivepress.io/developer-docs/framework/controllers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
