Silex "There is no user provider for user" how to configure security - silex

$app->register(new SecurityServiceProvider(), array(
'security.firewalls' => array(
'admin' => array(
'pattern' => '^/',
'form' => array(
'login_path' => '/login',
'check_path' => '/login_check',
'always_use_default_target_path' => true,
'default_target_path' => '/profile'
),
'logout' => true,
'anonymous' => true,
'users' => function () use ($app) {
return new \App\UserProvider($app['dbs']['mysql']);
},
),
),
'security.access_rules' => array(
array('^/profile', 'ROLE_USER')
)
));
In a Silex 2 application I have been able to authenticate a users credentials in the login_check, but then on redirect is the dreaded (for me) Runtime exception "ContextListener.php line 74 There is no user provider for user "Symfony\Component\Security\Core\User\User".
(my 'standard' User provider class)
class UserProvider implements UserProviderInterface {
private $conn;
public function __construct(Connection $conn)
{
$this->conn = $conn;
}
public function loadUserByUsername($username)
{
// $app['monolog']->addInfo(sprintf("User '%s' registered.", $username));
$stmt = $this->conn->executeQuery('SELECT * FROM users_wet4 WHERE email = ?', array(strtolower($username)));
if (!$user = $stmt->fetch()) {
throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username));
}
return new User($user['email'], $user['password'], explode(',', $user['roles']), true, true, true, true);
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof \App\Security\User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return $class === 'Symfony\Component\Security\Core\User\User';
}
}
I've searched across it seems every instance of this issue, and it looks like the most common resolution in a Symfony installation is configuring security to point to the custom user provider, but I have not seen any examples for silex differently than the way above:
'users' => function () use ($app) {
return new \App\UserProvider($app['dbs']['mysql']);
},
(I've seen this in a security.xml file for symfony, is this kind of provider config what is missing?)
providers:
main:
entity: { class: FredUtilisateurBundle:User, property: login }
Is there anyone who can help me with the logic of the 'no user provider' after being authenticated?

Ok solved it, problem was actually here:
if (!$user instanceof \App\Security\User) {
should have just been User.
if (!$user instanceof User) {
or whatever Custom User you might have created.
\App\MyUser

Related

event that adds a parameter to routing

Is it possible to hook up (ideally in the controller) to add an additional parameter to routing?
I know that sounds unclear and at first glance it may sounds ridiculous - because to reach the controller we already must have routing. But I want to change only default variables.
I'll try to explain what I want to achieve:
Config:
return [
'router' => [
'routes' => [
'some' => [
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => [
'route' => '/some/:project',
'defaults' => [
'__NAMESPACE__' => 'Some\Controller',
'controller' => 'Some\Controller\Some',
'action' => 'some',
'extra' => 'default-value'
],
],
]
]
]
];
Controller:
class SomeController extends AbstractActionController {
protected $project = null;
public function setEventManager(EventManagerInterface $events)
{
parent::setEventManager($events);
$controller = $this;
$events->attach(
'dispatch', function (\Zend\Mvc\MvcEvent $e) use ($controller) {
$params = $e->getRouteMatch()->getParams();
$this->project = $params['project'] ;
// and there should be something that I want to
// achieve but do not know how (and if it is possible)
if ($this->project == 1) {
// magic action which modify config default param
// "extra" from "default-value" to "changed-value"
}
return;
}, 50
);
}
protected function attachDefaultListeners()
{
parent::attachDefaultListeners();
$eventManager = $this->getEventManager();
$eventManager->attach(
\Zend\Mvc\MvcEvent::EVENT_DISPATCH,
function(\Zend\Mvc\MvcEvent $event) {
$ViewModel = $event->getResult();
if ($ViewModel instanceof \Zend\View\Model\ViewModel) {
$ViewModel->setVariable('project',$this->project);
}
},
-99);
}
public function someAction() {
echo $this->params()->fromRoute("extra"); // return "default-value";
// but i want
echo $this->params()->fromRoute("extra"); // return "changed-value";
return new ViewModel();
}
}
View
<?php
echo "project: ".$this->project;
echo $this->url('some',['project'=>1]); // result: "/some/1"
I know this seems very strange. But for some reason (readable links, seo) is necessary to me.
Are you sure, you want to change the default param?
if ($this->project == 1) {
$e->getRouteMatch()->setParam('extra', 'changed-value');
}
You can set default params globally for assembling:
$serviceLocator->get('router')->setDefaultParam('extra', 'changed-value');
There is no way to change the defaults-Property of Zend\Mvc\Router\Http\Segment
If you really need it you must extend this class (but I would not recommend that, because I think your approach is already wrong)

Zend/Session with ZfcUser

I'm using ZfcUser in my app and I need to control the timeout parameter. As it's not part of the configuration I would like to set my own Zend/Session object (with the remember_me_seconds param) to ZfcUser on bootstrap but I don't know how.
By chance, has anyone done this already?
The easiest way to set session params is as follows
config\autoload\global.php
return array(
'service_manager' => [
'factories' => [
// Configures the default SessionManager instance
'Zend\Session\ManagerInterface' => 'Zend\Session\Service\SessionManagerFactory',
// Provides session configuration to SessionManagerFactory
'Zend\Session\Config\ConfigInterface' => 'Zend\Session\Service\SessionConfigFactory',
],
],
'session_manager' => [
// SessionManager config: validators, etc
],
'session_config' => [
'cache_expire' => 86400,
'cookie_lifetime' => 86400,
'remember_me_seconds' => 86400,
'gc_probability' => 10,
'gc_divisor' => 1000,
'use_cookies' => true,
'cookie_httponly' => true,
'cookie_lifetime' => 0, // to reset lifetime to maximum at every click
'gc_maxlifetime' => 86400,
],
);
And add line to onBootstrap method at Module.php
public function onBootstrap(MvcEvent $e)
{
$manager = $e->getApplication()->getServiceManager()->get('Zend\Session\ManagerInterface');
}
This will affect session setting and phpinfo() shows it.
I found it in zfcuser github
I don't use zfcuser but try this
autoload/global.php
<?php
use Zend\Session\Config\SessionConfig;
use Zend\Session\SessionManager;
use Zend\Session\Container;
return array(
'service_manager' => array(
'factories' => array(
'SessionManager' => function($sm) {
$sessionConfig = new SessionConfig();
$sessionConfig->setOption('remember_me_seconds', 1440);
$sessionManager = new SessionManager($sessionConfig);
Container::setDefaultManager($sessionManager);
return $sessionManager;
},
),
),
);
Module.php
public function onBootstrap($event)
{
$serviceManager = $event->getApplication()->getServiceManager();
$serviceManager->get('SessionManager')->start();
}
Here is how I did it. I am not the worlds greatest coder but this seems to work. This is all in Module.php
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$sharedManager = $eventManager->getSharedManager();
$sm = $e->getApplication()->getServiceManager();
//This checks to see if the user is logged in.
$eventManager->attach(MvcEvent::EVENT_DISPATCH, array($this, 'checkLogin'), 100);
}
//This function is attached to a listener to see if the user is not currently logged in
//If they are not logged in they will be redirected to the login page. This check will happen through the
//application so there is no need to keep checking in other modules
public function checkLogin (MvcEvent $e)
{
$session = new Container('defaults');
$this->route = $e->getRouteMatch();
$this->matchedRouteName = explode('/', $this->route->getMatchedRouteName());
$this->route_root = $this->matchedRouteName[0];
$sm = $e->getApplication()->getServiceManager();
$zfcServiceEvents = $sm->get('ZfcUser\Authentication\Adapter\AdapterChain')->getEventManager();
$zfcServiceEvents->attach(
'authenticate',
function ($e) use ($session) {
$session->offsetSet('sessionstart', $_SERVER['REQUEST_TIME']);
}
);
$auth = $sm->get('zfcuser_auth_service');
if (!$auth->hasIdentity() && $this->route_root != 'zfcuser')
{
$response = new \Zend\Http\PhpEnvironment\Response();
$response->getHeaders()->addHeaderLine('Location', '/user/login');
$response->setStatusCode(302);
$response->sendHeaders();
$e->stopPropagation(true);
return $response;
}
else if ($auth->hasIdentity() && $session->offsetGet('sessionstart') < ($_SERVER['REQUEST_TIME'] - 10800) && $this->route_root != 'zfcuser')
{
$response = new \Zend\Http\PhpEnvironment\Response();
$response->getHeaders()->addHeaderLine('Location', '/user/logout');
$response->setStatusCode(302);
$response->sendHeaders();
$e->stopPropagation(true);
return $response;
}
else if ($auth->hasIdentity())
{
$session->offsetSet('sessionstart', $_SERVER['REQUEST_TIME']);
}
}

Is there a way to add a log writer factory into the logger configuration?

I write logger config and used Zend\Log\LoggerServiceFactory for configure Logger. If I use base writers all work. But I want add to a logger my own writer who created by factory, and this is donn`t work.
Is there a way to use config and base logger factory to add writer from own factory?
Update: here is my code
This is my config where I define factory for Logger, factory for writer and configs for base writers
// config/autoload/global.php
return array(
'service_manager' => array(
'factories' => array(
'Logger' => 'Zend\Log\LoggerServiceFactory',
'Rollbar' => 'Yassa\Rollbar\Log\Writer\Rollbar'
),
),
'log' => array(
'writers' => array(
array(
'name' => 'stream',
'options' => array(
...
),
),
array(
'name' => 'stream',
'options' => array(
...
),
),
array(
'name' => 'Rollbar',
),
),
),
);
Yassa\Rollbar\Log\Writer\Rollbar - it`s a factory from yassa\rollbar module (github)
Without Rollbar writer this config does what I need - create and configure standart writers.
Thus I call logger from aontroller:
$this->getServiceLocator()->get('Logger')->info('test');
I researched the component code and did not find a way to use the factory to create my own writer. Unfortunately currently this is not possible.
I think I found the solution. The solution is not very nice, but nothing better I figured it out.
I wrote a replacement for standard factory (\Zend\Log\LoggerServiceFactory) and transfer logger configuration from the Logger constructor in the my factory. In addition, I added a check for the writer factory.
Here is the resulting class:
<?php
namespace Application\Factory;
use Zend\Log\Exception\InvalidArgumentException;
use Zend\Log\Logger;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class LoggerServiceFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
// Configure the logger
$config = $serviceLocator->get('Config');
$options = isset($config['log']) ? $config['log'] : array();
$logger = new Logger();
if (is_array($options)) {
if (isset($options['writers']) && is_array($options['writers'])) {
foreach ($options['writers'] as $writer) {
if (!isset($writer['name'])) {
throw new InvalidArgumentException('Options must contain a name for the writer');
}
$priority = (isset($writer['priority'])) ? $writer['priority'] : null;
$writerOptions = (isset($writer['options'])) ? $writer['options'] : null;
if ($serviceLocator->has($writer['name'])) {
$writer = $serviceLocator->get($writer['name']);
$logger->addWriter($writer, $priority, $writerOptions);
} else {
$logger->addWriter($writer['name'], $priority, $writerOptions);
}
}
}
if (isset($options['exceptionhandler']) && $options['exceptionhandler'] === true) {
Logger::registerExceptionHandler($logger);
}
if (isset($options['errorhandler']) && $options['errorhandler'] === true) {
Logger::registerErrorHandler($logger);
}
}
return $logger;
}
}
Can anybody suggest a better solution?

