Zend Framework 3中的GetServiceLocator

时间:2017-03-23 11:31:20

标签: php zend-framework3 service-locator

早上好,我一直在学习使用框架(Zend Framework)进行编程。 在我过去的经历中,我使用的是骨架应用程序v.2.5。话虽如此,我过去开发的所有模块都是围绕来自ServiceManager的servicelocator()工作的。 有没有办法在zend框架3中安装ServiceManager(带有servicelocator功能)?

如果没有,你可以给我一个使用servicelocator工作的方法吗?

感谢您的关注,祝您有个美好的一天:)

* / UPDATED - 小模块为例。 作为一个例子,我将向您展示我在2.5中使用的登录验证模块:

我的Module.php

<?php

namespace SanAuth;

use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\Authentication\Storage;
use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;

class Module implements AutoloaderProviderInterface
{
    public function getAutoloaderConfig()
    {
        return array(
             'Zend\Loader\StandardAutoloader' => array(
                 'namespaces' => array(
                     __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
                 ),
              ),
        );
    }
    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    public function getServiceConfig()
    {
        return array(
            'factories'=>array(
         'SanAuth\Model\MyAuthStorage' => function($sm){
            return new \SanAuth\Model\MyAuthStorage('zf_tutorial');  
        },

        'AuthService' => function($sm) {
            $dbAdapter           = $sm->get('Zend\Db\Adapter\Adapter');
                $dbTableAuthAdapter  = new DbTableAuthAdapter($dbAdapter, 
                                          'users','user_name','pass_word', 'MD5(?)');

        $authService = new AuthenticationService();
        $authService->setAdapter($dbTableAuthAdapter);
                $authService->setStorage($sm->get('SanAuth\Model\MyAuthStorage'));

        return $authService;
    },
        ),
    );
}

}

我的AuthController:

<?php
//module/SanAuth/src/SanAuth/Controller/AuthController.php
namespace SanAuth\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\Form\Annotation\AnnotationBuilder;
use Zend\View\Model\ViewModel;

use SanAuth\Model\User;

class AuthController extends AbstractActionController
{
    protected $form;
    protected $storage;
    protected $authservice;

    public function getAuthService()
    {
        if (! $this->authservice) {
            $this->authservice = $this->getServiceLocator()
                                  ->get('AuthService');
        }

        return $this->authservice;
    }

    public function getSessionStorage()
    {
        if (! $this->storage) {
            $this->storage = $this->getServiceLocator()
                              ->get('SanAuth\Model\MyAuthStorage');
        }

        return $this->storage;
    }

    public function getForm()
    {
        if (! $this->form) {
           $user       = new User();
           $builder    = new AnnotationBuilder();
           $this->form = $builder->createForm($user);
        }
        $this->form->setLabel('Entrar')
            ->setAttribute('class', 'comment_form')
            ->setAttribute('style', 'width: 100px;');

       return $this->form;
    }

    public function loginAction()
    {
        //if already login, redirect to success page 
        if ($this->getAuthService()->hasIdentity()){
           return $this->redirect()->toRoute('success');
        }

        $form       = $this->getForm();

        return array(
            'form'      => $form,
            'messages'  => $this->flashmessenger()->getMessages()
        );
    }

    public function authenticateAction()
    {
        $form       = $this->getForm();
        $redirect = 'login';

        $request = $this->getRequest();
        if ($request->isPost()){
            $form->setData($request->getPost());
            if ($form->isValid()){
                //check authentication...
                $this->getAuthService()->getAdapter()
                                     ->setIdentity($request->getPost('username'))
                                   ->setCredential($request->getPost('password'));

            $result = $this->getAuthService()->authenticate();
            foreach($result->getMessages() as $message)
            {
                //save message temporary into flashmessenger
                $this->flashmessenger()->addMessage($message);
            }

            if ($result->isValid()) {
                $redirect = 'success';
                //check if it has rememberMe :
                if ($request->getPost('rememberme') == 1 ) {
                    $this->getSessionStorage()
                         ->setRememberMe(1);
                    //set storage again 
                    $this->getAuthService()->setStorage($this->getSessionStorage());
                }
                $this->getAuthService()->getStorage()->write($request->getPost('username'));
                }
             }
         }

       return $this->redirect()->toRoute($redirect);
     }

