override ResourceOwner class for Wordpress - php

I went to override WordpressResourceOwner into HWIOAuthBundle as it didn`t return user information response
I notice that every ResourceOwner work as Service and declared into oauth.xml

i had override registration twig into HWIOAuthBundle and create new bundle inherit from HWIOAuthBundle like answer of this question but I can`t work the same with WordpressResourceOwner
after searching I had found we can override class of WordpressResourceOwner Service
Steps:
1) create new ResourceOwner
EX:
namespace project\OAuthBundle\OAuth\ResourceOwner;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;
use HWI\Bundle\OAuthBundle\Security\Core\Authentication\Token\OAuthToken;
/**
* Override WordpressResourceOwner class into HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\WordpressResourceOwner
*
* #author ahmedhamdy
*
*/
class WordpressResourceOwner extends GenericOAuth2ResourceOwner
{
/**
* {#inheritDoc}
*/
protected $paths = array(
'identifier' => 'ID',
'nickname' => 'username',
'realname' => 'display_name',
'email' => 'email',
'profilepicture' => 'avatar_URL',
);
/**
* {#inheritDoc}
*/
protected function doGetUserInformationRequest($url, array $parameters = array())
{
$apiAccessToken = $parameters['apiAccessToken'];
$headers = array(
0 => 'authorization: Bearer '.$apiAccessToken,
);
return $this->httpRequest($url,null,$headers);
}
/**
* {#inheritDoc}
*/
public function getUserInformation(array $accessToken, array $extraParameters = array())
{
$url = $this->normalizeUrl($this->options['infos_url'], array(
'access_token' => $accessToken['access_token']
));
$parameters = array(
'apiAccessToken' => $accessToken['access_token'],
);
$content = $this->doGetUserInformationRequest($url,$parameters)->getContent();
$response = $this->getUserResponse();
$response->setResponse($content);
$response->setResourceOwner($this);
$response->setOAuthToken(new OAuthToken($accessToken));
return $response;
}
/**
* {#inheritDoc}
*/
protected function configureOptions(OptionsResolverInterface $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefaults(array(
'authorization_url' => 'https://public-api.wordpress.com/oauth2/authorize',
'access_token_url' => 'https://public-api.wordpress.com/oauth2/token',
'infos_url' => 'https://public-api.wordpress.com/rest/v1/me',
));
}
}
2) create CompilerPass class to override service class like Symfony2 documentation
EX:
namespace project\OAuthBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* OverrideWordpressResourceOwner
*
* #author ahmedhamdy
*/
class OverrideWordpressResourceOwner implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition("hwi_oauth.abstract_resource_owner.wordpress");
$definition->setClass('ProfileTree\OAuthBundle\OAuth\ResourceOwner\WordpressResourceOwner');
}
}
3) we must override build method into Bundle class like Symfony2 documentation
EX:
namespace Project\OAuthBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use ProfileTree\OAuthBundle\DependencyInjection\Compiler\OverrideWordpressResourceOwner;
class ProfileTreeOAuthBundle extends Bundle
{
public function getParent()
{
return 'HWIOAuthBundle';
}
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new OverrideWordpressResourceOwner());
}
}
4) last step calling compile method for ContainerBuilder into Bundle Extension like Symfony2 documentation
EX:
namespace Project\OAuthBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class ProfileTreeOAuthExtension extends Extension
{
/**
* {#inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$container->compile();
}
}

Related

How to inject dependencies into private service using container?

I'm developing Form Request for Symfony, but i have one problem.
I inject FormRequest instances into controller action using argument value resolving. But I would like to inject services to FormRequest instance without making it public in services.yaml file.
Here is my Resolver:
<?php
namespace App\Resolver;
use App\Exception\FormValidationException;
use App\Request\FormRequest;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ControllerRequestResolver implements ArgumentValueResolverInterface
{
/**
* #var SerializerInterface
*/
private $serializer;
/**
* #var ValidatorInterface
*/
private $validator;
/**
* #var DecoderInterface
*/
private $decoder;
/**
* #var ContainerInterface
*/
private $container;
public function __construct(
SerializerInterface $serializer,
ValidatorInterface $validator,
DecoderInterface $decoder,
ContainerInterface $container
) {
$this->serializer = $serializer;
$this->validator = $validator;
$this->decoder = $decoder;
$this->container = $container;
}
/**
* {#inheritdoc}
* #throws FormValidationException
*/
public function resolve(Request $request, ArgumentMetadata $argument)
{
$data = $this->decoder->decode($request->getContent(), 'json');
$request->request->replace($data);
$formRequestClass = $argument->getType();
/** #var FormRequest $form */
$form = $this->container->has($formRequestClass)
? $this->container->get($formRequestClass)
: new $formRequestClass();
$form->initialize(
$request->query->all(), $request->request->all(), $request->attributes->all(),
$request->cookies->all(), $request->files->all(), $request->server->all(), $request->getContent()
);
if (!$form->authorize()) {
throw new AccessDeniedHttpException('Access denied.');
}
$violations = $this->validator->validate($data, $form->rules());
if ($violations->count() > 0) {
throw new FormValidationException($violations, 'Validation error.');
}
yield $form;
}
/**
* {#inheritdoc}
*/
public function supports(Request $request, ArgumentMetadata $argument)
{
return (new \ReflectionClass($argument->getType()))->isSubclassOf(FormRequest::class);
}
}
So to receive FormRequest with needed dependencies in $this->container->get($formRequestClass) I need to make it public.
Here is FormRequest:
<?php
namespace App\Request;
use App\Entity\User;
use App\Rule\UniqueConfig;
use App\Service\Randomizer;
use App\Validator\Constraints\UniqueEntity;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Validator\Constraints as Assert;
class UserRequest extends FormRequest
{
/**
* #var null|Randomizer
*/
private $randomizer;
public function __construct(Randomizer $randomizer)
{
$this->randomizer = $randomizer;
}
public function authorize(): bool
{
return $this->randomizer->getNumber() > 0.5;
}
public function rules(): Assert\Collection
{
return new Assert\Collection([
'email' => [
new Assert\NotBlank(),
new Assert\Email(),
new UniqueEntity([
'config' => new UniqueConfig(User::class, 'u', 'email', function ($value, QueryBuilder $qb) {
// You can add here additional filtering
}),
]),
],
'firstName' => [
new Assert\Length(['max' => 255]),
],
'lastName' => [
new Assert\Length(['max' => 255]),
],
]);
}
}
Thanks to #Cerad for help! Here is total result:
<?php
namespace App\Locator;
use Symfony\Component\DependencyInjection\ServiceLocator;
class FormRequestServiceLocator extends ServiceLocator
{
}
I inject it (FormRequestServiceLocator) into ControllerRequestResolver
<?php
namespace App\DependencyInjection\Compiler;
use App\Locator\FormRequestServiceLocator;
use App\Request\FormRequest;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
class FormRequestPass implements CompilerPassInterface
{
/**
* {#inheritdoc}
*/
public function process(ContainerBuilder $container)
{
if (!$container->has(FormRequest::class)) {
return;
}
$taggedServices = $container->findTaggedServiceIds('app.form_request.tag');
$serviceReferences = [];
foreach ($taggedServices as $id => $tags) {
if ($id === FormRequest::class) {
continue;
}
$serviceReferences[$id] = new Reference($id);
}
$driverLocator = $container->getDefinition(FormRequestServiceLocator::class);
$driverLocator->setArguments([$serviceReferences]);
}
}
<?php
namespace App;
// ...
class Kernel extends BaseKernel
{
// ...
protected function build(ContainerBuilder $container)
{
parent::build($container);
$container->registerForAutoconfiguration(FormRequest::class)
->addTag('app.form_request.tag');
$container->addCompilerPass(new FormRequestPass());
}
}