Configure multi DB connections on ZF2

I'm actualy a beginner in ZF2
I managed to use multiple BDD on the same application and it works.
(I'm talking about this : configure multiple databases in zf2 ).
Though, I'd have a little question...
Is it ok to declare my custom factory in global.php ? (in the service_manager thing).
Or do I need to declare it inside each module ? (in module.php)
Declaring it into global.php actualy works, but I was wondering if it's not breaking the spirit of the framework or something...
Thanks for your time !
Tounu
Store your connection settings in a local config:
config/autoload/local.php
this is in case you have multiple environments with different databases/connection credentials etc. for example, you may gave a staging setup, and a live setup, both using a separate database.
You can also then use multiple connections inside your application this way too.
there's nothing to stop you setting up multiple connections in here, and using them as needed in your database adapters etc.
local.php
return array(
/**
* Database Connection One
*/
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=dbnamehere;host=localhost',
'username' => 'root',
'password' => '',
),
/**
* Database Connection Two
*/
'db_two' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=anotherdb;host=localhost',
'username' => 'root',
'password' => '',
),
If you are using version control (you should be!) this also allows you to exclude the .local config files from your repository to avoid storing password etc in there, and allows for easier deployment to multiple environments.
You can setup multiple adapters to use different connections too:
global.php
return array(
/**
* Database Adapter(s)
*/
'service_manager' => array(
'factories' => array(
/**
* Adapter One - this factory will use the default 'db' connection
*/
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
/**
* Adapter Two - use the second connection
*/
'Application\Db\AdapterTwo' => function($sm) {
$config = $sm->get('Config');
return new Adapter($config['db_two']);
},
),
),
);
To connect multiple database at a time, follow these steps:
Step 1:
Create /module/MyModule/ and add into application.config.ini to access.
Step 2:
Create Module.php in /module/MyModule/ directory with the following scripts
<?php
namespace MyModule;
use MyModule\MyAdapterFactory;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
class Module implements ServiceProviderInterface{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__.'/Db/Adapter/',
),
),
);
}
public function getServiceConfig()
{
return array(
'factories' => array(
'adapter1' => new MyAdapterFactory('db_adapter1'),
'adapter2' => new MyAdapterFactory('db_adapter2'),
),
);
}
}
Step 3:
Create MyAdapterFactory.php in the path: /module/MyModule/src/MyModule/Db/Adapter/ with the following scripts.
<?php
namespace MyModule;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\Adapter;
class MyAdapterFactory implements FactoryInterface
{
protected $configKey;
public function __construct($key)
{
$this->configKey = $key;
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('Config');
return new Adapter($config[$this->configKey]);
}
}
?>
Step 4:
Add the following scripts in your getServiceConfig().
'YourModule\Model\YourTable' => function($sm) {
$tableGateway = $sm->get('YourTableGateway');
$table = new YourTable($tableGateway);
return $table;
},
'YourTableGateway' => function ($sm) {
$adapter1 = $sm->get('adapter1');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new YourModel());
return new TableGateway('tbl_name', $adapter1, null, $resultSetPrototype);
},
Step 5:
Add method into your controller to access your table as below:
Declare this on start of the class:
protected $this->yourTable;
public function getYourTable()
{
if (!$this->yourTable) {
$sm = $this->getServiceLocator();
$this->yourTable = $sm->get('YourModule\Model\YourTable');
}
return $this->yourTable;
}
Then, You can call your Model methods for Select, Update, Insert using this function (getYourTable()) in your controller.

