I'm fairly new to Zend and I am trying to set a session namespace variable. I am receiving an error message stating "Configuration is missing a "session_config" key, or the value of that key is not an array".
I've followed the documentation provided by Zend on the subject but I'm coming up a bit short on how it all ties together.
I've configured the session manager in the global config file as follows:
'session_manager' => [
'config' => [
'class' => Session\Config\SessionConfig::class,
'options' => [
'name' => 'user',
],
],
'storage' => Session\Storage\SessionArrayStorage::class,
'validators' => [
Session\Validator\RemoteAddr::class,
Session\Validator\HttpUserAgent::class,
],
],
I created the session manager in the Module class as follows
use Zend\Session\SessionManager;
use Zend\Session\Config\SessionConfig;
use Zend\Session\Container;
use Zend\Session\Validator;
use Zend\Mvc\ModuleRouteListener;
class Module implements ConfigProviderInterface
{
public function onBootstrap($e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$this->bootstrapSession($e);
}
public function bootstrapSession($e)
{
$session = new SessionManager();
$session->start();
$container = new Container('initialized');
if (isset($container->init)) {
return;
}
$serviceManager = $e->getApplication()->getServiceManager();
$request = $serviceManager->get('Request');
$session->regenerateId(true);
$container->init = 1;
$container->remoteAddr = $request->getServer()->get('REMOTE_ADDR');
$container->httpUserAgent = $request->getServer()->get('HTTP_USER_AGENT');
$config = $serviceManager->get('Config');
if (! isset($config['session'])) {
return;
}
$sessionConfig = $config['session'];
if (! isset($sessionConfig['validators'])) {
return;
}
$chain = $session->getValidatorChain();
foreach ($sessionConfig['validators'] as $validator) {
switch ($validator) {
case Validator\HttpUserAgent::class:
$validator = new $validator($container->httpUserAgent);
break;
case Validator\RemoteAddr::class:
$validator = new $validator($container->remoteAddr);
break;
default:
$validator = new $validator();
}
$chain->attach('session.validate', array($validator, 'isValid'));
}
}
public function getServiceConfig()
{
return [
'factories' => [
SessionManager::class => function ($container) {
$config = $container->get('config');
if (! isset($config['session'])) {
$sessionManager = new SessionManager();
Container::setDefaultManager($sessionManager);
return $sessionManager;
}
$session = $config['session'];
$sessionConfig = null;
if (isset($session['config'])) {
$class = isset($session['config']['class'])
? $session['config']['class']
: SessionConfig::class;
$options = isset($session['config']['options'])
? $session['config']['options']
: [];
$sessionConfig = new $class();
$sessionConfig->setOptions($options);
}
$sessionStorage = null;
if (isset($session['storage'])) {
$class = $session['storage'];
$sessionStorage = new $class();
}
$sessionSaveHandler = null;
if (isset($session['save_handler'])) {
// class should be fetched from service manager
// since it will require constructor arguments
$sessionSaveHandler = $container->get($session['save_handler']);
}
$sessionManager = new SessionManager(
$sessionConfig,
$sessionStorage,
$sessionSaveHandler
);
Container::setDefaultManager($sessionManager);
return $sessionManager;
},
],
];
}
I defined the session container namespace in the module.config.php file as follows:
'session_containers' => [
'UserNamespace'
],
I try to access the namespace in the factory of the controller as follows:
namespace User\Factory;
use Interop\Container\ContainerInterface;
use Zend\Authentication\AuthenticationService;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\Session\Container;
use User\Controller\AuthController;
use User\Model\UserRepositoryInterface;
use User\Form\LoginForm;
class AuthControllerFactory implements FactoryInterface
{
/**
* #param ContainerInterface $container
* #param string $requestedName
* #param null|array $options
* #return AuthController
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$formManager = $container->get('FormElementManager');
$sessionContainer = $container->get('UserNamespace');
return new AuthController(
$container->get(UserRepositoryInterface::class),
$formManager->get(LoginForm::class),
$sessionContainer
);
}
}
And finally I try to call the session namespace variable in the controller as follows:
namespace User\Controller;
use User\Form\LoginForm;
use User\Model\User;
use User\Model\UserRepositoryInterface;
use Zend\Session\Container;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class AuthController extends AbstractActionController
{
/**
* #var UserRepositoryInterface
*/
private $userRepository;
/**
* #var LoginForm
*/
private $loginForm;
private $sessionContainer;
/**
* #param UserRepositoryInterface $userRepository
* #param LoginForm $loginForm
*/
public function __construct(
UserRepositoryInterface $userRepository,
LoginForm $loginForm,
$sessionContainer
) {
$this->userRepository = $userRepository;
$this->loginForm = $loginForm;
$sessionContainer;
}
public function loginAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel(['form' => $this->loginForm]);
if (! $request->isPost()) {
return $viewModel;
}
$this->loginForm->setData($request->getPost());
if (! $this->loginForm->isValid()) {
return $viewModel;
}
$loginAttempt = $this->loginForm->getData();
// var_dump($loginAttempt); die;
try {
$user = $this->userRepository->retrieveUserByUsername($loginAttempt['username']);
} catch (\Exception $ex) {
throw $ex;
}
// var_dump($user); die;
try {
$isLogin = $this->userRepository->validatePassword($user, $loginAttempt['password']);
} catch (\Exception $ex) {
throw $ex;
}
// var_dump($isLogin); die;
if($isLogin == true) {
$sessionContainer->test = "This is a test";
}
var_dump($sessionContainer->test); die;
}
I'm sure I'm a bit mixed up on my execution to make this work so any assistance or advice you can provide will be greatly appreciated.
whats this wrong with this? I'm new in zend framework...........................................................................................................................
this is my folder struct
UserControllerFactory.php
<?php
namespace Admin\Controller\Factory;
use Admin\Controller\UserController;
use User\Entity\User;
use Admin\Form\UserForm;
use User\Model\UserTable;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Entity;
use Interop\Container\ContainerInterface;
class UserControllerFactory
{
public function __invoke(ContainerInterface $container)
{
/** #var EntityManager $entityManager */
$entityManager = $container->get(EntityManager::class);
$repository = $entityManager->getRepository(User::class);
$userForm = $container->get(UserForm::class);
return new UserController($entityManager, $repository, $userForm);
}
}
UserController.php
<?php
namespace Admin\Controller;
//use User\Entity\User;
use Admin\Form\UserForm;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Zend\Hydrator\ClassMethods;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\Http\Request;
use Zend\View\Model\ViewModel;
class UserController extends AbstractActionController
{
/**
* #var EntityRepository
*/
private $repository;
/**
* #var EntityManager
*/
private $entityManager;
private $form;
public function __constructor(EntityManager $entityManager, EntityRepository $repository, UserForm $form){
$this->form = $form;
$this->repository = $repository;
$this->entityManager = $entityManager;
}
public function indexAction()
{
return new ViewModel([
'users' => $this->repository->fetchAll()
]);
}
public function addAction()
{
$form = $this->form;
$form->get('submit')->setValue('Adicionar');
$request = $this->getRequest();
if (!$request->isPost()) {
return ['form' => $form];
}
$form->setData($request->getPost());
if (!$form->isValid()) {
return ['form' => $form];
}
$post = $form->getData();
$this->entityManager->persist($post);
$this->entityManager->flush();
return $this->redirect()->toRoute('admin/user');
}
public function editAction()
{
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id || !($post = $this->repository->find($id))) {
return $this->redirect()->toRoute('admin/user');
}
$form = $this->form;
$form->bind($post);
$form->get('submit')->setAttribute('value', 'Edit Post');
$request = $this->getRequest();
if (!$request->isPost()) {
return [
'id' => $id,
'form' => $form
];
}
$form->setData($request->getPost());
if (!$form->isValid()) {
return [
'id' => $id,
'form' => $form
];
}
$this->entityManager->flush();
return $this->redirect()->toRoute('admin/user');
}
public function deleteAction()
{
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id || !($post = $this->repository->find($id))) {
return $this->redirect()->toRoute('admin/user');
}
$this->entityManager->remove($post);
$this->entityManager->flush();
return $this->redirect()->toRoute('admin/user');
}
}
UserTable.php
<?php
/**
* Created by PhpStorm.
* User: jho
* Date: 24/06/2017
* Time: 18:55
*/
namespace User\Model\Factory;
use Zend\Db\Exception\RuntimeException;
use Zend\Db\TableGateway\TableGatewayInterface;
class UserTable
{
private $tableGateway;
public function find($id)
{
$id = (int)$id;
$rowset = $this->tableGateway->select(['id' => $id]);
$row = $rowset->current();
if (!row) {
throw new RuntimeException(sprintf(
'Could not retrieve the row %d', $id
));
}
return $row;
}
public function fetchAll(){
return $this->tableGateway->select();
}
public function save(User $user){
$data = [
'username'=>$user->username,
'fullname'=>$user->fullname,
'password'=>$user->password,
];
$id = (int) $user->id;
if((int)$user->id === 0){
$this->tableGateway->insert($data);
return;
}
if(!$this->find($id)){
throw new RuntimeException(sprintf(
'Could not retrieve the row %d', $id
));
}
$this->tableGateway->update($data, ['id'=>$id]);
}
}
User.php
<?php
namespace User\Model;
class User
{
public $id;
public $fullname;
public function exchangeArray(array $data){
$this->id = (!empty($data['id'])) ? $data['id']: null;
$this->title = (!empty($data['fullname'])) ? $data['fullname']: null;
}
public function getArrayCopy(){
return[
'id'=>$this->id,
'fullname'=>$this->fullname,
];
}
}
You are mixing up two different approaches of retrieving data from your database.
You can either use the Zend approach as in TableGateway's or you can go with Doctrine (EntityManager/Repositories).
So you've got to make a choice between one of the methods you want to use within your controller.
So if you want to stick with Doctrine, you could take a look at the following slides of Ocramius: http://ocramius.github.io/presentations/doctrine-orm-and-zend-framework-2/#/59
So you pretty much have to update your User model:
namespace User\Model;
use Doctrine\ORM\Mapping AS ORM;
/**
* #ORM\Entity()
*/
class User
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
public $id;
/** #ORM\Column(type="string") */
public $fullname;
public function exchangeArray(array $data){
$this->id = (!empty($data['id'])) ? $data['id']: null;
$this->title = (!empty($data['fullname'])) ? $data['fullname']: null;
}
public function getArrayCopy(){
return[
'id'=>$this->id,
'fullname'=>$this->fullname,
];
}
}
Update the following file module.config.php of your User module and add the following to your configuration:
array(
'doctrine' => array(
'driver' => array(
'application_entities' => array(
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/User/Model')
),
'orm_default' => array(
'drivers' => array(
'User\model' => 'application_entities'
)
),
)
),
Notice that this requires the Doctrine-ORM-module. See: https://github.com/doctrine/DoctrineORMModule
I'm trying to do mock for viewHelper and can't do this.
When I am trying to run phpunit I get the assert error "Failed asserting that two strings are equal." because the analiticHelper hasn't been overwriten. I wrote setAllowOverride(true) for my ServiseManager, but this didn't help.
Could you please tell me how can I do mock for viewHelper in Zend Framework 2?
I will appreciate your time and help!
Thanks!
# module\Application\test\Controller\IndexControllerTest.php
<?php
namespace ApplicationTest\Controller;
use Application\Controller\IndexController;
use PHPUnit_Framework_TestCase as TestCase;
use ApplicationTest\Bootstrap;
class HttpTest extends TestCase {
/**
* #var IndexController
*/
// private $indexController;
protected $traceError = false;
public function setUp() {
$this->sm = Bootstrap::getServiceManager();
$this->em = $this->sm->get('Doctrine\ORM\EntityManager');
}
public function testAction() {
$mockAnaliticHelper = $this->getMockBuilder(\Application\View\Helper\AnaliticHelper::class)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->getMock();
$mockAnaliticHelper->method('getKey')
->willReturn('some-value');
$this->assertEquals('some-value', $mockAnaliticHelper->getKey()); // it's ok
$this->sm->setAllowOverride(true);
$this->sm->setService('analiticHelper', $mockAnaliticHelper); // before
$viewHelperManager = $this->sm->get('ViewHelperManager');
$analiticHelper = $viewHelperManager->get('analiticHelper');
$this->sm->setService('analiticHelper', $mockAnaliticHelper); // after
$key = $analiticHelper->getKey(); // return 'web'
$this->assertEquals('some-value', $analiticHelper->getKey()); // return error
}
}
# Module.php
<?php
....
public function getViewHelperConfig()
{
return array(
'factories' => array(
...,
'analiticHelper' => function($sm){
$locator = $sm->getServiceLocator();
$config = $locator->get('config');
$em = $locator->get('Doctrine\ORM\EntityManager');
$viewHelper = new \Application\View\Helper\AnaliticHelper($em, $locator, $config);
return $viewHelper;
},
),
);
}
# module\Application\src\Application\View\Helper\AnaliticHelper.php
<?php
namespace Application\View\Helper;
use Zend\View\Helper\HelperInterface;
use Zend\View\Renderer\RendererInterface as Renderer;
use Doctrine\ORM\EntityManager;
use ZfcUser\Entity\UserInterface;
use Zend\Session\Container;
class AnaliticHelper implements \Zend\View\Helper\HelperInterface{
protected $_em;
protected $_serviceLocator;
protected $_config;
const SESSION_CONTANIER = 'analitic';
const SESSION_KEY = 'analiticKey';
const DEFAULT_KEY = 'web';
public function __construct(EntityManager $em, $serviceLocator, $config) {
$this->_em = $em;
$this->_serviceLocator = $serviceLocator;
$this->_config = $config;
$router = $this->_serviceLocator->get('router');
$request = $this->_serviceLocator->get('request');
$this->routeMatch = $router->match($request);
}
public function __invoke(){
return $this;
}
public function getKey(){
// some actions
return self::DEFAULT_KEY;
}
/**
* Set the View object
*
* #param Renderer $view
* #return HelperInterface
*/
public function setView(Renderer $view)
{
$this->view = $view;
return $this;
}
/**
* Get the View object
*
* #return Renderer
*/
public function getView()
{
return $this->view;
}
}
I'm integrating Zend and Doctrine 2 to work with MongoDB.
I'm using the quickstart skeleton.
Here is the Doctrine.php
<?php
use Doctrine\MongoDB\Connection;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Mapping\Annotations;
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
class Resource_Doctrine extends Zend_Application_Resource_ResourceAbstract
{
protected $_options = array();
private $manager;
public function __set($config, $null) {
$this->_options = array(
'connection' => array(
'dbname' => $config['connection']['dbname'],
),
'modelDir' => $config['modelDir'],
'proxyDir' => $config['proxyDir'],
'proxyNamespace' => $config['proxyNamespace'],
'hydratorDir' => $config['proxyDir'],
'hydratorNamespace' => $config['proxyNamespace'],
'autoGenerateProxyClasses' => $config['autoGenerateProxyClasses']
);
}
public function init()
{
$zendConfig = $this->getOptions();
if(!empty($zendConfig)) Zend_Registry::set('config', $zendConfig);
$options = Zend_Registry::get('config');
$this->__set($options,null);
$config = new \Doctrine\ODM\MongoDB\Configuration;
$config->setDefaultDB($options['connection']['dbname']);
$config->setProxyDir($this->_options['proxyDir']);
$config->setProxyNamespace($this->_options['proxyNamespace']);
$config->setHydratorDir($this->_options['hydratorDir']);
$config->setHydratorNamespace($this->_options['hydratorNamespace']);
$config->setMetadataDriverImpl(AnnotationDriver::create($this->_options['modelDir']));
Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver::registerAnnotationClasses();
$dm = DocumentManager::create(new Connection(), $config);
return $dm;
}
}
The class
<?php
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/** #ODM\Document */
class Application_Model_Guestbook
{
/**
* #ODM\Id
*/
public $id;
/** #ODM\String */
public $email;
/** #ODM\String */
public $comment;
/** #ODM\Date */
public $created;
public function setGuestbook($comment)
{
$this->email = $comment['email'];
$this->comment = $comment['comment'];
$this->created = date('d-m-Y H:i:s');
}
public function getGuestbook()
{
return $this;
}
}
And the action
public function signAction()
{
$request = $this->getRequest();
$this->getHelper('loadResource')->form('sign', 'Guestbook');
$form = new Application_Form_Guestbook();
if ($this->getRequest()->isPost()) {
if ($form->isValid($request->getPost())) {
$guestbook = new Application_Model_Guestbook;
$guestbook->setGuestbook($form->getValues());
try
{
$this->em->persist($guestbook);
$this->em->flush($guestbook);
return $this->_helper->redirector('index');
}
catch (Exception $e)
{
throw new Exception($e);
}
}
}
$this->view->form = $form;
}
I'm geting the error: Catchable fatal error: Argument 3 passed to Doctrine\ODM\MongoDB\Hydrator\HydratorFactory::hydrate() must be of the type array, null given, called in /home/gabiru/www/twitradar_mongo/library/Doctrine/ODM/MongoDB/UnitOfWork.php on line 2518
I've searched and don't find any result of anyone with the same problem, anyone have any idea about it?
The 3rd argument is the variable $hint, and I don't know where the argument is set.
Do anyone know why this occurs?
as far I can get, the child class method is declared in the same way as parent's.
Thanks!
here is my kernel code:
<?php
require_once __DIR__.'/../src/autoload.php';
use Symfony\Framework\Kernel;
use Symfony\Components\DependencyInjection\Loader\YamlFileLoader as ContainerLoader;
use Symfony\Components\Routing\Loader\YamlFileLoader as RoutingLoader;
use Symfony\Framework\KernelBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\ZendBundle\ZendBundle;
use Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle;
use Symfony\Bundle\DoctrineBundle\DoctrineBundle;
use Symfony\Bundle\DoctrineMigrationsBundle\DoctrineMigrationsBundle;
use Symfony\Bundle\DoctrineMongoDBBundle\DoctrineMongoDBBundle;
use Symfony\Bundle\PropelBundle\PropelBundle;
use Symfony\Bundle\TwigBundle\TwigBundle;
use Application\UfaraBundle\UfaraBundle;
class UfaraKernel extends Kernel {
public function registerRootDir() {
return __DIR__;
}
public function registerBundles() {
$bundles = array(
new KernelBundle(),
new FrameworkBundle(),
new ZendBundle(),
new SwiftmailerBundle(),
new DoctrineBundle(),
//new DoctrineMigrationsBundle(),
//new DoctrineMongoDBBundle(),
//new PropelBundle(),
//new TwigBundle(),
new UfaraBundle(),
);
if ($this->isDebug()) {
}
return $bundles;
}
public function registerBundleDirs() {
$bundles = array(
'Application' => __DIR__.'/../src/Application',
'Bundle' => __DIR__.'/../src/Bundle',
'Symfony\\Framework' => __DIR__.'/../src/vendor/symfony/src/Symfony/Framework',
'Symfony\\Bundle' => __DIR__.'/../src/vendor/symfony/src/Symfony/Bundle',
);
return $bundles;
}
public function registerContainerConfiguration(LoaderInterface $loader) {
return $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
public function registerRoutes() {
$loader = new RoutingLoader($this->getBundleDirs());
return $loader->load(__DIR__.'/config/routing.yml');
}
}
here is the parent class code:
<?php
namespace Symfony\Framework;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Resource\FileResource;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Loader\DelegatingLoader;
use Symfony\Component\DependencyInjection\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Framework\ClassCollectionLoader;
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier#symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* The Kernel is the heart of the Symfony system. It manages an environment
* that can host bundles.
*
* #author Fabien Potencier <fabien.potencier#symfony-project.org>
*/
abstract class Kernel implements HttpKernelInterface, \Serializable
{
protected $bundles;
protected $bundleDirs;
protected $container;
protected $rootDir;
protected $environment;
protected $debug;
protected $booted;
protected $name;
protected $startTime;
protected $request;
const VERSION = '2.0.0-DEV';
/**
* Constructor.
*
* #param string $environment The environment
* #param Boolean $debug Whether to enable debugging or not
*/
public function __construct($environment, $debug)
{
$this->environment = $environment;
$this->debug = (Boolean) $debug;
$this->booted = false;
$this->rootDir = realpath($this->registerRootDir());
$this->name = basename($this->rootDir);
if ($this->debug) {
ini_set('display_errors', 1);
error_reporting(-1);
$this->startTime = microtime(true);
} else {
ini_set('display_errors', 0);
}
}
public function __clone()
{
if ($this->debug) {
$this->startTime = microtime(true);
}
$this->booted = false;
$this->container = null;
$this->request = null;
}
abstract public function registerRootDir();
abstract public function registerBundles();
abstract public function registerBundleDirs();
abstract public function registerContainerConfiguration(LoaderInterface $loader);
/**
* Checks whether the current kernel has been booted or not.
*
* #return boolean $booted
*/
public function isBooted()
{
return $this->booted;
}
/**
* Boots the current kernel.
*
* This method boots the bundles, which MUST set
* the DI container.
*
* #throws \LogicException When the Kernel is already booted
*/
public function boot()
{
if (true === $this->booted) {
throw new \LogicException('The kernel is already booted.');
}
if (!$this->isDebug()) {
require_once __DIR__.'/bootstrap.php';
}
$this->bundles = $this->registerBundles();
$this->bundleDirs = $this->registerBundleDirs();
$this->container = $this->initializeContainer();
// load core classes
ClassCollectionLoader::load(
$this->container->getParameter('kernel.compiled_classes'),
$this->container->getParameter('kernel.cache_dir'),
'classes',
$this->container->getParameter('kernel.debug'),
true
);
foreach ($this->bundles as $bundle) {
$bundle->setContainer($this->container);
$bundle->boot();
}
$this->booted = true;
}
/**
* Shutdowns the kernel.
*
* This method is mainly useful when doing functional testing.
*/
public function shutdown()
{
$this->booted = false;
foreach ($this->bundles as $bundle) {
$bundle->shutdown();
$bundle->setContainer(null);
}
$this->container = null;
}
/**
* Reboots the kernel.
*
* This method is mainly useful when doing functional testing.
*
* It is a shortcut for the call to shutdown() and boot().
*/
public function reboot()
{
$this->shutdown();
$this->boot();
}
/**
* Gets the Request instance associated with the master request.
*
* #return Request A Request instance
*/
public function getRequest()
{
return $this->request;
}
/**
* Handles a request to convert it to a response by calling the HttpKernel service.
*
* #param Request $request A Request instance
* #param integer $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
* #param Boolean $raw Whether to catch exceptions or not
*
* #return Response $response A Response instance
*/
public function handle(Request $request = null, $type = HttpKernelInterface::MASTER_REQUEST, $raw = false)
{
if (false === $this->booted) {
$this->boot();
}
if (null === $request) {
$request = $this->container->get('request');
} else {
$this->container->set('request', $request);
}
if (HttpKernelInterface::MASTER_REQUEST === $type) {
$this->request = $request;
}
$response = $this->container->getHttpKernelService()->handle($request, $type, $raw);
$this->container->set('request', $this->request);
return $response;
}
/**
* Gets the directories where bundles can be stored.
*
* #return array An array of directories where bundles can be stored
*/
public function getBundleDirs()
{
return $this->bundleDirs;
}
/**
* Gets the registered bundle names.
*
* #return array An array of registered bundle names
*/
public function getBundles()
{
return $this->bundles;
}
/**
* Checks if a given class name belongs to an active bundle.
*
* #param string $class A class name
*
* #return Boolean true if the class belongs to an active bundle, false otherwise
*/
public function isClassInActiveBundle($class)
{
foreach ($this->bundles as $bundle) {
$bundleClass = get_class($bundle);
if (0 === strpos($class, substr($bundleClass, 0, strrpos($bundleClass, '\\')))) {
return true;
}
}
return false;
}
/**
* Returns the Bundle name for a given class.
*
* #param string $class A class name
*
* #return string The Bundle name or null if the class does not belongs to a bundle
*/
public function getBundleForClass($class)
{
$namespace = substr($class, 0, strrpos($class, '\\'));
foreach (array_keys($this->getBundleDirs()) as $prefix) {
if (0 === $pos = strpos($namespace, $prefix)) {
return substr($namespace, strlen($prefix) + 1, strpos($class, 'Bundle\\') + 7);
}
}
}
public function getName()
{
return $this->name;
}
public function getSafeName()
{
return preg_replace('/[^a-zA-Z0-9_]+/', '', $this->name);
}
public function getEnvironment()
{
return $this->environment;
}
public function isDebug()
{
return $this->debug;
}
public function getRootDir()
{
return $this->rootDir;
}
public function getContainer()
{
return $this->container;
}
public function getStartTime()
{
return $this->debug ? $this->startTime : -INF;
}
public function getCacheDir()
{
return $this->rootDir.'/cache/'.$this->environment;
}
public function getLogDir()
{
return $this->rootDir.'/logs';
}
protected function initializeContainer()
{
$class = $this->getSafeName().ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
$location = $this->getCacheDir().'/'.$class;
$reload = $this->debug ? $this->needsReload($class, $location) : false;
if ($reload || !file_exists($location.'.php')) {
$this->buildContainer($class, $location.'.php');
}
require_once $location.'.php';
$container = new $class();
$container->set('kernel', $this);
return $container;
}
public function getKernelParameters()
{
$bundles = array();
foreach ($this->bundles as $bundle) {
$bundles[] = get_class($bundle);
}
return array_merge(
array(
'kernel.root_dir' => $this->rootDir,
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => $this->getCacheDir(),
'kernel.logs_dir' => $this->getLogDir(),
'kernel.bundle_dirs' => $this->bundleDirs,
'kernel.bundles' => $bundles,
'kernel.charset' => 'UTF-8',
'kernel.compiled_classes' => array(),
),
$this->getEnvParameters()
);
}
protected function getEnvParameters()
{
$parameters = array();
foreach ($_SERVER as $key => $value) {
if ('SYMFONY__' === substr($key, 0, 9)) {
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
}
}
return $parameters;
}
protected function needsReload($class, $location)
{
if (!file_exists($location.'.meta') || !file_exists($location.'.php')) {
return true;
}
$meta = unserialize(file_get_contents($location.'.meta'));
$time = filemtime($location.'.php');
foreach ($meta as $resource) {
if (!$resource->isUptodate($time)) {
return true;
}
}
return false;
}
protected function buildContainer($class, $file)
{
$parameterBag = new ParameterBag($this->getKernelParameters());
$container = new ContainerBuilder($parameterBag);
foreach ($this->bundles as $bundle) {
$bundle->registerExtensions($container);
if ($this->debug) {
$container->addObjectResource($bundle);
}
}
if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
$container->merge($cont);
}
$container->freeze();
foreach (array('cache', 'logs') as $name) {
$dir = $container->getParameter(sprintf('kernel.%s_dir', $name));
if (!is_dir($dir)) {
if (false === #mkdir($dir, 0777, true)) {
die(sprintf('Unable to create the %s directory (%s)', $name, dirname($dir)));
}
} elseif (!is_writable($dir)) {
die(sprintf('Unable to write in the %s directory (%s)', $name, $dir));
}
}
// cache the container
$dumper = new PhpDumper($container);
$content = $dumper->dump(array('class' => $class));
if (!$this->debug) {
$content = self::stripComments($content);
}
$this->writeCacheFile($file, $content);
if ($this->debug) {
$container->addObjectResource($this);
// save the resources
$this->writeCacheFile($this->getCacheDir().'/'.$class.'.meta', serialize($container->getResources()));
}
}
protected function getContainerLoader(ContainerInterface $container)
{
$resolver = new LoaderResolver(array(
new XmlFileLoader($container, $this->getBundleDirs()),
new YamlFileLoader($container, $this->getBundleDirs()),
new IniFileLoader($container, $this->getBundleDirs()),
new PhpFileLoader($container, $this->getBundleDirs()),
new ClosureLoader($container),
));
return new DelegatingLoader($resolver);
}
/**
* Removes comments from a PHP source string.
*
* We don't use the PHP php_strip_whitespace() function
* as we want the content to be readable and well-formatted.
*
* #param string $source A PHP string
*
* #return string The PHP string with the comments removed
*/
static public function stripComments($source)
{
if (!function_exists('token_get_all')) {
return $source;
}
$output = '';
foreach (token_get_all($source) as $token) {
if (is_string($token)) {
$output .= $token;
} elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
$output .= $token[1];
}
}
// replace multiple new lines with a single newline
$output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
// reformat {} "a la python"
$output = preg_replace(array('/\n\s*\{/', '/\n\s*\}/'), array(' {', ' }'), $output);
return $output;
}
protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
if (false !== #file_put_contents($tmpFile, $content) && #rename($tmpFile, $file)) {
chmod($file, 0644);
return;
}
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
}
public function serialize()
{
return serialize(array($this->environment, $this->debug));
}
public function unserialize($data)
{
list($environment, $debug) = unserialize($data);
$this->__construct($environment, $debug);
}
}
Your answer lies in the imported namespaces. In the Kernel's file, there's this use clause:
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
So that ties LoaderInterface to the fully namespaced class Symfony\Component\DependencyInjection\Loader\LoaderInterface.
Basically making the signature:
public function registerContainerConfiguration(Symfony\Component\DependencyInjection\Loader\LoaderInterface $loader);
In your class, you don't import that namespace. So PHP by default assumes the class is in your namespace (since none of the imported namespaces have that interface name).
So your signature is (since you don't declare a namespace):
public function registerContainerConfiguration(\LoaderInterface $loader);
So to get them to match, simply add the use line to the top of your file:
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;