Integrations / Frameworks / Symfony / Upgrading the Algolia SearchBundle

Upgrading the Algolia SearchBundle

Upgrading from 3.4.0 to 4.0.0

The new SearchBundle is now based on version 2 of the PHP API client. Note the following architectural changes in version 4 of the Algolia SearchBundle

  • Remove search engine-agnostic feature
  • Merge AlgoliaEngine and IndexManager classes into SearchService class
  • SearchClient is a public class. Its method signatures and return types changed between v1 and v2 of the Algolia PHP API client. Read the update guide for more information.

Upgrade the algolia/search-bundle dependency from ^3.4 to 4.0.0 in your composer.json file and run composer update algolia/search-bundle algolia/algoliasearch-client-php in your terminal.

Improved developer experience with the Algolia PHP client version 2

You don’t have to worry about the method signatures: most of the earlier methods you could use remain the same. You can also benefit from new features: you can copy a whole index, copy all the rules from an index, replace all data in an index, generate secured API keys, and more. The instantiation of the client is easier, and the methods have more detailed exceptions for better error management. Please read the upgrade guide of the PHP API client to learn more.

Examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Either autowire the SearchClient service...

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class ArticleController extends AbstractController
{
    public function refillAction(SearchClient $client, array $objects)
    {
        // Copy an index
        $client->copyIndex('SRC_INDEX_NAME', 'DEST_INDEX_NAME');

        // Copy all the rules from an index
        $client->copyRules('SRC_INDEX_NAME', 'DEST_INDEX_NAME');

        // Replace all objects
        $index = $client->initIndex('DEST_INDEX_NAME');
        $index->replaceAllObjects($objects);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ...Or fetch it directly from the container. Note that this method is not encouraged.

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class ArticleController extends Controller
{
    public function refillAction(array $objects)
    {
        $client = $this->get('search.client');
        // Copy an index
        $client->copyIndex('SRC_INDEX_NAME', 'DEST_INDEX_NAME');

        // Copy all the rules from an index
        $client->copyRules('SRC_INDEX_NAME', 'DEST_INDEX_NAME');

        // Replace all objects
        $index = $client->initIndex('DEST_INDEX_NAME');
        $index->replaceAllObjects($objects);
    }
}

SearchService

IndexManager has been renamed to SearchService. This is the only service you will need to interact with Algolia.

Previously, to get started:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Algolia\SearchBundle\IndexManagerInterface;

class ExampleController extends Controller
{
    protected $indexManager;

    public function __construct(IndexManagerInterface $indexingManager)
    {
        $this->indexManager = $indexingManager;
    }
}

Now, in 4.0.0 you should update your code to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Algolia\SearchBundle\SearchService;

class ExampleController extends Controller
{
    protected $searchService;

    public function __construct(SearchServiceInterface $searchService)
    {
        $this->searchService = $searchService;
    }
}

Method signature changes

3.4.0 Breaking Change 4.0.0
getSearchableEntities(): array<int, string> Renamed getSearchables(): array<int, string>
getFullIndexName($className): string Renamed searchableAs($className): string
index($entities, ObjectManager $objectManager): array<string, int> Changed index(ObjectManager $objectManager, $searchables, $requestOptions = []): array<int, array<string, \Algolia\AlgoliaSearch\Response\AbstractResponse>>
remove($entities, ObjectManager $objectManager): array<string, int> Changed remove(ObjectManager $objectManager, $searchables, $requestOptions = []): array<int, array<string, \Algolia\AlgoliaSearch\Response\AbstractResponse>>
clear($className): boolean Changed clear($className): \Algolia\AlgoliaSearch\Response\AbstractResponse
delete($className): boolean Changed delete($className): \Algolia\AlgoliaSearch\Response\AbstractResponse
search($query, $className, ObjectManager $objectManager, $page = 1, $nbResults = null, array $parameters = []): array<int, object> Changed search(ObjectManagåer $objectManager, $className, $query = '', $requestOptions = []): array<int, object>
rawSearch($query, $className, $page = 1, $nbResults = null, array $parameters = []): array<string, int | string | array> Changed rawSearch($className, $query = '', $requestOptions = []): array<string, int | string | array>
count($query, $className, array $parameters = []): int Changed count($className, $query = '', $requestOptions = []): int

Waitable operations

Methods from the SearchService are now waitable. You can rely on the wait() method to wait for your task to be completely handled by the engine before moving on, instead of handling this logic yourself.

Examples:

1
2
3
4
5
// index objects and wait for the task to finish
$response = $this->searchService->index($entityManager, $objects)->wait();

// clear an index
$response = $this->searchService->clear($className)->wait();

This also means that the return type of waitable methods has changed. They now all return an AbstractResponse. Please update your code accordingly.

Add any options to your operations

The methods follow these rules:

  • All required parameters have their own argument
  • All optional arguments are passed in an array or as RequestOptions object as the last argument
  • The client never sets any default values

Now you can pass any optional arguments and search parameters to the engine in the $requestOptions parameter, available in all SearchService methods. For example, you can add filters, choose which facets to retrieve, change the number of hits per page, or pass new headers.

A few examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# v3
$result = $this->indexManager->remove(
    $searchablePosts,
    $this->get('doctrine')->getManager()
    // you could not pass requestOptions
);

# v4
$result = $this->searchService->remove(
    $this->get('doctrine')->getManager(),
    $searchablePosts,
    // here you can pass any requestOptions or headers, for example 'X-Forwarded-For', 'X-Algolia-UserToken'...
    [
        'X-Forwarded-For' => '0.0.0.0',
    ]
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# v3
$result = $this->indexManager->search(
    'foo',
    Post::class,
    $this->get('doctrine')->getManager(),
    // the optional page and hitsPerPage parameters were passed separately
    // page argument was starting from 1
    1,
    20,
    'attributesToRetrieve' => [
        'title',
    ]
);

# v4
$result = $this->searchService->search(
    $this->get('doctrine')->getManager(),
    Post::class,
    'foo',
    // all the optional parameters are now sent as once in the $requestOptions
    // be careful as page argument now starts from 0
    [
        'page'                 => 0,
        'hitsPerPage'          => 20,
        'attributesToRetrieve' => [
            'title',
        ],
    ]
);

List of changes in fully qualified namespaces

3.4.0 Breaking Change 4.0.0
Algolia\SearchBundle\Engine\AlgoliaEngine Removed /
Algolia\SearchBundle\IndexManager Renamed Algolia\SearchBundle\Services\AlgoliaSearchService
Algolia\SearchBundle\IndexManagerInterface Renamed Algolia\SearchBundle\SearchService
Algolia\SearchBundle\Engine\NullEngine Changed Algolia\SearchBundle\Services\NullSearchService*

For testing purposes use Algolia\SearchBundle\SearchService by mocking or extending it, and override the search.service in your test configuration (see https://symfony.com/doc/current/configuration.html#configuration-environments). The Algolia\SearchBundle\Services\NullSearchService class is a good starting point.

List of classes that became internal

The following classes are now internal. They’re not meant to be used directly and can change between minor versions.

  • Algolia\SearchBundle\Command\SearchClearCommand
  • Algolia\SearchBundle\Command\SearchImportCommand
  • Algolia\SearchBundle\Command\SearchSettingsBackupCommand
  • Algolia\SearchBundle\Command\SearchSettingsCommand
  • Algolia\SearchBundle\Command\SearchSettingsPushCommand
  • Algolia\SearchBundle\DependencyInjection\AlgoliaSearchExtension
  • Algolia\SearchBundle\DependencyInjection\Configuration
  • Algolia\SearchBundle\EventListener\SearchIndexerSubscriber
  • Algolia\SearchBundle\SearchableEntity
  • Algolia\SearchBundle\SettingsManager

List of deleted interfaces and final classes you should use instead

3.4.0 Breaking Change 4.0.0
Algolia\SearchBundle\Settings\SettingsManagerInterface Removed Algolia\SearchBundle\Settings\SettingsManager
Algolia\SearchBundle\Engine\EngineInterface Removed /

List of updated public services names

3.4.0 Breaking Change 4.0.0
search.index_manager Renamed search.service
algolia_client (setup publicly manually, you may not have been using it) Renamed search.client or SearchClient class autowired
Did you find this page helpful?