Default listener settings of FOSElasticaBundle is set to automatically update elasticsearch index in real time when an object is added, updated or removed. It is set as listener: ~ in the config file. If you want to manually update elasticsearch index then you can use example below.

In this example, there is a 'Post' entity and we will do insert, update and delete operations with doctrine then manually update elasticsearch index with an event listener.

Note: I suggest you to use this version rather than longer event subscriber version that I have in this blog.


Config


fos_elastica:
clients:
default: { host: 127.0.0.1, port: 9200 }
indexes:
post_index:
client: default
index_name: post_dev
types:
post:
mappings:
id:
type: integer
index: not_analyzed
title:
type: string
analyzer: english
year:
type: integer
index: not_analyzed
price:
type: double
index: not_analyzed
is_published:
type: boolean
index: not_analyzed
persistence:
driver: orm
model: Application\SearchBundle\Entity\Post
finder: ~
provider: ~
listener: ~

PostService


namespace Application\SearchBundle\Service;

...........
...........

class PostDatabaseService
{
...........
...........

public function createPost()
{
$post = new Post();
$post->setTitle('inanzzz');
$post->setYear(1999);
$post->setPrice(6.99);
$post->setIsPublished(true);

$this->entityManager->persist($post);
$this->entityManager->flush();

return sprintf('create-post ID: %s', $post->getId());
}

public function updatePost($id)
{
/** @var Post $post */
$post = $this->findPost($id);
$post->setTitle('inanzzz inanzzz');

$this->entityManager->flush();

return sprintf('update-post ID: %s', $id);
}

public function deletePost($id)
{
/** @var Post $post */
$post = $this->findPost($id);

$this->entityManager->remove($post);
$this->entityManager->flush();

return sprintf('delete-post ID: %s', $id);
}

private function findPost($id)
{
$post = $this->postRepository->findOneById($id);
if (!$post instanceof Post) {
throw new EntityNotFoundException(sprintf('Post [%s] cannot be found.', $id));
}

return $post;
}
}

PostIndexListener


You should also study vendor/friendsofsymfony/elastica-bundle/Doctrine/Listener.php class to see how things actually work.


namespace Application\SearchBundle\Listener;

use Application\SearchBundle\Entity\Post;
use Doctrine\Common\EventSubscriber;
use FOS\ElasticaBundle\Doctrine\Listener;
use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
use FOS\ElasticaBundle\Provider\IndexableInterface;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Symfony\Component\PropertyAccess\PropertyAccess;

class PostIndexListener extends Listener implements EventSubscriber
{
protected $propertyAccessor;

private $indexable;
private $config;

public function __construct(
ObjectPersisterInterface $postPersister,
IndexableInterface $indexable,
array $config
) {
$this->objectPersister = $postPersister;
$this->indexable = $indexable;
$this->config = $config;
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
}

public function getSubscribedEvents()
{
return ['postPersist', 'postUpdate', 'preRemove', 'preFlush', 'postFlush'];
}

public function postPersist(LifecycleEventArgs $eventArgs)
{
$entity = $eventArgs->getObject();

if ($entity instanceof Post) {
if ($this->objectPersister->handlesObject($entity)) {
if ($this->isObjectIndexable($entity)) {
$this->scheduledForInsertion[] = $entity;
}
}
}
}

public function postUpdate(LifecycleEventArgs $args)
{
$entity = $args->getObject();

if ($entity instanceof Post) {
if ($this->objectPersister->handlesObject($entity)) {
if ($this->isObjectIndexable($entity)) {
$this->scheduledForUpdate[] = $entity;
}
}
}
}

public function preRemove(LifecycleEventArgs $args)
{
$entity = $args->getObject();

if ($entity instanceof Post) {
if ($this->objectPersister->handlesObject($entity)) {
if ($identifierValue = $this->propertyAccessor->getValue($entity, $this->config['identifier'])) {
$this->scheduledForDeletion[] = $identifierValue;
}
}
}
}

private function isObjectIndexable($object)
{
return $this->indexable->isObjectIndexable(
$this->config['index'],
$this->config['type'],
$object
);
}
}

Services.yml


services:
application_search.listener.post_index:
class: Application\SearchBundle\Listener\PostIndexListener
arguments:
- @fos_elastica.object_persister.post_index.post
- @fos_elastica.indexable
- { index: post_index, type: post, identifier: id }
tags:
- { name: doctrine.event_subscriber }