1
votes

I am working on my first Zend Framework 2 Project. I needed a User Module and integrated ZfcUser for this. Because I have a slight difference in my User Table, I had to use my own User Entity and User Mapper. I created a new Module called ZfcUserExtension.

I then copied a lot of files from the original ZfcUSer Module like:

  • Entity/User.php
  • Entity/UserInterface.php
  • Factory/Entity/IndexControllerFactory.php
  • Factory/Mapper/UserHydratorFactory.php
  • Mapper/Exeption/ExceptionInterface
  • Mapper/Exeption/InvalidArgumentException.php
  • Mapper/Exeption/RuntimeException.php Mapper/HydratorInterface.php
  • Mapper/User.php Mapper/UserHydrator.php Mapper/UserHydrator.php
  • Mapper/UserInterface.php

In zfcuser.global.php I set the user_entity_class to use my own Entity.

'user_entity_class' => 'ZfcUserExtension\Entity\User',

In the module.config.php from the ZfcUserExtension I add the below to make sure that I use my own User Mapper and UserHydrator. The reason for that was that I use "id" as a Primary Key in my User table instead of "user_id", so I had to make sure that this gets overwritten as well.

<?php
 return array(
 'controllers' => array(
    'factories' => array(
        'ZfcUserExtension\Controller\Index' => function(Zend\Mvc  \Controller\ControllerManager $cm) {
            $sm = $cm->getServiceLocator();
            return new \ZfcUserExtension\Controller\IndexController(
                $sm->get("doctrine.entitymanager.orm_default")
            );
        }
    ),
),

'service_manager' => array(
    'factories' => array(
        'zfcuser_user_mapper' => function ($sm) {
            $options = $sm->get('zfcuser_module_options');
            $mapper = new \ZfcUserExtension\Mapper\User();
            // No db adapter present add below line
            $mapper->setDbAdapter($sm->get('zfcuser_zend_db_adapter'));
            $entityClass = $options->getUserEntityClass();
            // No entity prototype set add below line
            $mapper->setEntityPrototype(new $entityClass);
            $mapper->setHydrator($sm->get('zfcuser_user_hydrator'));
            $mapper->setTableName($options->getTableName());
            return $mapper;
        },
        //  'zfcuserextension_change_password_form' => 'ZfcUserExtension\Factory\Form\ChangePhoneFormFactory',
            ),
),

I finally got all this to work, till I now run into another problem. I want some additional fields for the User like Phone Number. How would I approach this? I know there are some ideas on the Internet, but I am mainly interested to know how I would actually offer the option to have a "Change Phone" Form. I have created a Form, similar to the "Change Password and "Change Email". I have then created a IndexController.php in my ZfcUSerExtension, again followed the set-up of the UserController from the ZfcUser Module

class IndexController extends AbstractActionController {

const ROUTE_LOGIN        = 'zfcuser/login';



/**
 * @var \Doctrine\ORM\EntityManager
 */
protected $em;

public function __construct(\Doctrine\ORM\EntityManager $em)    
{
    $this->em = $em;
}


/**
 * @var Form
 */
protected $changeEmailForm;



public function indexAction() {

    if (!$this->zfcUserAuthentication()->hasIdentity()) {
         return $this->redirect()->toRoute(static::ROUTE_LOGIN);
    }
    return new ViewModel();
}

 public function changephoneAction() {

    // if the user isn't logged in, we can't change phone
    if (!$this->zfcUserAuthentication()->hasIdentity()) {
       return $this->redirect()->toRoute(static::ROUTE_LOGIN);
    }

    $form = $this->getChangePhoneForm();
    $request = $this->getRequest();
    $request->getPost()->set('PrevPhone', $this->getUserService()->getAuthService()->getIdentity()->getPrevPhone());

       return array(
            'status' => false,
            'changePhoneForm' => $form,
        );


    $fm = $this->flashMessenger()->setNamespace('change-phone')->getMessages();
    if (isset($fm[0])) {
        $status = $fm[0];
    } else {
        $status = null;
    }

    $prg = $this->prg(static::ROUTE_LOGIN);
    if ($prg instanceof Response) {
        return $prg;
    } elseif ($prg === false) {
        return array(
            'status' => $status,
            'changePhoneForm' => $form,
        );
    }

    $form->setData($prg);

    if (!$form->isValid()) {
        return array(
            'status' => false,
            'changePhoneForm' => $form,
        );
    }

    $change = $this->getUserService()->changeEmail($prg);

    if (!$change) {
        $this->flashMessenger()->setNamespace('change-email')->addMessage(false);
        return array(
            'status' => false,
            'changeEmailForm' => $form,
        );
    }
    $this->flashMessenger()->setNamespace('change-email')->addMessage(true);
    return $this->redirect()->toRoute(static::ROUTE_CHANGEEMAIL);

}


public function getChangePhoneForm()
{
      $sl = $this->getServiceLocator();
      $this->setChangePhoneForm($sl->get('zfcuserextension_change_phone_form'));
    return $this->changePhoneForm;
}

public function setChangePhoneForm($changePhoneForm)
{
    $this->changePhoneForm = $changePhoneForm;      
    return $this;
}

I now noticed that I will face a problem with the User Service Service/User.php. The Service offers a changePassword() and changeEmail() Method. I now thought that I need to copy this file into my own Modules. Am I right that if I extend the User Service from ZfcUser then the Methods changePassword() and changeEmail() will still be available, so I would delete it from the just copied file and just add changePhone()?

And if I am right with my thoughts, the User Service currently starts like this:

class User extends EventProvider implements ServiceManagerAwareInterface

How would I have to change it that I extend the original User Service? I hope somebody can help, I am still rather confused with all this. Thanky you very much in advance.

1

1 Answers

1
votes

There are two possible methods:

  1. Build custom classes extending ZfcUser's entity, form and input filter and add your custom fields. In the ZfcUser configuration change aliases or override factories to ensure your custom classes are instantiated rather than the built in ones.

  2. If you are OK with having the custom profile fields stored and accessed separately from the ZfcUser user entity, check out my module on GitHub: LdcUserProfile. It provides a profile system for ZfcUser but also makes it easy to add your own custom profile fieldsets linked to a user.