如何使用原则2在Zend框架2中集成Elasticsearch


How to integrate Elasticsearch in Zend Framework 2 using Doctrine 2

我遵循本教程将doctrine与Zend Framework 2集成。现在,一切都很好,但我想把Elasticsearch集成到这个项目。

我找到了很多关于Elasticsearch的文档,我下载了Elastica的PHP插件,但是我不知道从哪里开始。

我搜索了将Elasticsearch与Doctrine集成的教程,但它们都是关于Symfony的。有人可以解释我(以一种简单的方式)如何在Zend框架2中使用ElasticSearch,使用Doctrine 2作为ORM来索引和搜索我的对象吗?

Doctrine 2Elasticsearch之间不存在直接关系。Doctrine ORM主要关注的是持久化、更新和读取关系数据库中的数据,而elasticsearch主要关注的是索引和搜索这些数据。与其考虑"将elasticsearch与doctrine集成",不如考虑"如何在同一应用中同时使用doctrine和elasticsearch"

当你在数据库中创建或更新记录时,你可能想要做更多的操作,比如在ElasticsearchSolr上索引数据,在MemcachedRedis上缓存或无效已经缓存的相同数据版本。要正确地做到这一点(或zf2方式),你应该仔细设计一个服务层,它协调持久性操作和相关的后处理,如elasticsearch上的索引、缓存、缓存失效、日志记录等。

通过EventManager触发一些事件来完成这些操作将是一个适当的决定。

注意:不要在简单的&简单的任务,如写日志行。事件并不是免费的,尤其是在《ZF2》中。(在ZF3中得到了很大的改进,但仍然不是自由的)。


对于问题,下面是使用Zend Framework 2的方法,同时使用第三方库ruflin/elastica:

打开终端,输入

$ cd /path/to/your/project
$ php composer.phar selfupdate
$ php composer.phar require ruflin/elastica:dev-master

B。为elastica客户端Application'Service'ElasticaClientFactory.php创建工厂

<?php
namespace Application'Service;
use Zend'ServiceManager'FactoryInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
class ElasticaClientFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $sl)
    {
        $config = $sl->get('Config');
        $clientOptions = isset($config['elastica']) ? $config['elastica'] : array();
        $client = new 'Elastica'Client($clientOptions);
        return $client;
    }
}

C。添加elastica配置并在module.config.php中的服务定位器中注册新的工厂类:

'elastica' => array(
    'servers' => array(
        array('host' => '127.0.0.1','port' => 9200),
        // You can add more servers when necessary
        // array('host' => '127.0.0.1','port' => 9200)
        ),
    ),
service_manager' => array(
    'factories' => array(
        'elastica-client' => 'Application'Service'ElasticaClientFactory'
    ),
)
此时,在任何控制器(坏)或服务(好)中,您都可以像这样获取elastica客户端实例:
$elastica = $this->getServiceLocator()->get('elastica-client');

好处:使用服务初始化器和trait

如果你的PHP版本是≥5.4,你可以使用traits,同时在服务初始化器的帮助下自动将Elastica Client注入到你的服务中。

D。新建接口Application'Service'ElasticaAwareInterface.php

<?php
namespace Application'Service;
interface ElasticaAwareInterface
{
    public function getElasticaClient();
    public function setElasticaClient('Elastica'Client $client);
}

E。创建一个名为Application'Traits'ElasticaAwareTrait.php的新特性(注意路径)。创建Traits文件夹(如果不存在)

<?php
namespace Application'Traits;
trait ElasticaAwareTrait
{
    protected $client = null;
    public function getElasticaClient()
    {
        return $this->client;
    }
    public function setElasticaClient('Elastica'Client $client)
    {
        $this->client = $client;
        return $this;
    }
}

F。创建一个名为Application'Initializers'ElasticaInitializer.php的新初始化器(再次注意路径)

<?php
namespace Application'Initializers;
use Zend'ServiceManager'InitializerInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
use Application'Service'ElasticaAwareInterface;
class ElasticaInitializer implements InitializerInterface
{
    /**
     * Initializer for the elastica-aware domain services.
     * Properly creates a new elastica client and injects it into related service.
     */
    public function initialize($service, ServiceLocatorInterface $serviceManager)
    {
        /**
         * Beware: This if statement will be run for every service instance
         * we grab from $serviceManager because the nature of initializers.
         * This worth think about on it. With ZF3 this went further. 
         * We may load our services lazily using delegator factories.
         */ 
        if ($service instanceof ElasticaAwareInterface) {
            $service->setElasticaClient( $serviceManager->get('elastica-client') );
        }
    }
}

到目前为止一切顺利。现在,我们可以把所有部分组合在一起。假设我们有一个名为UserService的服务,它使用Doctrine实体管理器(或者更好的是UserRepository),也需要使用Elastica

G。向服务经理注册我们的服务:

service_manager' => array(
    'factories' => array(
        'elastica-client' => 'Application'Service'ElasticaClientFactory'
    ),
    'invokables' => array(
        'user-service' => 'Application'Service'UserService'
    )
)
最后,UserService签名:
<?php
namespace Application'Service;
use Application'Service'ElasticaAwareInterface;
class UserService implements ElasticaAwareInterface
{
    // Here is our trait
    use 'Application'Traits'ElasticaAwareTrait;
    public function fooMethod()
    {
        // Do some things with doctrine EM here..
        // And grab the elastica client easily anywhere in UserService
        $client = $this->getElasticaClient();
    }
}

有一些(仍在大量开发中)模块结合了Doctrine2和ElasticSearch。例如,检查这个模块称为OcraElasticSearch从Doctrine2+ZF2大师@Ocramius自己:)

除此之外,Symfony2在整合Doctrine和ElasticSearch方面似乎领先一步。

我敢打赌,在一到两个月内,你应该可以在GitHub上找到更多的替代品。

因为我们很快就需要类似的功能,我可能会在以后发现更多。