0
votes

I am working on my first Zend Framework 2 Project. I have implemented ZfcUser in my Project and since I have slightly different Columns in my Database Table, I want to overwrite the User Mapper from ZfcUser. I have searched through the Internet and on here, but did not get the solutions to work. I have to admit that the solution I found is from 2012 (ZF2: Custom user mapper for ZfcUser module), so maybe something has changed in the meantime.

So what have I done so far. I have created my own User entity. If I understood it right then it needs to extend ZfcUser which I have done like this:

module/Application/src/Entity/User.php

namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use ZfcUser\Entity\User as ZfcUser;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
 class User extends ZfcUser
 {

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer", nullable=false)
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 */
 protected $id;

/**
 * @var string
 *
 * @ORM\Column(name="username", type="string", length=255, nullable=false)
 */
 protected $username;

I then copied the zfcuser.global.php and moved it in the Folder config/autoload/zfcuser.global.php

In this file I have activated 'user_entity_class' => 'Application\Entity\User', I hope this is correct so far.

Now I need my own UserMapper. As far what I understood this can not be done through the config file. I copied the Folder "Mapper" with all its files from zfc-user/src/ZfcUser/Mapper into my Application Module. I changed the Namespace from all the files. Now I am confused what else I need to copy, the Service and/or the Factory Folder? And where and how do I tell my Application to use my own Mapper instead of ZfcUser? I just don't get it and hope someone can give me some assistance. Thank you very much in advance !

2

2 Answers

0
votes

ZfcUser just asks the service manager for an instance of a UserMapper. The alias they use is called 'zfcuser_user_mapper'.

So if you link that alias to your own UserMapper then you should be good to go. You can set this up in either your module's module.config.php file, i.e.:

'service_manager' => array(

        'invokables' => array(
            'MyModule\Mapper\UserMapper' => 'MyModule\Mapper\UserMapper',
        ),

        'aliases' => array(
            'zfcuser_user_mapper' => 'MyModule\Mapper\UserMapper',
        ),
),

or you can also set it up in your Module.php in getServiceConfig().

Just make sure you load your own module after ZfcUser in your application.config.php.

Please note that I haven't tested this, but in theory it should work.

Edit (2014/09/24) Since you got the error message An alias by the name "zfcuserusermapper" or "zfcuser_user_mapper" already exists try to override the factory directly in your own module. In your own module's module.config.php:

'service_manager' => array(
    'factories' => array(
        // Override ZfcUser User Mapper factory
        'zfcuser_user_mapper' => function ($sm) {
            $options = $sm->get('zfcuser_module_options');
            $mapper = new MyModule\Mapper\User($sm->get('Zend\Db\Adapter\Adapter'));
            $entityClass = $options->getUserEntityClass();
            $mapper->setHydrator(new ZfcUser\Mapper\UserHydrator());
            $mapper->setTableName($options->getTableName());
            return $mapper;
        },
    )
),
0
votes

Thank you to Ruben and his suggestions. I had to change it slightly to get it to work maybe because I am using the latest Zend Framework 2.

I will describe here my Error messages and the solution, just in case someone else will face the same problem.

module.php

// This solution did not work for me
public function getServiceConfig()
{
    return array(
      'service_manager' => array(
         'factories' => array(
          // Override ZfcUser User Mapper factory
          'zfcuser_user_mapper' => function ($sm) {
              $options = $sm->get('zfcuser_module_options');
              $mapper = new MyModule\Mapper\User($sm->get('Zend\Db\Adapter\Adapter'));
              $entityClass = $options->getUserEntityClass();
              $mapper->setHydrator(new ZfcUser\Mapper\UserHydrator());
              $mapper->setTableName($options->getTableName());
              return $mapper;
           },
        )
     );     
} 

First of all I had to remove 'service_manager' => array(), otherwise the code was totally ignored and the normal ZfcUser was used. After I removed that I received 3 Error Message.

1. Catchable fatal error: Argument 1 passed to ZfcUser\Mapper\UserHydrator::__construct() must be an instance of Zend\Crypt\Password\PasswordInterface, none given,

to fix it, I had to change this:

 $mapper->setHydrator(new ZfcUser\Mapper\UserHydrator());

to this code:

 $mapper->setHydrator($sm->get('zfcuser_user_hydrator'));

after that I got the next Error message:

2. No db adapter present

Again some code needed changing:

 $mapper = new MyModule\Mapper\User($sm->get('Zend\Db\Adapter\Adapter'));

into this

 $mapper = new \ZfcUserExtension\Mapper\User();                   
 $mapper->setDbAdapter($sm->get('zfcuser_zend_db_adapter'));

And the last Error message

3. No entity prototype set

This message disappeared when I added the below line:

$mapper->setEntityPrototype(new $entityClass);

Here now the final working code:

public function getServiceConfig()
{
    return 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;
                    },
                )
            );  
}

I copied in the end the Mapper and Entity Folder from ZfcUser into my Model called ZfcUserExtension. I then changed in the UserMapper the Database column name from user_id to id. I can now Log in and Register with the new Column name.

Unfortunately I am not able to use Change-Password yet, since this is still using user_id and I have not found out where this is set and how I can overwrite it, but I will update the post when I have found out a solution for it. If anyone knows the solution for this problem, then please feel free to share it.

A big Thank you @Ruben for his assistance !!