DI fails with namespace - dependency-injection

I'm following this tutorial to get a deeper understanding in dependency injection.
Because our host is still on PHP5.3, I'm using Aura\Web -components for HTTP response/request.
Dependency injection is done with Auryn\Injector
So far I've managed to get project running, but I cannot use the alias as a classname that I've defined in the injector:
$injector = new \Auryn\Injector;
$injector->alias( 'Http\Request', '\Aura\Web\Request' );
$injector->share( '\Aura\Web\Request' );
$injector->define( '\Aura\Web\Request', array(
':client' => new \Aura\Web\Request\Client( $_SERVER ),
':content' => new \Aura\Web\Request\Content( $_SERVER ),
':globals' => new \Aura\Web\Request\Globals(
new \Aura\Web\Request\Values( $_COOKIE ),
new \Aura\Web\Request\Values( $_ENV ),
new \Aura\Web\Request\Files( $_FILES ),
new \Aura\Web\Request\Values( $_POST ),
new \Aura\Web\Request\Values( $_GET ),
new \Aura\Web\Request\Values( $_SERVER )
),
':headers' => new \Aura\Web\Request\Headers( $_SERVER ),
':method' => new \Aura\Web\Request\Method( $_SERVER, $_POST ),
':params' => new \Aura\Web\Request\Params,
':url' => new \Aura\Web\Request\Url( $_SERVER )
)
);
In my controller I would like to use this alias:
namespace Example\Controllers;
use Http\Request;
class Homepage {
public function __construct( Request $request) { ... }
}
This throws the following error:
Could not make \Example\Controllers\Homepage: Class Http\Request does not exist
I can fix this by declaring the class as:
namespace Example\Controllers;
use Aura\Web\Request;
class Homepage {
public function __construct( Request $request) { ... }
}
Which probably makes the dependency injection a bit.. useless? Auryn still supplies the proper arguments ($action = $injector->make( $action_class );), but why isn't the alias accepted?
I hope my question makes some sense. :-)

This is an Auryn "issue". If you read their docs, you can see that alias works like this:
// Tell the Injector class to inject an instance of V8 any time
// it encounters an Engine type-hint
$injector->alias('Engine', 'V8');
So all it does is it maps a default implementation (class) to an interface.
Right now you are mixing my own HTTP library with the one from Aura which won't work because Aura\Web\Request is not implementing the Http\Request interface from my library (obviously).
So what you need to do is type hint either for an interface or class that is part of the Aura library.
I recommend you give the Auryn docs a read so that you understand how alias and the other commands work.

Related

AngularDart CurrentInstruction

I am trying to update angular2 to latest version. Several of the functions are missing
I would like to know what is the alternate for the following function
final RouteParams _params;
String get routeName => _router.currentInstruction.component.routeName;
How to get routeName from new AngularDart
Not possible to access current component route anymore.
I don't know what you want to do exactly and how you define your routeName, but you probably need to use additionalData of RoutePath or RouteDefinition
class AdditionalRouteData {
final String routeName;
const AdditionalRouteData({this.routeName});
}
final routePath = RoutePath(
path: '/',
additionalData: AdditionalRouteData(routeName: 'Home'),
);
// then get it that way
(router.current.routePath.additionalData as AdditionalRouteData).routeName;
However, if your routeName is dynamic, you must find a new way to access it (without the router, using a service via dependency injection)

ZF2 resolver could not resolve to a file (but works on development environment)

