Lesson 4. Working with Ajax in the autocomplete posts plugin

Lesson 4. Working with Ajax in the autocomplete posts plugin

Let’s continue developing our post autocomplete plugin. Today we’ll explore Ajax functionality in the WordPress engine—what, how, and where to hook into it, how to test the logic without a frontend, and what requests should be sent to the server.

Let’s move to the code. Open our only project file so far: “/wp-content/plugins/wp-post-autocomplete/wp-post-autocomplete.php”. Place the cursor inside the constructor of the `WpPostAutocomplete` class and add the following lines:

add_action('wp_ajax_autocomplete', array($this, 'ajax_autocomplete'));
add_action('wp_ajax_nopriv_autocomplete', array($this, 'ajax_autocomplete'));

In the snippet above, we used WordPress’s `add_action()` function to register our custom hook for handling Ajax requests. Note the naming convention:
- `wp_ajax_...` — for logged-in users.
- `wp_ajax_nopriv_...` — for guests (non-logged-in users).

And the suffix (in our case `autocomplete`) should match the `action` parameter sent via POST/GET from the frontend. The hooks will look like this:

add_action('wp_ajax_{autocomplete}');
add_action('wp_ajax_nopriv_{autocomplete}');

Where `autocomplete` is the same value passed through the `wp_localize_script()` function (see the previous lesson).

The second parameter of our `add_action()` call is the method that will handle the Ajax request. Here is the implementation of the `ajax_autocomplete()` method:

public function ajax_autocomplete()
{
	try
	{
		$Posts = get_posts([
			'posts_per_page' => 10,
			's' => esc_sql(filter_input(INPUT_POST, 'text', FILTER_SANITIZE_STRING)),
		]);

		$array = [];
		foreach($Posts as $Post)
		{
			$array[] = [
				'title' => $Post -> post_title,
				'link' => get_permalink($Post -> ID),
			];
		}

		wp_send_json_success($array);			
	}
	catch (Exception $ex)
	{
		wp_send_json_error(array(
			'message' => 'Failed to process request',
		));
	}
}

Let’s break it down:
- Retrieve the search text using:

filter_input(INPUT_POST, 'text', FILTER_SANITIZE_STRING)

- Use the `get_posts()` core function to fetch up to 10 matching posts, searching both titles and content:

$Posts = get_posts([
	'posts_per_page' => 10,
	's' => esc_sql(filter_input(INPUT_POST, 'text', FILTER_SANITIZE_STRING)),
]);

- Prepare an array of results with titles and links:

$array = [];
foreach($Posts as $Post)
{
	$array[] = [
		'title' => $Post -> post_title,
		'link' => get_permalink($Post -> ID),
	];
}

- Send the data back as a JSON success response:

wp_send_json_success($array);

- In case of an exception, send a JSON error:

wp_send_json_error(array(
	'message' => 'Failed to process request',
));

You could also extend this to handle cases where no results are found, but since our plugin is fairly simple, we’ll skip that for now.

Testing

If the frontend had already been implemented, we could test with a form and the browser’s developer tools. However, since that’s coming in the next lesson, we’ll use the terminal and `curl`. If `curl` is not installed, install it and run the following commands to test:

curl -d "action=autocomplete&text=this" -X POST http://wordpress.l/wp-admin/admin-ajax.php

Or, for pretty-printed JSON output:

curl -d "action=autocomplete&text=это" -X POST http://wordpress.l/wp-admin/admin-ajax.php | json_pp

The difference between the two is the use of `json_pp`, a utility to format the JSON response nicely.


Here, “http://wordpress.l/” is the address of the WordPress site receiving the request.

That’s it! You can find the code for this lesson in our GitHub repository via this link.

Full lesson list

Posts on similar topics

Are you having problems with your WordPress site? Do you need additional functionality? A custom plugin or a new page?
Then write to me via the feedback form, and I will try to help you.

Write a comment

Your email address will not be published. Required fields are marked *