Suppose I have a query that returns the following data:
RangeId | MinValue | MaxValue | Resolution | UnitId | UnitName
I want to hydrate the object MeasurementRange with the above data.
class MeasurementRange {
public function getRangeId() {...};
public function setRangeId($id) {...};
public function getRange() {...};
public function setRange(Range $range) {...};
public function getUnit() {...};
public function setUnit(Unit $unit) {...};
}
class Range {
public function getMinValue() {...};
public function setMinValue(float $minVal) {...};
public function getMaxValue() {...};
public function setMaxValue(float $maxVal) {...};
public function getResolution {...};
public function setResolution(float $resolution) {...};
}
class Unit {
public function getUnitId() {...};
public function setUnitId(int $id) {...};
public function getUnitName() {...};
public function setUnitName(string $name) {...};
}
As you can see the MeasurementRange object has set Range and Unit objects.
How can I hydrate MeasurementRange and the inner Range and Unit objects from the above query?
PS: I didn't specify protected properties of the objects. I guess they are self-evident.
You need to create a mapper, that will use your dbAdapter to fetch the data as an array, and then use hydrators to hydrate all the objects, and finally add the Range and Unit to MeasurementRange. You could alternatively create a custom hydrator (that would be even better, in terms of single responsibility).
I haven't got time to clean the example below, but that's what it could look like :)
final class LanguageMapper
{
/**
* #param LanguageTable $languageTable
* #param PackageTable $packageTable
* #param Cache $cache
* #param LoggerInterface $logger
*/
public function __construct(LanguageTable $languageTable, PackageTable $packageTable, Cache $cache, LoggerInterface $logger)
{
$this->languageTable = $languageTable;
$this->packageTable = $packageTable;
$this->cache = $cache;
$this->logger = $logger;
}
/**
* #param array $where
*
* #return array List of active languages
*/
public function findActive(array $where = [])
{
try {
if (empty($where) && $this->cache->hasItem('active_languages')) {
return unserialize($this->cache->getItem('active_languages'));
}
} catch (RuntimeException $exception) {
$this->logger->critical($exception->getMessage(), [
'exception' => $exception,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
}
/* #var $adapter \Zend\Db\Adapter\Adapter */
$adapter = $this->languageTable->getGateway()->getAdapter();
$sql = new Sql($adapter);
$select = $sql->select()->columns([Select::SQL_STAR])
->from('language')
->join('package', 'package.id = language.package', Select::SQL_STAR, Select::JOIN_LEFT)
->where(array_merge($where, ['active' => true]))
->order(['position']);
$selectString = $sql->buildSqlString($select);
$resultSet = $adapter->query($selectString, Adapter::QUERY_MODE_EXECUTE);
$languages = [];
$hydrator = new ArraySerializable();
foreach ($resultSet as $result) {
$language = new Language();
$package = new Package();
$hydrator->hydrate((array) $result, $package);
$hydrator->hydrate((array) $result, $language);
$language->setPackage($package);
$languages[] = $language;
}
if (empty($where)) {
try {
$this->cache->setItem('active_languages', serialize($languages));
} catch (RuntimeException $exception) {
$this->logger->warning($exception->getMessage(), [
'exception' => $exception,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
}
}
return $languages;
}
}
Related
i wrote a sample test case for collection like class but weird thing about this is in my testAdd method that i add a item in CustomCollectionService and it changed my parameter too. how can this happend?
class CustomCollectionService
{
/**
* #var Collection $collection
*/
public $collection;
public function makeCollection($arr)
{
$this->collection = collect($arr);
}
/**
* #param Collection $collection
*/
public function setCollection(Collection $collection): void
{
$this->collection = $collection;
}
/**
* #return mixed
*/
public function getCollection()
{
return $this->collection;
}
public function add($item)
{
return $this->collection->add($item);
}
}
and this is my test:
class CustomCollectionTest extends TestCase
{
public $collectionService;
public $collection;
protected function setUp(): void
{
$this->collectionService = new CustomCollectionService();
}
public function testCollectionCreator()
{
$arr = ['sina','1',5];
$this->assertIsArray($arr);
return $arr;
}
/**
* #param $arr
* #depends testCollectionCreator
*/
public function testAction($arr)
{
$this->collectionService->makeCollection($arr);
$this->assertIsArray($this->collectionService->getCollection()->toArray());
return $this->collectionService->getCollection();
}
/**
* #depends testAction
*/
public function testAdd($col)
{
$actualCount = $col->count();
$this->collectionService->setCollection($col);
$manipulatedCollection = $this->collectionService->add(['xx']);
dump($actualCount); // 3
dump($col->count()); //4
$this->assertEquals($actualCount+1, $manipulatedCollection->count());
}
}
Because it is an object. So when you pass the $col object to the CollectionService and call the add method within the CollectionService, it is still the $col object from your test method that is being used.
I am beginner in Laravel. In my project I use repository pattern and Laravel 7.
I have this controller:
class PageController extends Controller
{
protected $model;
/**
* PageController constructor.
* #param PageRepositoryInterface $repository
*/
public function __construct(PageRepositoryInterface $repository)
{
$this->model = $repository;
}
/**
* #param Request $request
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(Request $request)
{
if ($request->input('query') != "") {
$pages = $this->model->search($request->input('query'), 'id', 'asc', [], 30);
} else {
$pages = $this->model->listWithPaginate('id', 'desc', [], 30);
}
return view('admin.pages.list', ['pages' => $pages]);
}
/**
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create()
{
return view('admin.pages.view');
}
/**
* #param PageRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(PageRequest $request)
{
if ($request->isMethod('post')) {
$data = [
'title' => $request->input('title'),
'description' => $request->input('description') ?? $request->input('title'),
'keywords' => $request->input('keywords') ?? $request->input('title'),
'content' => $request->input('content'),
'enable' => $request->input('enable') ?? 0,
'slug' => Str::slug($request->input('title'), '-')
];
$this->model->create($data);
return redirect()->route('page.index')->with('success', __('messages.record_save_info'));
}
}
/**
* #param int $id
* #return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit(int $id)
{
Cache::forget("page.{$id}");
return view('admin.pages.view', ['page' => $this->model->findOrFail($id)]);
}
/**
* #param PageRequest $request
* #param int $id
* #return \Illuminate\Http\RedirectResponse
*/
public function update(PageRequest $request, int $id)
{
if ($request->isMethod('put')) {
$data = [
'title' => $request->input('title'),
'description' => $request->input('description'),
'keywords' => $request->input('keywords'),
'content' => $request->input('content'),
'enable' => $request->input('enable') ?? 0,
'slug' => Str::slug($request->input('title'), '-')
];
$this->model->update($data, $id, 'id');
return redirect()->route('page.index')->with('success', __('messages.record_edit_info'));
}
}
/**
* #param Request $request
* #param int $id
* #return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request, int $id)
{
if ($request->isMethod('delete')) {
$this->model->delete($id);
return redirect()->route('page.index')->with('success', __('messages.record_remove_info'));
}
}
}
and CachingBaseRepository
abstract class CachingBaseRepository implements RepositoryInterface
{
use ScopeActiveTrait;
protected $model;
protected $cacheKey;
protected $cacheTime;
public function all()
{
return Cache::remember($this->cacheKey.'.all', $this->cacheTime, function () {
return $this->model->get();
});
}
public function allEnables()
{
return Cache::remember($this->cacheKey.'.enables', $this->cacheTime, function () {
return $this->model->active()->get();
});
}
public function list(string $orderByColumn, string $orderBy = 'desc', array $with = [])
{
return Cache::remember($this->cacheKey.'.list', $this->cacheTime, function () use($with, $orderByColumn, $orderBy) {
return $this->model->with($with)
->orderBy($orderByColumn, $orderBy)
->get();
});
}
public function listWithPaginate(string $orderByColumn, string $orderBy = 'desc', array $with = [], int $perPage = 10)
{
return Cache::remember($this->cacheKey.'.listWithPaginate', $this->cacheTime, function () use($with, $orderByColumn, $orderBy, $perPage) {
return $this->model->with($with)
->orderBy($orderByColumn, $orderBy)
->paginate($perPage)->appends(request()->query());
});
}
public function create(array $data): int
{
Cache::forget($this->cacheKey);
Cache::forget($this->cacheKey.'.all');
Cache::forget($this->cacheKey.'.enables');
Cache::forget($this->cacheKey.'.list');
Cache::forget($this->cacheKey.'.listWithPaginate');
return $this->model->create($data)->id;
}
public function update(array $data, int $id, string $attribute = 'id'): void
{
$this->model->where($attribute, '=', $id)->update($data);
Cache::forget($this->cacheKey);
Cache::forget($this->cacheKey.".{$id}");
Cache::forget($this->cacheKey.'.all');
Cache::forget($this->cacheKey.'.enables');
Cache::forget($this->cacheKey.'.list');
Cache::forget($this->cacheKey.'.listWithPaginate');
}
public function delete(int $id): void
{
$this->model->destroy($id);
Cache::forget($this->cacheKey);
Cache::forget($this->cacheKey.'.all');
Cache::forget($this->cacheKey.'.enables');
Cache::forget($this->cacheKey.'.list');
Cache::forget($this->cacheKey.'.listWithPaginate');
}
public function find(int $id)
{
return Cache::remember($this->cacheKey.".{$id}", $this->cacheTime, function () use ($id) {
return $this->model->find($id);
});
}
public function getModel()
{
return Cache::remember($this->cacheKey.".all", $this->cacheTime, function (){
return $this->model;
});
}
public function findOrFail(int $id)
{
return Cache::remember($this->cacheKey.".{$id}", $this->cacheTime, function () use ($id) {
return $this->model->findOrFail($id);
});
}
}
I have problem with paginate. When I go to pagination 2,3,7 or 10 - I always see the same as on page 1.
Is my code optimal? Can duplication be replaced - one function (I have remove in controller - in edit too):
:: Cache forget ($ this-> cacheKey);
:: Cache forget ($ this-> cacheKey.. 'All');
:: Cache forget ($ this-> cacheKey. '. Enables');
:: Cache forget ($ this-> cacheKey.. 'Letter');
:: Cache forget ($ this-> cacheKey. '. ListWithPaginate');
some one function?
That is because when you call first page it is cached, on second page since the key is not changed the cache assume that you want cached version and returns page 1.
One way will be to update tag depending on input:
public function listWithPaginate(string $orderByColumn, string $orderBy = 'desc', array $with = [], int $perPage = 10)
{
$tag = sprintf('%s.listWithPaginate.%s.%s',
$this->cacheKey,
serialize(func_get_args()),
serialize(request()->query())
);
return Cache::remember($tag, $this->cacheTime...;
}
Another way will be to cache all rows and then paginate them from cache. You will need to make custom collection paginator (google "laravel collection pagination, and will find many tutorials). You may still need to add $with to your cache tag. And for many results isn't a good idea.
Don't try to cache everything. Caching isn't always the fastest way. Better try to optimize your database.
Personally I don't think it is a good idea to cache in repositories.
To flush multiple tags you can use:
Cache::tags('tag1', 'tag2')->flush()
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 am trying to solve problem of cheeking function in standart gii
I need to check if function exist in yii\base\Model
and if it exist, add prefix to this function
For example if you generate model with yii2\gii
you will have somthing like this
/**
* #return \yii\db\ActiveQuery
*/
public function getErrors()
{
return $this->hasMany(Error::className(), ['groupId' => 'id']);
}
I need to change function name when it generate to
/**
* #return \yii\db\ActiveQuery
*/
public function funky_key_getErrors()
{
return $this->hasMany(Error::className(), ['groupId' => 'id']);
}
I extend basics gii and rewrite function but it doesn't help
My code from generators\model\Generator, i think i need to check $relations in this function
protected function generateRelations()
{
\before basik yii code\
$relations = self::checkExistClass($relations);
return $relations;
}
private static function checkExistClass($relations)
{
foreach ($relations as $name => $relation) {
foreach ($relation as $functionName => $functionValue) {
$functionNameGet = 'get' . $functionName;
$directory = new Model;
if (method_exists($directory, $functionNameGet)) {
$relation['funky_key_' . $functionName] = $functionValue;
unset($relation[$functionName]);
}
}
}
return $relations;
}
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;