cms
cms copied to clipboard
[5.x] Provide search index name callback
Currently Statamic always generates search index names like this $locale ? $name.'_'.$locale : $name.
When using different environments (staging, production) and a cloud search provider (e.g. Algolia) index names tpyically collide. Staging updates overwrite those from production and vice versa.
At least in the lower pricing plans Algolia has a limit of 1 app per account and per app isolation is also often a configuration overhead. So an environment prefix for the search index name would be handy?
Afaik there a two approaches to get this solved in user land:
- With a dirty env access within
search.php
'indexes' => [
env('APP_ENV') . '_pages' => [
'driver' => 'algolia',
'searchables' => ['collection:pages'],
'fields' => ['title'],
'sites' => 'all',
],
]
- By overriding the default index within a ServiceProvider's boot method:
use Algolia\AlgoliaSearch\SearchClient;
use App\Statamic\Search\Algolia\EnvironmentIndex;
use Illuminate\Foundation\Application;
use Statamic\Facades\Search;
Search::extend(
driver: 'algolia',
callback: fn (Application $app, array $config, string $name, string $locale): EnvironmentIndex => new EnvironmentIndex(
client: SearchClient::create(
appId: $config['credentials']['id'],
apiKey: $config['credentials']['secret']
),
name: $name,
config: $config,
locale: $locale
)
);
//
namespace App\Statamic\Search\Algolia;
use Algolia\AlgoliaSearch\SearchClient;
use Statamic\Search\Algolia\Index as BaseIndex;
class EnvironmentIndex extends BaseIndex
{
public function __construct(SearchClient $client, string $name, array $config, string $locale)
{
parent::__construct(
client: $client,
name: app()->environment() . '_' . $name,
config: $config,
locale: $locale
);
}
}
With this PR it would possible to override the generating of index names by setting a callback within a ServiceProvider's boot method e.g. like this:
use Statamic\Search\Algolia\Index as AlgoliaIndex;
AlgoliaIndex::resolveNameUsing(fn (string $name): string => app()->environment() . '_' . $name);
No breaking chances, default name generation is preserved.
Any chance that this is getting merged? :) Thanks!
Closes statamic/ideas#1202
@ajnsn Would #10536 work for you?
Ah yes, sure. I am not that config-file fan any more but as Statamic has a lot of config files it would fit too. Also keep in mind that there are other search providers as well. Narrowing down this to Algolia could lead to other PR's :)
Also keep in mind that there are other search providers as well. Narrowing down this to Algolia could lead to other PR's
Good point!
I went the config file road in the other PR because that's the way it is done in Laravel Scout. In the end it's more about having the opportunity to have the value in your env file. It doesn't have to be in the drivers.algolia array, but it would be great to have it in the config file, maybe at a higher level, so we can use the same value from the env file.
I'm sure some folks are tied up with Laracon/traveling, but happy to help support this in any way!
We're about to work on a project that needs this type of capability. Any documentation necessary here? I can write that up if so if it'll help get this merged sooner!
I'm sure some folks are tied up with Laracon/traveling, but happy to help support this in any way!
We're about to work on a project that needs this type of capability. Any documentation necessary here? I can write that up if so if it'll help get this merged sooner!
You can always composer patch it in.
Good idea, @edalzell! In the meantime, if the core team could use an extra pair of hands I'm happy to jump in!
Hi @jasonvarga. I added a test for the search index name callback. This somehow took longer as expected as the getIndex() approach seems to be unused or broken? But this could be the right place for this type of test and maybe provides a basis for further search index testing?
Please let me know if this works for you and if there is anything missing. Thanks!
Sorry for the delay. Thanks for your patience.
I've adjusted this so that your resolver function accepts the original name, and the locale.
You'll need to put the locale on that string if you're dealing with multisite.
AlgoliaIndex::resolveNameUsing(function ($name, $locale) {
return 'prefix_'.$name.'_'.$locale;
// prefix_name_locale
});
I also updated the tests.