Skip to content
← Back to Functions
Code

Search Query Cleaner

Normalizes search input for database search without breaking quoted phrases or Unicode.

Function signature

ogCleanSearchQuery(query, max_length = 120, max_terms = 10)

Categories

  • Database Integrity

Parameters

queryRaw search query.max_lengthMaximum query length.max_termsMaximum number of parsed search terms.

Return value

Short public-safe status message.

  • query
  • terms
  • phrase_count

Compatibility

Existing function name and call order preserved; metadata signature corrected to source.

Minimum PHP version: 7.4

Security notes

Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Normalizes search input for display, fulltext search, and LIKE fallback use.
 *
 * @param string $query Raw search query.
 * @param int $max_length Maximum query length.
 * @param int $max_terms Maximum number of parsed search terms.
 * @return array Search query metadata.
 */
function ogCleanSearchQuery($query, $max_length = 120, $max_terms = 10) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	$query = trim((string)$query);
	$max_length = (int)$max_length;
	$max_terms = (int)$max_terms;

	if ($max_length < 20) {
		$max_length = 20;
	}
	if ($max_terms < 1) {
		$max_terms = 1;
	}

	$query = strip_tags($query);
	$query = preg_replace('/[\x00-\x1F\x7F]+/', ' ', $query);
	$query = preg_replace('/\s+/', ' ', $query);
	$query = trim($query);

	if (strlen($query) > $max_length) {
		$query = substr($query, 0, $max_length);
		$query = trim($query);
	}

	if (empty($query)) {
		$result['message'] = 'Search query is empty.';
		return $result;
	}

	preg_match_all('/"([^"]+)"|(\S+)/', $query, $matches);
	$terms = array();
	foreach ($matches[0] as $match) {
		$term = trim($match, ' "');
		$term = preg_replace('/[^\p{L}\p{N}_\- ]+/u', '', $term);
		$term = trim($term);
		if (!empty($term) && !in_array($term, $terms, true)) {
			$terms[] = $term;
		}
		if (count($terms) >= $max_terms) {
			break;
		}
	}

	if (empty($terms)) {
		$result['message'] = 'Search query does not contain usable terms.';
		return $result;
	}

	$result['success'] = true;
	$result['message'] = 'Search query cleaned.';
	$result['data'] = array(
		'display_query' => $query,
		'terms' => $terms,
		'fulltext_query' => implode(' ', $terms),
		'like_terms' => $terms
	);

	return $result;
}