symfony 4 form collection entity with file type create

How to create and upload the document using entity where fileType field is embedded in parent form via collectionType. I did read the documentation Symfony Upload. But didn't manage to accomplish this. Always get this error "Type error: Argument 1 passed to App\Service\FileUploader::upload() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, instance of App\Entity\Attachment given".
Below is my Invoice entity
class Invoice
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Attachment", mappedBy="invoiceId", cascade={"persist"})
*/
private $attachments;
public function __construct()
{
$this->attachments = new ArrayCollection();
}
/**
* #return Collection|Attachment[]
*/
public function getAttachments(): Collection
{
return $this->attachments;
}
public function addAttachment(Attachment $attachment): self
{
if (!$this->attachments->contains($attachment)) {
$this->attachments[] = $attachment;
$attachment->setInvoiceId($this);
}
return $this;
}
Attachment entity
class Attachment
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $path;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Invoice", inversedBy="attachments")
*/
private $invoiceId;
public function getId()
{
return $this->id;
}
public function getPath(): ?string
{
return $this->path;
}
public function setPath(string $path): self
{
$this->path = $path;
return $this;
}
public function getInvoiceId(): ?Invoice
{
return $this->invoiceId;
}
public function setInvoiceId(?Invoice $invoiceId): self
{
$this->invoiceId = $invoiceId;
return $this;
}
Attachment form type
namespace App\Form;
use App\Entity\Attachment;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\FileType;
class AttachmentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('path',FileType::class, array(
'label' => false,
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Attachment::class,
]);
}
}
Invoice form type
namespace App\Form;
use App\Entity\Invoice;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class InvoiceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('attachments', CollectionType::class, array(
'entry_type' => AttachmentType::class,
'entry_options' => array('label' => false),
'allow_add' => true
))
->add('submit', SubmitType::class, array(
'label' => $options['set_button_label']
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Invoice::class,
'set_button_label' => "Create Invoice",
]);
}
}
and the Controller
namespace App\Controller;
use App\Entity\Invoice;
use App\Form\InvoiceType;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Debug\Debug;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use App\Service\FileUploader;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class InvoiceController extends Controller
{
/**
* #Route("/invoice/create", name="createInvoice")
* #param Request $request
* #param UserInterface $user
* #param FileUploader $fileUploader
* #return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
*/
public function createInvoice( Request $request, UserInterface $user, FileUploader $fileUploader)
{
Debug::enable();
$invoice = new Invoice();
$form = $this->createForm(InvoiceType::class,$invoice);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid())
{
// Prepare upload file
/** #var UploadedFile $files */
$files = $invoice->getAttachments();
foreach($files as $file){
$fileName = $fileUploader->upload($file);
}
$file->move(
$this->getParameter('attachment_directory'),
$fileName
);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($invoice);
$entityManager->flush();
return $this->redirectToRoute('user');
}
return $this->render('invoice/createInvoice.html.twig', [
'controller_name' => 'UserController',
'form' => $form->createView()
]);
}
I think the problem is the FileType field return attachment entity instance while it should return File instance. the question is how do i get the value as File instance?
In your case the property $path type of UploadedFile and not $invoice->getAttachments().
Try to add a property to your Attachement class called $file without doctrine mapping, generate it's getter and setter methods.
/**
* #var UploadedFile
*/
protected $file;
In your AttachmentType class change 'path' => 'file'.
Now, try to update this part in your controller:
$attachements = $invoice->getAttachments();
foreach($attachements as $attachement){
/** #var UploadedFile $file */
$file = $attachement->getFile(); // This is the file
$attachement->setPath($this->fileUploader->upload($file));
}
Please, make your fileUploader service the unique responsible for uploading file, no need to use $file->move().

