【问题标题】:How to integrate Elasticsearch in Zend Framework 2 using Doctrine 2如何使用 Doctrine 2 在 Zend Framework 2 中集成 Elasticsearch
【发布时间】:2014-10-04 05:07:30
【问题描述】:

我关注 this tutorial 将教义与 Zend Framework 2 集成。现在,一切正常,但我想将 Elasticsearch 集成到这个项目中。

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

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

【问题讨论】:

    标签: php doctrine-orm elasticsearch zend-framework2 elastica


    【解决方案1】:

    Doctrine 2Elasticsearch 之间没有直接关系。虽然 Doctrine ORM 的主要关注点是持久化、更新和读取关系数据库上的数据,但 elasticsearch 主要关注索引和搜索该数据。与其考虑“将elasticsearch与学说集成”,不如考虑“我如何在同一个应用程序中同时使用学说和elasticsearch”

    每当您在数据库中创建或更新记录时,您可能希望执行更多操作,例如在 ElasticsearchSolr 上为该数据编制索引,缓存或使已缓存的版本无效MemcachedRedis 等上的相同数据。要正确地做到这一点(或 zf2 方式),您应该仔细设计一个服务层,orchestrates 包括持久性操作和相关诸如在 elasticsearch 上建立索引、缓存、缓存失效、日志记录等后处理。

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

    注意:不要将 EventManager 大量用于简单直接的任务,例如编写日志行。活动不是免费的,尤其是在 ZF2 中。 (在 ZF3 中得到了很大的改进,但仍然不是免费的)。


    对于问题,这里是使用 Zend Framework 2 的方法,同时使用 ruflin/elastica 的 3rd 方库:

    A.打开终端并输入

    $ 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');
    

    奖励:使用服务初始化器和特征

    如果您的 PHP 版本 ≥ 5.4,您可以使用 traits,同时借助 service initializers 将 Elastica 客户端自动注入您的服务。

    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();
        }
    }
    

    【讨论】:

    • 不错的答案!奖金 - 特质!是的!
    • 你的回答非常详细,对于像我这样的初学者来说看起来很容易理解,我明天会测试它(在我的国家已经很晚了)并给你反馈。非常感谢:)
    • 嗨,所以我尝试了你的解决方案,但是当我调用 $elastica = $this->getServiceLocator()->get('elastica-client'); 时出现此错误: 在尝试创建 elasticaclient(alias: elastica-client) 时,为此实例类型注册了一个无效工厂。
    • 您能否在 gist.github.com 上为您当前的 module.config.php 和 ElasticaServiceFactory.php 内容创建一个要点?
    【解决方案2】:

    有一些(仍在大力开发中)模块结合了 Doctrine2 和 ElasticSearch。例如从 Doctrine2+ZF2 大师@Ocramius 本人那里查看this module called OcraElasticSearch :)

    否则,在集成 Doctrine 和 ElasticSearch 方面,Symfony2 似乎领先一步。

    我敢打赌,在一两个月内,您应该能够在 GitHub 上找到更多替代方案。

    由于我们很快需要类似的功能,我以后可能会发现更多。如果我这样做了,我会更新我的帖子。

    【讨论】:

      猜你喜欢
      • 2011-06-27
      • 2011-08-15
      • 2011-12-13
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多