0
votes

I have the problem that the backend users can set a word with a "­" character, for example something like "Test&shy ;labor". If someone uses the frontend search with the word "Testlabor" no match will be found. In the extbase repository I used this:

$query->like('name', '%' . $searchWord . '%')

I can change that to something like this:

$query->statement("SELECT * FROM table WHERE hidden = 0 AND REPLACE(name,'­', '') LIKE '%$searchWord%'")

Then the word will be found but I have to check all the things the framework normally does, like check if it's hidden and deleted and more complicated, if the result is in the right site tree. Now I just get everything that matches the searchword.

Is there a better way to search for words which have "­" inside? Can I use something like that within the TYPO3 query builder?

Many thanks in advance.

1

1 Answers

0
votes

You can try with QueryBuilder interface

    public function findShy($searchWord)
    {

        /** @var ConnectionPool $pool */
        $pool = GeneralUtility::makeInstance(ConnectionPool::class);
        $connection = $pool->getConnectionForTable('table');

        $queryBuilder = $connection->createQueryBuilder();

        $query = $queryBuilder
            ->select('*')
            ->from('table')
            ->where("REPLACE(name,'­', '') like :name")
            ->setParameter('name', "%{$searchWord}%");

        // for debug only
        echo($query->getSQL());
        print_r($query->getParameters());

        return $query->execute()->fetchAll();
    }

and call it somewhere i.e. in your controller:

DebuggerUtility::var_dump(
    $this->yourRepository->findShy('Testlabor'), 
    'findShy() sample'
);

it will create a query with named parameter like (according to your TCA of course):

SELECT *
FROM `table`
WHERE (REPLACE(name, '­'­, '') like :name)
  AND ((`table`.`deleted` = 0) AND (`table`.`hidden` = 0) AND
       (`table`.`starttime` <= 1596363840) AND
       ((`table`.`endtime` = 0) OR (`table`.`endtime` > 1596363840)))

Note that returns associative array with the record not a mapped object of your model.

Optional

If you need mapped model objects anyway, you can mix these two solutions, i.e. first select only the pids of your records with QueryBuilder and then fetch them with Query which implements QueryInterface like this:

public function findShy2($searchWord)
{

    /** @var ConnectionPool $pool */
    $pool = GeneralUtility::makeInstance(ConnectionPool::class);
    $connection = $pool->getConnectionForTable('table');

    $queryBuilder = $connection->createQueryBuilder();

    $preQuery = $queryBuilder
        ->select('uid')
        ->from('table')
        ->where("REPLACE(name,'&shy;', '') like :name")
        ->setParameter('name', "%{$searchWord}%");

    // for debug only
        echo($query->getSQL());
        print_r($query->getParameters());

    $uids = [];
    foreach ($preQuery->execute()->fetchAll() as $item) {
        $uids[] = $item['uid'];
    }

    if(count($uids) > 0){
        $interfaceQuery = $this->createQuery();
        $interfaceQuery->matching(
            $interfaceQuery->in('uid', $uids)
        );

        return $interfaceQuery->execute();
    }

    return [];
}