Integrations / Frameworks / Symfony / Upgrade Guide

Upgrade Guide

Upgrading from 3.4.0 to 4.0.0

The new SearchBundle is now based on version 2 of the PHP API client. This means you can use all the new features introduced in this API client in your Symfony application. This means we’ve made some changes to the architecture to keep it as clear as possible. For example, we removed the search engine-agnostic feature, and the AlgoliaEngine and IndexManager classes are merged into a SearchService class. The SearchClient class is now public. However, its method signatures and return types have changed from v1 to v2. Please read our PHP Client v2 upgrade guide to get a list of the changes.

We attempt to document every possible breaking change, even though not all of them may affect your application.

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.

Miscellaneous

We strongly encourage you to take a look at the PHP Client v2 upgrade guide to get acquainted with the new features deployed in this version.

Improved DX with our PHP Client v2

You don’t have to worry about the method signatures: most of the previous methods you could use remained 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. We also made the instantiation of the client easier, and added 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;
    }
}
List of 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

To have the most consistent, predictable, and future-proof method signature, our methods follow these rules:

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

So you now have the possibility to 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, pass new headers, and so on.

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 are 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?