COUNT() without GROUP BY will always return a single row. In your query the result set will be a single row with a single column -- and the count can be expected to be an integer which is 0 or greater.
You have several available approaches for your MATCH AGAINST query.
Query builder methods:
public function countViaMatchAgainst(string $search): int
{
return $this->db->where(
sprintf(
'MATCH (title, description) AGAINST (%s IN BOOLEAN MODE)',
$this->db->escape("+$search*")
)
)
->count_all_results('post');
}
Execute raw SQL with a parameterized query.
public function countViaMatchAgainst(string $search): int
{
$sql = <<<SQL
SELECT COUNT(*) totalCount
FROM post
WHERE MATCH (title, description) AGAINST (? IN BOOLEAN MODE)
SQL;
return $this->db->query($sql, "+$search*")->row('totalCount');
}
I do not endorse returning a payload with rows of column data unless you actually intend to use it. This means that you should NOT be removing COUNT(*) from your raw query using num_rows().
Neither of the above scripts will return any row/column values; only the count integer will be returned.