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 !
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;
},
)
),
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 !!