Migration from ZF2 to ZF 3 without getServicelocator();

I am new at ZF3 and I need your help.
In ZF3 there is no service Locator any more. So I created a Factory class to replace the service Locator in my code.
Here is my code with service Locator in my AbstractController.php file:
protected function getService()
{
return $this->getServiceLocator()->get($service); //remove from ZF3
return $this->service = $service;
}
Now I replaced the service Locator in AbstractController.php:
protected function getService($service)
{
$service = $this->service;
return $this->service = $service;
}
And in Module.Config.php I added the following lines:
return [
'controllers' => [
'factories' => [
Controller\AbstactController::class => Controller\AbstactControllerFactory::class,
],
],
And I created a AbstractControllerFactory file with the following lines:
<?php
namespace Application\Controller;
use Application\Controller\AbstractController;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class AbstractControllerFactory implements FactoryInterface
{
protected function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new AbstractController($container->get(service::class));
}
}
I need to know if this is a correct migration from ZF2 to ZF3?
In ZF3 the first thing you do is create your Service and a Factory for it. Let's take in this example UserManager.php in Services folder.
So we have in folder Service -> UserManager.php and in Service -> Factory -> UserManagerFactory.php
UserManagerFactory.php:
<?php
namespace User\Service\Factory;
use Interop\Container\ContainerInterface;
use User\Service\UserManager;
/**
* This is the factory class for UserManager service. The purpose of the factory
* is to instantiate the service and pass it dependencies (inject dependencies).
*/
class UserManagerFactory
{
/**
* This method creates the UserManager service and returns its instance.
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$entityManager = $container->get('doctrine.entitymanager.orm_default');
return new UserManager($entityManager);
}
}
UserManager.php:
<?php
namespace User\Service;
use User\Entity\User;
/**
* This service is responsible for adding/editing users
* and changing user password.
*/
class UserManager
{
/**
* Doctrine entity manager.
* #var Doctrine\ORM\EntityManager
*/
private $entityManager;
/**
* Constructs the service.
*/
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
// REST OF YOUR CODE
}
Now that we have our service, we go into User\config\modules.config.php:
'service_manager' => [
'factories' => [
Service\UserManager::class => Service\Factory\UserManagerFactory::class,
],
],
Well that's basically it, we can inject the service in our controller and job done:
<?php
namespace User\Controller;
use Zend\Mvc\Controller\AbstractActionController;
/**
* This controller is responsible for user management (adding, editing,
* viewing users and changing user's password).
*/
class UserController extends AbstractActionController
{
/**
* User manager.
* #var User\Service\UserManager
*/
private $userManager;
/**
* Constructor.
*/
public function __construct($userManager)
{
$this->userManager = $userManager;
}
// REST OF YOUR CODE
}
I really hope this helps you understand how to use Service in ZF3.
Good Luck!

While attempting to create controlleralbumcontroller(alias: Controller\AlbumController) an invalid factory was registered for this instance type

I have created AlbumControllerFactory.php in folder \module\Album\src\Album\Factory as follows: But it is showing error a mentioned above
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Album\Controller\AlbumController;
class AlbumControllerFactory implements FactoryInterface
{
/**
*
* #param ContainerInterface $container
* #param string $requestedName
* #param null|array $options
* #return AlbumController
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$class = $requestedName ? $requestedName : AlbumController::class;
$albumTable = $container->get('Album\Model\AlbumTable'); // get service from service manager
$controller = new $class($albumTable);
return $controller;
}
/**
* Provided for backwards compatibility; proxies to __invoke().
*
* #param ContainerInterface|ServiceLocatorInterface $container
* #return AlbumController
*/
public function createService(ServiceLocatorInterface $container)
{
return $this($container, AlbumController::class);
}
}
And in my controller i have following code to get my factory:
namespace Album\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Album\Model\Album;
use Album\Form\AlbumForm;
class AlbumController extends AbstractActionController
{
protected $_albumTable;
public function __construct(AlbumTable $albumTable)
{
$this->_albumTable = $albumTable;
}
public function indexAction()
{
return new ViewModel(array(
'albums' => $this->getAlbumTable()->fetchAll(),
));
}
}
And in my module.config.php i have set the controller as like follows:
return array(
'controllers' => array(
'factories' => array(
Controller\AlbumController::class => Factory\Controller\AlbumControllerFactory::class,
),
),
So How i can fix this issue in-order to make my module work fine as it was working fine before creating the factory but it was showing a deprecated message. Please have a look at let me know what wrong i have done and how to fix this.
Here is a full example of how to use factories in Zend 2/3. I guess you are missing namespace in module.config.php file, but please compare your namespaces and directories with these.
You should have following directory structure:
module
- Album
- config
module.config.php
- src
- Controller
AlbumController.php
- Factory
- Controller
AlbumControllerFactory.php
- Module.php
Factory
namespace Album\Factory\Controller
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Album\Controller\AlbumController;
class AlbumControllerFactory implements FactoryInterface
{
/**
*
* #param ContainerInterface $container
* #param string $requestedName
* #param null|array $options
* #return AlbumController
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$class = $requestedName ? $requestedName : AlbumController::class;
$albumTable = $container->get('Album\Model\AlbumTable'); // get service from service manager
$controller = new $class($albumTable);
return $controller;
}
/**
* Provided for backwards compatibility; proxies to __invoke().
*
* #param ContainerInterface|ServiceLocatorInterface $container
* #return AlbumController
*/
public function createService(ServiceLocatorInterface $container)
{
return $this($container, AlbumController::class);
}
}
Controller
namespace Album\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Album\Model\Album;
use Album\Form\AlbumForm;
class AlbumController extends AbstractActionController
{
protected $_albumTable;
public function __construct(AlbumTable $albumTable)
{
$this->_albumTable = $albumTable;
}
public function indexAction()
{
return new ViewModel(array(
'albums' => $this->getAlbumTable()->fetchAll(),
));
}
}
module.config.php
namespace Album;
use Album\Controller;
use Album\Factory;
return array(
'controllers' => array(
'factories' => array(
Controller\AlbumController::class => Factory\Controller\AlbumControllerFactory::class,
),
),
I like to have segregated factories, but you can keep all your factories in main Factory directory, but be sure to set correct namespaces for them and in module.config.php file
Your problem is about Namespace :
You said :
I have created AlbumControllerFactory.php in folder
\module\Album\src\Album\Factory
BUT you call
Controller\AlbumController::class => Factory\Controller\AlbumControllerFactory::class,
Factory\Controller\AlbumControllerFactory is not a correct Full Qualified Class Name (FQCN)
You should have this in your config file
Suppose your namespace declared in the config file is Album :
Controller\AlbumController::class => Factory\AlbumControllerFactory::class

getServiceLocator only works with LoginController

I am using ZF2 with Doctrine 2 ORM, using the following:
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
seems to work in LoginController but doesn't seem to work in any other controller, what might be the reasons ? ( All controllers are under the same application )
<?php
namespace OEC;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\Mvc\MvcEvent;
use Zend\ServiceManager\ServiceManager;
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 onBootstrap(MvcEvent $e){
$e->getApplication()->getEventManager()->getSharedManager()->attach('Zend\Mvc\Controller\AbstractController', 'dispatch', function($e) {
$controller = $e->getTarget();
if ($controller instanceof Controller\LoginController) {
$controller->layout('login/login.phtml');
} else {
$controller->layout('layout/layout.phtml');
}
}, 100);
}
public function getServiceConfig(){
return array(
'factories' => array(
'Zend\Authentication\AuthenticationService' => function($serviceManager) {
return $serviceManager->get('doctrine.entitymanager.orm_default');
}
)
);
}
}
?>
Constantly getting this error Call to a member function get() on null
My working controller
<?php
namespace OEC\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Session\Container;
use OEC\Controller\CommonController;
class LoginController extends AbstractActionController{
public function indexAction(){
$session = self::checkUserLoginAction();
if( $session ){
return $this->redirect()->toUrl( MAIN_URL . 'oec/view/dashboard');
}
return new ViewModel();
}
public function loginAction(){
$username = $this->getRequest()->getPost('username');
$password = $this->getRequest()->getPost('password');
try{
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$user = $objectManager->getRepository('OEC\Entity\User')->findOneBy(array('username' => $username, 'password' => md5($password) ));
if( !$user ){
print_r("not found");exit;
}
if( $user && $user->getId() != 0 ){
$session = new Container('user');
$session->userId = $user->getId();
$session->username = $user->getUsername();
$session->userType = $user->getUserTypeId();
CommonController::json(true, "successfully logged in", NULL, "view/dashboard");exit;
}
}catch(\Doctrine\ORM\NoResultException $e) {
print_r("error");exit;
}
}
public static function checkUserLoginAction(){
$session = new Container('user');
if( $session->offsetExists('username') && $session->offsetExists('userId') && $session->offsetExists('userType') ){
return array(
"username" => $session->offsetGet('username'),
"name" => $session->offsetGet('name'),
"userType" => $session->offsetGet('userType')
);
}else{
return false;
}
}
public function logoutAction(){
$session = new Container('user');
$session->getManager()->destroy();
return $this->redirect()->toUrl( MAIN_URL . 'oec/view/login');
}
}
My not working controller
<?php
namespace OEC\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class BloodTypeController extends AbstractActionController
{
public function indexAction()
{
return new ViewModel();
}
public function listAll(){
$objectManager = $this->getServiceLocator()->get('doctrine');
$bloodRep = $objectManager->getRepository('OEC\Entity\Blood');
$bloods = $bloodRep->findAll();
$bloodsArr = array();
foreach( $bloods as $blood ){
array_push($bloodsArr , $blood->toArray() );
}
$objectManager->close();
return $bloods;
}
}
doctrine is not a valid name to get an entity manager, there are two ways to get it directly through the service manager:
$this->getServiceLocator()->get("Doctrine\ORM\EntityManager");
as you did in your LoginController will trigger the standard factory and always returns the entity manager orm_default
$this->getServiceLocator()->get("doctrine.entitymanager.orm_default");
will trigger an abstract factory and returns the entity manager orm_default or a different entity manager if you replace orm_default after the last dot. This is the most common way to get the entity manager.
You use 3 different ways to get your service (the EntityManager instance):
$serviceManager->get('doctrine.entitymanager.orm_default');
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$objectManager = $this->getServiceLocator()->get('doctrine');
This third one is wrong. You are getting the Doctrine service, to get the EntityManager instance you need to call an additional ->getEntityManager();
$objectManager = $this->getServiceLocator()->get('doctrine')->getEntityManager();
This 'doctrine' service is typically available in Symfony framework and does not work in Zend Framework 2
If would suggest to consistently use one service name:
$objectManager = $this->getServiceLocator()->get('doctrine.entitymanager.orm_default');
This should work.
Another solution
Another even better solution is to make your controller dependent on the ObjectManager, use the doctrine ObjectManagerAwareInterface inside the Controller class and inject the service in a factory.
To do this you need to register your controller in the module.config.php under controllers - factories like this:
'controllers' => array(
'factories' => array(
'OEC\Controller\BloodTypeController' => 'OEC\Controller\Factory\BloodTypeControllerFactory'
)
)
And then create a BloodTypeControllerFactory factory class like this:
<?php
namespace OEC\Controller\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use OEC\Controller\BloodTypeController;
class BloodTypeControllerFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return BloodTypeController
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$controllerPluginManager = $serviceLocator;
$serviceManager = $controllerPluginManager->get('ServiceManager');
$objectManager = $serviceManager->get('doctrine.entitymanager.orm_default');
return new BloodTypeController($objectManager);
}
}
And then add following to your OEC\Controller\BloodTypeController:
<?php
namespace OEC\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;
class BloodTypeController extends AbstractActionController implements ObjectManagerAwareInterface
{
/**
* #var ObjectManager
*/
protected $objectManager;
/**
* #param ObjectManager $objectManager
*/
public function __construct(ObjectManager $objectManager){
$this->objectManager = $objectManager
}
/**
* Set the object manager
*
* #param ObjectManager $objectManager
*/
public function setObjectManager(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
/**
* Get the object manager
*
* #return ObjectManager
*/
public function getObjectManager()
{
return $this->objectManager();
}
public function indexAction()
{
return new ViewModel();
}
public function listAll()
{
$objectManager = $this->getObjectManager();
//etc
}
}

Categories