Good morning, i have been learning to program using a framework (Zend Framework). In my past experiences i was using a skeleton application v.2.5. That been said, all my past developed Modules work around servicelocator() from ServiceManager. Is there any way of installing ServiceManager(with the servicelocator functionality) in zend framework 3?
If not, can you send me a propor way to work around servicelocator?
Thank You for atention, have a awesome day :)
*/ UPDATED - Small module as example. As an example i will show you a login authentication module that i was using back in 2.5:
my 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;
},
),
);
}
}
my 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');
}
}
My 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();
}
}
my 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;
}
And 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();
}
}
There is no more service locator in ZF3 as it is considered as an antipattern.
The proper way to proceed is to use factories in the service manager, and pass specific dependencies into your class.
If you have any code you can show, I'll be happy to help you further.
Edit according to the example provided.
First thing first, use composer for autoloading rather than the old Zend stuff. In Module.php, remove the autoloading. Removing the autoload_classmap file is also required.
Add a composer.json file and set your PSR-0 or PSR-4 autoloading (ask if you don't know how).
Back on the Module class, you also need to change the service manager configuration. I'm keeping your anonymous functions here but you should use proper classes.
<?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;
},
),
);
}
}
Also, please consider using password_* functions rather than MD5 (or whatever, but not md5 anyways).
Let's focus on just one simple controller. Same things needs to be repeated for the others.
<?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();
}
}
Obviously you need to update the factory: https://github.com/samsonasik/SanAuth/blob/master/config/module.config.php#L10 (inject the service as parameter).
Looking at the code on github, the master branch introduces ZF3 compatibility from what I can see, so have a look there!
来源:https://stackoverflow.com/questions/42974794/getservicelocator-in-zend-framework-3