【问题标题】:Zend Framework 2: Pass Variable to View HelperZend Framework 2:将变量传递给 View Helper
【发布时间】:2014-11-17 20:28:55
【问题描述】:

我创建了一个 View Helper 来显示来自数据库表的最新广告。由于我有不同类型的广告,我希望能够从视图内部传递一个变量,在该视图中调用 View Helper 来显示特定的广告。

很抱歉我无法更好地解释它,但我仍然是 ZF2 的初学者。我将添加源代码,希望这会使它更清楚。请注意,我有一本书中的源代码,它随机显示了比萨饼并对其进行了更改,直到它可以显示我的广告。我可能仍然有实际上不需要的代码,所以请不要怀疑......好吧,代码在这里:

1.视图:index.html

<?php foreach ($this->latestAdvert() as $value){ ?>
      <li><?php echo $value->getAdvertTitle();?></li>
<?php }?>

2。视图助手:Advert\View\Helper\LatestAdvert.php

namespace Advert\View\Helper;
use Zend\View\Helper\AbstractHelper;

class LatestAdvert extends AbstractHelper
{

   protected $random = null;


   public function __construct($random)
   {
     $this->setLatestAdvert($random);
   }


   public function setLatestAdvert($random)
   {
     $this->random = $random;
   }


   public function getLatestAdvert()
   {
     return $this->random;
   }


   public function __invoke()
   {
     $latestAdverts = $this->getLatestAdvert();
     return $latestAdverts;
   }
}

3.工厂:Advert\View\Helper\LatestAdvertFactory.php

namespace Advert\View\Helper;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class LatestAdvertFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator) 
    {
      $locator = $serviceLocator->getServiceLocator();
      $service = $locator->get('Advert\Service');
      $random  = $service->fetchSingleByRandom();
      $helper  = new LatestAdvert($random);

      return $helper;
    }
}

4.服务: Advert\Service\LatestAdvertService .php

namespace Advert\Service;

use Advert\Entity\Advert as AdvertEntity;
use Doctrine\ORM\EntityManager;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
use Zend\Debug\Debug;

class LatestAdvertService implements ServiceManagerAwareInterface
{

  /**
   * Service manager.
   * @var Zend\ServiceManager\ServiceManager
   */
   private $serviceManager = null;

  /**
   * Sets service manager.
   * @param Zend\ServiceManager\ServiceManager $serviceManager Service manager.
   */
  public function setServiceManager(ServiceManager $serviceManager)
  {
    $this->serviceManager = $serviceManager;
  }

  /**
   * Returns service manager.
   * @return type
   */
  public function getServiceLocator()
  {
    return $this->serviceManager;
  }


  public function fetchSingleByRandom()
  {     
    // Get Doctrine entity manager.
    $entityManager =  $this->getServiceLocator()
                           ->get('doctrine.entitymanager.orm_default');
    $advertType = 'wanted'; // This should be removed
    $random = $entityManager->getRepository('Advert\Entity\Advert')
                            ->findAdvertsByDate($advertType);

    return $random; 
  }
}

5.模块:Advert\Module.php

public function getServiceConfig()
{
    return array(
        'invokables' => array(
                 'Advert\Service' => 'Advert\Service\LatestAdvertService',
                    ),
    );
}

public function getViewHelperConfig()
{
    return array(
        'factories' => array(           
            'latestAdvert' => 'Advert\View\Helper\LatestAdvertFactory',
        ),

    );
}

正如您在 #4 中看到的,我有一个名为 $advertType 的变量。当我在 index.html 中调用视图助手时,我想设置变量,f.e. $this->latestAdvert('wanted'),但是我怎样才能通过我的所有文件传递这个变量呢?我只是找不到解决方案。有没有人告诉我如何实现它?非常感谢您提前。

!更新!

正如 SenseException 在下面指出的,将服务定位器注入服务是一种不好的做法,相反我应该将存储库或实体管理器注入服务,我现在已经为实体管理器制定了第一个可行的解决方案。

为此我更新了 2 个文件:module.php 和 LatestAdvertService.php

#5 模块.php