I've gone through the other similar questions on here and have tried numerous things though to no avail.
I have a dashboard controller that works correctly on my development machine, though when it is uploaded to the production server it reports:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "Dashboard\Dashboard\Index"; resolver could not resolve to a file
I've checked my module.config.php file for the view-template (and it's correctly listed on there)
'template_path_stack' => array(
'dashboard' => __DIR__ . '/../view',
),
And the file is also at that physical location...
I'm not sure what I am missing in terms of this, so any pointers would be great.
UPDATE:
Here is the code for the controller:
public function indexAction() {
//check the users authenticity
$userId = null;
$auth = $this->getServiceLocator()->get('zfcuser_auth_service');
if ($auth->hasIdentity()) {
$user = $auth->getIdentity();
$userId = $user->getId();
} else {
$this->redirect()->toUrl('/user/login');
}
//set the view model to improve performance
//http://samminds.com/2012/11/zf2-performance-quicktipp-1-viewmodels/
$viewModel = new ViewModel();
$viewModel->setTemplate('Dashboard\Dashboard\Index');
//return the amount of counts the various items have outstanding
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$systemRepo = $this->getSystemRepo($dbAdapter);
$internalContacts = $systemRepo->widgetAlphabetList("Internal Contacts", $systemRepo->getInternalContacts(), 'firstname', 'surname');
return $viewModel->setVariables(array(
'internalContacts' => $internalContacts
));
}
And the full path to the file is (add index.phtml on the end of the below):
/var/www/html/module/Dashboard/view/dashboard/dashboard
I'm going to guess dev machine is not a case sensitive file system and prod is case sensitive. Try this:
$viewModel->setTemplate('dashboard/dashboard/index')

zf2 how to use 3rd party module in my own specific module (based on route)?

I'm developping a website by ZendFramework 2. I have 2 modules: module for administration called Administration(route defined like www.mysite.com/admin/...) et module public site called Application(route defined like www.mysite.com/...) I distinguish the 2 modules by the route.
I don't know how to distinguish the two modules based on route.
To make it clear, I have 2 questions for example:
I use Zfcuser for the login system for the module Administration et in Administration/Module.php I added the following code to the purpose that if one user doesn't have identity the layout will change to the login form.
namespace Administration;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module {
public function onBootstrap(MvcEvent $e) {
$eventManager = $e->getApplication ()->getEventManager ();
$moduleRouteListener = new ModuleRouteListener ();
$moduleRouteListener->attach ( $eventManager );
$eventManager->attach('dispatch', array($this, 'checkLoginChangeLayout'));
}
public function checkLoginChangeLayout(MvcEvent $e) {
if (! $e->getApplication ()->getServiceManager ()->get ( 'zfcuser_auth_service' )->hasIdentity ()) {
$controller = $e->getTarget ();
$controller->layout ( 'layout/authentication.phtml' );
}
}
public function getConfig() {
return include __DIR__ . '/config/module.config.php';
}
public function getAutoloaderConfig() {
return array (
'Zend\Loader\StandardAutoloader' => array (
'namespaces' => array (
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__
)
)
);
}
}
But all the 2 modules are affected by the function checkLoginChangeLayout(). I want to use the module ZfcUser just in the module Administration but not the module Application.
Can I do something about the Module Manager or Event Manager to solve the problem?
I've found a 3rd party module called BjyAuthorize which is used for ACL by "guard". When I active the module in application.config.php , all my 2 modules are controlled by it. But I just want to use the 3rd party module in the module Administration but not the other modules.
your first approach is fail
because (as you found) there is another module for doing such a thing called BJYAUTHORIZE
it has a config for allowing different type of users access which controller/action/module/route/...
plz review it's documentation for more information and also there is a blog post for How to join ZFCUser and BJY together .
http://samminds.com/2013/03/zfcuser-bjyauthorize-and-doctrine-working-together/

ZF2 - Injecting pages to navigation before controller is called