How to set db adapter to Validator NoRecordExists and use it in controller?

I recently started learning ZF2 and hope someone can help me with this.
I am working my way through Rob Allen's Zend Framework 2 Tutorial (many thanks to #rob-allen).
Also I use a solution of #AlloVince and #Maciej How to set db adapter to Validator RecordExists in Zend Framework 2 (many thanks to both authors for it) and I confused because didn't to use this solution in editAction.
I see Fatal error: Call to a member function get() on a non-object in 'adapter' => $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter').
1) In the Module.php added
public function getServiceConfig()
{
return array(
'invokables' => array(
'RegionModel' => 'FcLibraries\Model\Region', //<-- added it
),
'factories' => array(
'FcLibraries\Model\RegionTable' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$table = new RegionTable($dbAdapter);
return $table;
},
),
);
}
2) In the Region.php added
/**
* #var
*/
protected $serviceLocator;
/**
* #param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator
* #return Library
*/
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
return $this;
}
/**
* #return \Zend\ServiceManager\ServiceLocatorInterface
*/
public function getServiceLocator()
{
return $this->serviceLocator;
}
and
$inputFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => $this->_filters,
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'table' => $this->table,
'field' => 'name',
//'exclude' => array(
// 'field' => 'id',
// 'value' => $this->id
//),
'adapter' => $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter'),
),
),
),
)));
3) In the RegionController.php in addAction using
$model = $this->getServiceLocator()->get('RegionModel');
instead of $model = new Region();.
This works fine for addAction, But I can not understand how I should use it in editAction.
My
public function editAction()
{
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('zfcadmin/region', array(
'action' => 'add'
));
}
$data = $this->getRegionTable()->get($id);
$form = new RegionForm();
$form->bind($data);
$form->get('submitBtn')->setAttribute('value', 'Save');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setInputFilter($data->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getRegionTable()->save($form->getData());
return $this->redirect()->toRoute('zfcadmin/regions');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
My RegionTable has the following code:
/**
* #param \Zend\Db\Adapter\Adapter $adapter
*/
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
$this->resultSetPrototype = new ResultSet();
$this->resultSetPrototype->setArrayObjectPrototype(new Region());
$this->initialize();
}
public function get($id)
{
$id = (int)$id;
$rowSet = $this->select(array('id' => $id));
$row = $rowSet->current();
if (!$row) {
throw new \Exception("Could not find row $id");
}
return $row;
}
Many thanks to all who will answer my question.
Best regards, Ruslan.
Instead of using the form filter from the entity which you gathered from the table you should instantiate a new entity via the service manager to use the database adapter.
You have a few options:
Move the input filter to its own class and instantiate via the service manager so your database adapter is injected.
Change the prototype object in the table gateway factory to be instantiated via the service manager factory.
Instantiate a separate entity via the service manager and get the input filter from there.
I personally would go for option 1 as it separates the code better.
Some examples:
Option 1 (my choice):
This involves moving the filter to its own file and class, creating a factory for it whilst injecting the database adapter. We will then, in the controller, get the filter via the service manager and apply the filter to the form.
So first move your filter to a file in ModName\src\ModName\Form\RegionFilter.php, obviosly replacing ModName with your module name.
and change the code to like so:
<?php
namespace Region\Form;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
use Zend\Db\Adapter\Adapter;
class RegionFilter implements InputFilterAwareInterface {
/**
* #var inputFilter
*/
protected $inputFilter;
/**
* #var Database Adapter
*/
protected $dbAdapter;
/**
* #param \Zend\InputFilter\InputFilterInterface $inputFilter
* #throws \Exception
*/
public function setInputFilter(InputFilterInterface $inputFilter) {
throw new \Exception("Not used");
}
/**
* #param \Zend\Db\Adapter $dbAdapter
*/
public function __construct(Adapter $dbAdapter) {
$this->dbAdapter = $dbAdapter;
}
/**
*
* #return Zend\Db\Adapter
*/
public function getDbAdapter() {
return $this->dbAdapter;
}
/**
* #return \Zend\InputFilter\InputFilter
*
* Get the input filter (build it first)
*/
public function getInputFilter() {
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => $this->_filters,
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 30,
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'table' => $this->table,
'field' => 'name',
//'exclude' => array(
// 'field' => 'id',
// 'value' => $this->id
//),
'adapter' => $this->getDbAdapter(),
),
),
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
?>
You would then create a factory like so in Module.php:
public function getServiceConfig()
{
return array(
'factories' => array(
'ModName\Form\RegionFilter' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
return new RegionFilter($dbAdapter);
},
),
);
}
And finally in your controller, just do the following:
if ($request->isPost()) {
$filter = $this->getServiceLocator()->get('ModName\Form\RegionFilter');
$form->setInputFilter($filter->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getRegionTable()->save($form->getData());
return $this->redirect()->toRoute('zfcadmin/regions');
}
}
Option 2:
This involves constructing your table with an instance of Region injected. Then you can set the prototype to this.
So in your table construct:
public function __construct(Adapter $adapter, Region $region)
{
$this->adapter = $adapter;
$this->resultSetPrototype = new ResultSet();
$this->resultSetPrototype->setArrayObjectPrototype($region);
$this->initialize();
}
And then your factory:
public function getServiceConfig()
{
return array(
'invokables' => array(
'RegionModel' => 'FcLibraries\Model\Region',
),
'factories' => array(
'FcLibraries\Model\RegionTable' => function ($sm) {
$region = $sm->get('RegionModel');
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$table = new RegionTable($dbAdapter,$region);
return $table;
},
),
);
}
You should be able to leave the rest of the code as is. Eg the controller. Now I have not tested this method so I'm not 100% it will work, but I think it should. The other two methods I have used previously myself.
Option 3 (the simplest):
This involves getting a separate region model via the service manager and using that to apply the input filter to the form.
public function editAction()
{
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('zfcadmin/region', array(
'action' => 'add'
));
}
$data = $this->getRegionTable()->get($id);
$form = new RegionForm();
$form->bind($data);
$form->get('submitBtn')->setAttribute('value', 'Save');
$request = $this->getRequest();
if ($request->isPost()) {
$region = $this->getServiceLocator()->get('RegionModel');
$form->setInputFilter($region->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getRegionTable()->save($form->getData());
return $this->redirect()->toRoute('zfcadmin/regions');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
I have not tested the code but you should get the gist. Any questions just ask.
For doing the validation for "Username already exists or not", Do the following simple way of Service Manager config settings like:
// config/autoload/global.php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2tutorial;host=localhost',
),
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => function ($serviceManager) {
$adapterFactory = new Zend\Db\Adapter\AdapterServiceFactory();
$adapter = $adapterFactory->createService($serviceManager);
\Zend\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter);
return $adapter;
}
),
)
);
and add the following array into getInputFilter():
array(
'table' => 'users',
'field' => 'username',
'adapter' => \Zend\Db\TableGateway\Feature\GlobalAdapterFeature::getStaticAdapter();
)

Resources