public function getServiceConfig()
{
    return array(
            'factories' => array(

                    'Advert\Service' => function ($sl) {
                        $entityManager =   $sl->get('doctrine.entitymanager.orm_default');
                        $myService = new Service\LatestAdvertService();
                        $myService->setEntityManager($entityManager);
                        //or you can set repository
                        //$repository = $entityManager->getRepository('Advert\Entity\Advert');
                        //$myService->setRepository($repository);
                        return $myService;
                    },

4.服务: Advert\Service\LatestAdvertService .php

namespace Advert\Service;

use Advert\Entity\Advert as AdvertEntity;
use Doctrine\ORM\EntityManager;

class LatestAdvertService 
{


  public function setEntityManager(EntityManager $entityManager)
  {
    $this->entityManager = $entityManager;
  }

  public function setRepository(Repository $repository) {
   $this->repository = $repository;
  }


  public function fetchSingleByAdvertType($advertType)
  {

    $random = $this->entityManager->getRepository('Advert\Entity\Advert')->findAdvertsByDate($advertType);  
//  $random = $this->repository->findAdvertsByDate($advertType);

    return $random;
  }
}

我尝试注入存储库,但收到以下错误消息:

传递给 Advert\Service\LatestAdvertService::setRepository() 的参数 1 必须是 Advert\Service\AdvertRepository 的实例,给定的 Advert\Repository\AdvertRepository 的实例,在

我会继续寻找存储库注入的解决方案,成功后更新。

【问题讨论】:

  • 关于您的错误消息(“参数 1 传递给...”),您需要将存储库命名空间添加到您的服务类,即 use Advert\Repository\AdvertRepository; 并将类型提示从 Repository 更改为AdvertRepositorysetRepository 方法上。如果没有它,Repository 将被假定在当前命名空间 (Advert\Service\Repository) 中,因此会出现错误。
  • 太棒了,解决了这个问题。我实际上认为我不需要添加存储库命名空间,因为我现在在我的 module.php 中使用 getRepository('Advert\Entity\Advert') 并且当我之前在我的服务中使用此代码时,我从未使用过。 ..命名空间。非常混乱,仍然需要学习。非常感谢您的帮助!

标签: php zend-framework2


【解决方案1】:

这个解决方案怎么样:

namespace Advert\View\Helper;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class LatestAdvertFactory implements FactoryInterface
{

    public function createService(ServiceLocatorInterface $serviceLocator) 
    {
      $locator = $serviceLocator->getServiceLocator();
      $service = $locator->get('Advert\Service');
      $helper  = new LatestAdvert($service);

      return $helper;
    }
}

当然还有助手类:

namespace Advert\View\Helper;
use Zend\View\Helper\AbstractHelper;

class LatestAdvert extends AbstractHelper
{

   protected $service;


   public function __construct($service)
   {
       $this->service = $service;
   }

   public function __invoke($advertType)
   {
       $latestAdverts = $this->service->fetchSingleByAdvertType($advertType);
       return $latestAdverts;
   }
}

对于服务:

public function fetchSingleByAdvertType($advertType)
{
    $entityManager =  $this->getServiceLocator()
                           ->get('doctrine.entitymanager.orm_default');

    $random = $entityManager->getRepository('Advert\Entity\Advert')
                            ->findAdvertsByDate($advertType);

    return $random; 
}

我试图让您的代码尽可能接近您的原始代码,但请听听有关服务定位器的一些建议。像在 LatestAdvertService 中那样将服务定位器注入服务是一种不好的做法。由于您的服务只需要一个存储库,因此只需将其注入其中。如果您的服务中需要实体管理器,请改为注入它。你的单元测试会感谢你的。

【讨论】:

  • 非常感谢 SenseException,它正在工作!我几乎要放弃了,因为我无法让它发挥作用。我现在正在尝试理解您的建议,并会寻找更好的解决方案,即使我觉得我再也不想在它终于工作之后再碰这个代码了:) 我必须在模块中注入存储库是对的吗.php?当我让它工作时,我会更新上面的代码。再次感谢!
  • 顺便说一句:由于 LatestAdvert 现在将 Service 放入其构造函数中,因此您可以摆脱工厂并让 LatestAdvert 本身成为服务。
  • 那会是更好的方法还是我的方法好吗?我认为现在已经明确分开了,但我想要“最好”的方式,特别是在我还在学习的时候,像你这样的建议很棒。我已经多次看到这种类型的设置,一个服务,一个工厂,即使我仍然试图理解一切......
  • 我对 ZF2 不是很熟悉,但我想在 Config 中是可能的:framework.zend.com/manual/2.2/en/modules/… 抱歉,我帮不上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-06
  • 2014-07-04
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
相关资源
最近更新 更多