I'm creating a dynamic Application in which the content is added through a CMS. Inside the CMS, I'm setting a db entry which states what module to use for each content page.
NodeId,
ParentNodeId,
Name_de,
Name_en,
ModuleName,
foreignkey_ContentLinks,
in this table entries look as follows:
6,
1,
Veranstaltung-21-02-2013,
Event-21-02-2013,
Events,
682
The entire tree should end up in my navigation (and perfectly also in my routing). I do not want to add it in some controller, because my Application consists of a whole bunch of Modules and I want to access that Info across all my Modules.
I already tried injecting it in the global.php, but to no avail because I can't my db adapter or any other important classes at that stage.
Any ideas or links to best practices?
The navigation containers are composed by factory classes. The easiest approach is to write your own factory and have the getPages() method fetch pages from a database instead of from config. If you extend from the AbstractNavigationFactory you only need to write a couple of methods.
<?php
namespace Application\Navigation\Service;
use Zend\Navigation\Service\AbstractNavigationFactory;
use Zend\ServiceManager\ServiceLocatorInterface;
class CmsNavigationFactory extends AbstractNavigationFactory
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return array
* #throws \Zend\Navigation\Exception\InvalidArgumentException
*/
protected function getPages(ServiceLocatorInterface $serviceLocator)
{
if (null === $this->pages) {
$application = $serviceLocator->get('Application');
$routeMatch = $application->getMvcEvent()->getRouteMatch();
$router = $application->getMvcEvent()->getRouter();
// get your pages from wherever...
$pages = $this->getPagesFromDB();
$this->pages = $this->injectComponents($pages, $routeMatch, $router);
}
return $this->pages;
}
public function getName()
{
// this isn't used if fetching from db, it's just here to keep the abstract factory happy
return 'cms';
}
}
Add the factory to the service manager, just like you would for other containers
'service_manager' => array(
'factories' => array(
'CmsNavigation' => 'Application\Navigation\Service\CmsNavigationFactory',
),
),
And use it with the navigation view helpers in the same way
<?php echo $this->navigation()->menu('CmsNavigation'); ?>
Responding to your comment on #Crisp's answer, and for future googlers, I'll explain how to do something similar for routing.
Typically you would want to create a custom router that can match URLs to the pages in your database, similarly to the standard Segment router. To do this, you will have to implement the Zend\Mvc\Router\RouteInterface interface. For example:
namespace Application\Router;
use Zend\Mvc\Router\RouteInterface;
use Application\Model\CMSTable;
class CmsRoute implements RouteInterface, ServiceLocatorAwareInterface
{
protected $table;
// Service locator injection code
public function getCmsTable()
{
// Retrieve the table from the service manager
}
public function match(Request $request)
{
// Match the request on some route field, etc.
}
public function assemble(array $params = array(), array $options = array())
{
// Assemble a URL based on the given parameters (e.g. page ID).
}
public static function factory($options = array())
{
// Construct a new route, based on the options.
}
}
You could then register this route as an invokable for the RoutePluginManager in your module configuration:
'route_manager' => array(
'invokables' => array(
'Cms' => 'Application\Router\CmsRoute'
),
),
Then, you can create a new route (just as you would for any other route) with type Cms. The route plugin manager will create your route instance, and since CmsRoute implements ServiceLocatorAwareInterface, the plugin manager will inject itself in the route. In turn, the plugin manager has the main service manager set, so that you can get the database table from there!
Of course you can match on page ID, but if you have a hierarchical structure, it's nicer to reflect that in your URLs. I would therefore recommend adding a route field to the database schema and match on that, beginning with the tree root and working down.

How to share zfcuser across subdomain in zend framework 2

I have in my application installed zfcuser module and everything works fine. I configured hostname router and here my problem starts, when I log in on main domain (http://example.com) everything is ok, but when I go to any subdomain (http://test.example.com, http://anysubdomain.example.com) I'm loosing logged state and on every subdomain I have to login again. How to share login state across subdomains? In ZF1 i just set 'cookie_domain' and it works but how make it in ZF2? Of course I'm using also Bjyauthorize and I want to keep bjyauthorize guards on subdomains...
Ok I found solution, in ZfcUser Module.php I've added:
use Zend\Session\Config\SessionConfig;
use Zend\Session\SessionManager;
use Zend\Session\Container;
use Zend\EventManager\EventInterface;
public function onBootstrap(EventInterface $e)
{
$config = $e->getApplication()
->getServiceManager()
->get('Configuration');
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions($config['session']);
$sessionManager = new SessionManager($sessionConfig);
$sessionManager->start();
Container::setDefaultManager($sessionManager);
}
and in ZfcUser module.config.php:
return array(
'session' => array(
'use_cookies' => true,
'cookie_domain'=>'example.com',
)
);
Hope it will help somebody.

Resources