0

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 !

Community
  • 1
  • 1
Luka
  • 748
  • 2
  • 9
  • 36

2 Answers2

0

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;
        },
    )
),
Ruben
  • 5,043
  • 2
  • 25
  • 49
  • Thanks Ruben, I have tried it out, but get the message: "An alias by the name "zfcuserusermapper" or "zfcuser_user_mapper" already exists vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php on line 801" It would be a nice solution – Luka Sep 23 '14 at 22:49
  • @Luka Please check the edit in the answer above. Does that help? – Ruben Sep 24 '14 at 16:01
0

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 !!

Luka
  • 748
  • 2
  • 9
  • 36
  • 1
    If you place the configuration in getServiceConfig() in Module.php you shouldn't use the service_manager key. What I wrote was to put it in your module's module.config.php. In that case you do need the service_manager key. The file should be located in your module's config folder, so /module/MyModule/config/module.config.php. This will automatically be loaded by the framework when your module is being loaded. So you have the choice to place your service manager config for your module in getServiceConfig in your Module.php or in module.config.php. Anyway glad you managed to solve it! – Ruben Sep 24 '14 at 22:07
  • Ah, okay. Thanks for pointing this out, still need to learn a lot. Still looking to get the Change-Password to work. Thought it would be the form, but that uses the Email as hidden field. – Luka Sep 24 '14 at 22:14
  • You're very welcome. You should open a new question for the Change Password problem, because it's not the same problem as the original question. – Ruben Sep 24 '14 at 22:21
  • You are right, the title of the question is probably not the best. I wanted a way to use different column names in my Database, this meant I needed to have my own Mapper to change the column name inside that mapper, but now I realise that won't be enough. So maybe I should re-think about the title. – Luka Sep 24 '14 at 22:26
  • I think the title for this issue is okay because you did want to use your own UserMapper. However if you have a follow up question it's probably best to open a new question. – Ruben Sep 24 '14 at 22:30
  • Ok, will try more tomorrow and otherwise post a new question. Hope to figure it out myself. Thanks again! – Luka Sep 24 '14 at 22:33