    public function logoutAction()
    {
       $this->getSessionStorage()->forgetMe();
       $this->getAuthService()->clearIdentity();

       $this->flashmessenger()->addMessage("You've been logged out");
       return $this->redirect()->toRoute('login');
    }
}

我的SucessController:

<?php
//module/SanAuth/src/SanAuth/Controller/SuccessController.php
namespace SanAuth\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class SuccessController extends AbstractActionController
{
    public function indexAction()
    {
        if (! $this->getServiceLocator()
                 ->get('AuthService')->hasIdentity()){
            return $this->redirect()->toRoute('login');
        }

        return new ViewModel();
    }
 }

我的User.php:

<?php
namespace SanAuth\Model;

use Zend\Form\Annotation;

/**
 * @Annotation\Hydrator("Zend\Stdlib\Hydrator\ObjectProperty")
 * @Annotation\Name("User")
 */
class User
{
    /**
     * @Annotation\Type("Zend\Form\Element\Text")
     * @Annotation\Required({"required":"true" })
     * @Annotation\Filter({"name":"StripTags"})
     * @Annotation\Options({"label":"Utilizador:  "})
     */
    public $username;

    /**
     * @Annotation\Type("Zend\Form\Element\Password")
     * @Annotation\Required({"required":"true" })
     * @Annotation\Filter({"name":"StripTags"})
     * @Annotation\Options({"label":"Password:  "})
     */
    public $password;

    /**
     * @Annotation\Type("Zend\Form\Element\Checkbox")
     * @Annotation\Options({"label":"Lembrar "})
     */
    public $rememberme;

    /**
     * @Annotation\Type("Zend\Form\Element\Submit")
     * @Annotation\Attributes({"value":"Entrar"})
     */
    public $submit;
}

和MyAuthStorage.php:

<?php
namespace SanAuth\Model;

use Zend\Authentication\Storage;

class MyAuthStorage extends Storage\Session
{
    public function setRememberMe($rememberMe = 0, $time = 1209600)
    {
         if ($rememberMe == 1) {
             $this->session->getManager()->rememberMe($time);
         }
    }

    public function forgetMe()
    {
        $this->session->getManager()->forgetMe();
    } 
}

1 个答案:

答案 0 :(得分:2)

ZF3中没有更多服务定位器,因为它被视为反模式。

正确的方法是在服务管理器中使用工厂,并将特定的依赖项传递到您的类中。

如果您有任何可以展示的代码,我们将很乐意为您提供进一步的帮助。

根据提供的示例进行编辑。

首先,使用composer进行自动加载而不是旧的Zend。在Module.php中,删除自动加载。还需要删除autoload_classmap文件。

添加composer.json文件并设置您的PSR-0或PSR-4自动加载(询问您是否不知道如何)。

回到Module类,您还需要更改服务管理器配置。我在这里保留你的匿名函数,但你应该使用适当的类。

<?php

namespace SanAuth;

use Zend\Authentication\Storage;
use Zend\Authentication\AuthenticationService;
use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;

final class Module
{
    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    public function getServiceConfig()
    {
        return [
            'factories'=> [
                \SanAuth\Model\MyAuthStorage::class => function($container){
                    return new \SanAuth\Model\MyAuthStorage('zf_tutorial');
                },
                'AuthService' => function($container) {
                    $dbAdapter = $sm->get(\Zend\Db\Adapter\Adapter::class);
                    $dbTableAuthAdapter = new DbTableAuthAdapter($dbAdapter, 'users','user_name','pass_word', 'MD5(?)');
                    $authService = new AuthenticationService();
                    $authService->setAdapter($dbTableAuthAdapter);
                    $authService->setStorage($container->get(SanAuth\Model\MyAuthStorage::class));

                    return $authService;
                },
            ),
        );
    }
}

另外,请考虑使用password_ *函数而不是MD5(或者其他什么,但不是md5)。

让我们只关注一个简​​单的控制器。同样的事情需要重复其他事情。

<?php

namespace SanAuth\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Authentication\AuthenticationService;

final class SuccessController extends AbstractActionController
{
    private $authenticationService;

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

    public function indexAction()
    {
        if (! $this->authenticationService->hasIdentity()){
            return $this->redirect()->toRoute('login');
        }

        return new ViewModel();
    }
}

显然你需要更新工厂: https://github.com/samsonasik/SanAuth/blob/master/config/module.config.php#L10(将服务注入参数)。

查看github上的代码,master分支从我所看到的内容中引入了ZF3兼容性,所以看看那里!