i route by hostname and i want to get my domain name by local.php config file in config/autoload in zf2
i know how should i get configs in controller,
but i dont know how can i get it in my router configuration file
i comment what i want in my code
'router' => array(
'routes' => array(
'advertise' => array(
'type' => 'Hostname',
'options' => array(
'route' => 'www.myhome.com', // here i want to get my domain by config
'defaults' => array(
'controller' => 'Advertise\Controller\Advertise',
'action' => 'index',
),
),
.............
You can use the API of the 'router' service (an instance of Zend\Mvc\Router\Http\TreeRouteStack) and add a route dynamically.
How you attach the route to the route stack is up to you, you could extend the default router factory Zend\Mvc\Service\RouterFactory with your own routes from config.
use MyModule\Mvc\Service;
use Zend\Mvc\Service\RouterFactory;
use Zend\ServiceManager\ServiceLocatorInterface;
class MyRouterFactory extends RouterFactory
{
public function createService(ServiceLocatorInterface $serviceLocator, $cName = null, $rName = null)
{
$serviceManager = $serviceLocator->getServiceLocator();
$router = parent::createService($serviceLocator, $cName, $rName);
$config = $serviceManager->get('config');
$router->addRoute('advertise', [
'type' => 'hostname',
'options' => [
'route' => $config['some_other_config_key'],
'defaults' => [
'controller' => 'Advertise\Controller\Advertise',
'action' => 'index'
]
],
'priority' => 123
]);
return $router;
}
}
Remember to register it with the name Router in module.config.php to replace the default implementation.
'service_manager' => [
'factories' => [
'Router' => 'MyModule\Mvc\Service\MyCustomRouterFactory',
],
],
The nice thing with this approach is that the routers construction is all kept in one place; also as you are adding it with a factory class
you have access to other services should you need them.
Alternatively, you could add it via an event, although being triggered via the event manager, this method would likely be more resource intensive.
namespace MyModule;
use Zend\ModuleManager\InitProviderInterface;
use Zend\ModuleManager\ModuleManagerInterface;
use Zend\Mvc\Application;
use Zend\Mvc\MvcEvent;
class Module implements InitProviderInterface
{
// init is called when the module is initilised, we can use this to add a listener to the
// 'bootstrap' event
public function init(ModuleManagerInterface $manager)
{
$eventManager = $manager->getEventManager()->getSharedManager();
$eventManager->attach(Application::class, MvcEvent::EVENT_BOOTSTRAP, [$this, 'addRoutes']);
}
public function addRoutes(MvcEvent $event)
{
$serviceManager = $event->getApplication()->getServiceManager();
$router = $serviceManager->get('Router');
$config = $serviceManager->get('Config');
$router->addRoute('advertise', [
'type' => 'hostname',
'options' => [
'route' => $config['some_other_config_key'],
'defaults' => [
'controller' => 'Advertise\Controller\Advertise',
'action' => 'index'
]
],
'priority' => 123
]);
}
}
Related
Here my Module.php:
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* #link http://github.com/zendframework/ZendSkeletonModule for the canonical source repository
* #copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Users;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\Mvc\ModuleRouteListener;
class Module implements AutoloaderProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
// if we're in a namespace deeper than one level we need to fix the \ in the path
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function onBootstrap($e)
{
// You may not need to do this if you're doing it elsewhere in your
// application
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
}
And here my module.config.php:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Users\Controller\Index' => 'Users\Controller\IndexController',
),
),
'router' => array(
'routes' => array(
'users' => array(
'type' => 'Literal',
'options' => array(
// Change this to something specific to your module
'route' => '/users',
'defaults' => array(
// Change this value to reflect the namespace in which
// the controllers for your module are found
'__NAMESPACE__' => 'Users\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
// This route is a sane default when developing a module;
// as you solidify the routes for your module, however,
// you may want to remove it and replace it with more
// specific routes.
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'users' => __DIR__ . '/../view',
),
),
);
But when I try to see the index page I get this:
( ! ) Fatal error: Uncaught
Zend\ModuleManager\Exception\RuntimeException: Module (Users) could
not be initialized. in
/var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php
on line 195
( ! ) Zend\ModuleManager\Exception\RuntimeException: Module (Users) could not be initialized. in /var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/ModuleManager/ModuleManager.php
on line 195
Anyone knows what's wrong with this code?
A couple of things to check:
The filename is Module.php - that exact case.
That Module.php is in module/Users (i.e. not in module/Users/src/)
I used internal server of php where I don't have xdebug enabled it got this:
127.0.0.1:48908 [500]: /public/ - Uncaught Zend\ModuleManager\Listener\Exception\InvalidArgumentException: Config being merged must be an array, implement the Traversable interface, or be an instance of Zend\Config\Config. boolean given. in /var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/ConfigListener.php:342
Stack trace:
0 /var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/ConfigListener.php(127): Zend\ModuleManager\Listener\ConfigListener->addConfig('Users', false)
1 [internal function]: Zend\ModuleManager\Listener\ConfigListener->onLoadModule(Object(Zend\ModuleManager\ModuleEvent))
2 /var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(444): call_user_func(Array, Object(Zend\ModuleManager\ModuleEvent))
3 /var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php(205): Zend\EventManager\EventManager->triggerListeners('loadModule in /var/www/html/communicationapp/vendor/zendframework/zendframework/library/Zend/ModuleManager/Listener/ConfigListener.php on line 342
I am migrating an application from Zend 1 to Zend 2 and starting to desperate with one issue. The application works with different locales and therefore, I need to store the data in a normalized way in the database. In Zend 1 I used this code:
public function normalizeNumber( $value )
{
// get the locale to change the date format
$this->_locale = Zend_Registry::get('Zend_Locale' );
return Zend_Locale_Format::getNumber($value, array('precision' => 2, 'locale' => $this->_locale));
}
Unfortunately Zend 2 does not has this Zend_Locale_Format::getNumber any more and I was not able to figure out what function did replace it. I have tried with NumberFormat, but I get only localized data not normalized. I need this function to normalize data I receive from a form via POST. Can someone give some advice?
thanks
Just to complete my question. The Form element definition I am using is the following:
namespace Profile\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;
class Profile Extends Form implements InputFilterProviderInterface
{
protected $model;
public function __construct( $model, $name = 'assignmentprofile')
{
parent::__construct( $name );
$this->setAttribute( 'method', 'post');
$this->model = $model;
...
$this->add( array(
'name' =>'CommutingRate',
'type' =>'Zend\Form\Element\Text',
'options' => array( // list of options to add to the element
'label' => 'Commuting rate to be charged:',
'pattern' => '/[0-9.,]/',
),
'attributes' => array( // Attributes to be passed to the HTML lement
'type' =>'text',
'required' => 'required',
'placeholder' => '',
),
));
}
public function getInputFilterSpecification()
{
return array(
...
'CommutingRate' => array(
'required' => true,
'filters' => array(
array( 'name' => 'StripTags', ),
array( 'name' => 'StringTrim'),
array( 'name' => 'NumberFormat', 'options' => array('locale' => 'en_US', 'style' => 'NumberFormatter::DECIMAL', 'type' => 'NumberFormatter::TYPE_DOUBLE',
))
),
'validators' => array(
array( 'name' => 'Float',
'options' => array( 'messages' => array('notFloat' => 'A valid numeric entry is required')),
),
),),
...
);
}
}
As mentioned before, I am able to localized the data and validate it in the localized manner, but i am failing to convert it back to a normalized manner...
Im my module.config.php file got following excerpt:
return array(
'service_manager' => array(
'aliases' => array(
'Util\Dao\Factory' => 'modelFactory',
),
'factories' => array(
'modelFactory' => function($sm) {
$dbAdapter = $sm->get('Doctrine\ORM\EntityManager');
return new \Util\Dao\Factory($dbAdapter);
},
)
),
'doctrine' => array(
'driver' => array(
'application_entities' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(
__DIR__ . '/../src/Application/Model'
),
),
'orm_default' => array(
'drivers' => array(
'Application\Model' => 'application_entities'
)
),
),
),
How do i put the block "doctrine" in module class?
Well, this is actually fairly simple. Probably your Module class has the method getConfig(). That method usually loads moduleName/config/module.config.php.
So in whatever function you are, simply call the getConfig()-method. This is pure and basic php ;)
//Module class
public function doSomethingAwesome() {
$moduleConfig = $this->getConfig();
$doctrineConfig = isset($moduleConfig['doctrine'])
? $moduleConfig['doctrine']
: array('doctrine-config-not-initialized');
}
However you need to notice that this only includes your Modules config. If you need to gain access to the merged configuration, you'll need to do that in the onBootstrap()-method. Which would be done like this:
//Module class
public function onBootstrap(MvcEvent $mvcEvent)
{
$application = $mvcEvent->getApplication();
$serviceLocator = $application->getServiceLocator();
$mergedConfig = $serviceLocator->get('config');
$doctrineConfig = isset($mergedConfig['doctrine'])
? $mergedConfig['doctrine']
: array('doctrine-config-not-initialized');
}
This works similar if you're attaching to some events...
I'm trying to understand all the configuration necessary to get my routing working in Zend Framework 2, and I can't help but wonder if I am making this more complicated than necessary.
I am working on a simple app that will follow a very simple convention:
/:module/:controller/:action
I've already created and wired up my module, "svc" (short for "service)". I then created a second controller, the "ClientsController", and I can't get the routing to pass through my requests to, e.g., /svc/clients/list to ClientsController::listAction().
As I'm wading through hundreds of lines of configuration, in deeply nested arrays, I'm thinking--isn't there some way to just have a default mapping of my URLs to /:module/:controller/:action ?
Thanks for any assistance. I'm going off of the Zend Framework 2 Quick Start, which walked me through creating a new module and then adding a controller to that module. But when I tried to add second controller to that module, I am tripping over the routing.
Update: I didn't catch this the first time through, but apparently this is supposed to be a feature of the Zend Framework Skeleton app. From the quick start guide:
ZendSkeletonApplication ships with a “default route” that will likely
get you to this action. That route basically expects
“/{module}/{controller}/{action}”, which allows you to specify this:
“/zend-user/hello/world”
That's exactly what I want! But I can't get it to work.
It lists an incomplete module.config.php, with a comment at the bottom about putting "other configuration" here. I tried to figure out what that "other configuration" is, and wound up with this:
return array(
'svc' => array(
'type' => 'Literal',
'options' => array(
'route' => '/svc',
'defaults' => array(
'controller' => 'svc\Controller\Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'svc\Controller\Clients' => 'svc\Controller\ClientsController',
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);
JFYI, here is what my controller looks like.
namespace svc\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class ClientsController extends AbstractActionController {
public function indexAction() {
return new ViewModel();
}
public function anotherAction(){
return new ViewModel();
}
}
My routes are not working. I get "route not found" when I try to pull up any of my routes.
It lists an incomplete module.config.php, with a comment at the bottom about putting "other configuration" here. I tried to figure out what that "other configuration" is, and wound up with this:
If your module.config.php really looks like that then it won't work, routes is an array of routes defined in the router key, your config contains no such spec, try replacing it with this
return array(
// routes
'router' => array(
'routes' => array(
'svc' => array(
'type' => 'Literal',
'options' => array(
'route' => '/svc',
'defaults' => array(
'controller' => 'svc\Controller\Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
// add the default namespace for :controllers in this route
'__NAMESPACE__' => 'svc\Controller',
),
),
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'svc\Controller\Clients' => 'svc\Controller\ClientsController',
),
),
'view_manager' => array(
'template_path_stack' => array(
'album' => __DIR__ . '/../view',
),
),
);
I have these routes that I need to work:
/user
/user/1
/user/1.json
Currently I have
'user' => array('key' => 'user', 'controller' => 'user'),
'user/:id' => array('key' => 'user-id', 'controller' => 'user', 'id' => "\d+"),
'user/:id.json' => array('key' => 'user-id-json', 'controller' => 'user', 'id' => "\d+"),
It matches the first route for all three urls.
I tried doing this:
'user' => array('key' => 'user', 'controller' => 'user'),
'user/"\d+"' => array('key' => 'user-id', 'controller' => 'user', 'id' => 1),
'user/"\d+".json' => array('key' => 'user-id-json', 'controller' => 'user', 'id' => 1),
but only the first route gets matched still
Is there a way in the Zend Route url rule to "encase" the :id so its picked out and allows me to put something other than / after it?
UPDATED
My bootstrap uses:
public function _initRoutes() {
$this->addRoutes(array(
'client' => array('key' => 'client', 'controller' => 'client'),
'client/:id' => array('key' => 'client-id', 'controller' => 'client', 'id' => "\d+"),
'user' => array('key' => 'user', 'controller' => 'user'),
'user/:id' => array('key' => 'user-id', 'controller' => 'user', 'id' => "\d+")
));
}
My extended extender uses
public function addRoutes($routes) {
$router = Zend_Controller_Front::getInstance()->getRouter();
foreach ($routes as $pattern => $data) {
$router->addRoute(
$data['key'],
new Zend_Controller_Router_Route(
$pattern,
array('controller' => $data['controller'])
)
);
}
}
I tried making addRoutes this:
public function addRoutes($routes) {
$router = Zend_Controller_Front::getInstance()->getRouter();
foreach ($routes as $pattern => $data) {
$router->addRoute(
$data['key'],
new Zend_Controller_Router_Route(
$pattern,
array('controller' => $data['controller'])
)
);
$router->addRoute(
$data['key'].'-json',
new Zend_Controller_Router_Route(
$pattern.'.json',
array('controller' => $data['controller'])
)
);
}
}
but the latter cancels out /user/50 for example
Firstly, don't try and do this all in one route; you can have multiple named routes that point you at the same place. Its not clear from the chunks if you are trying to define this for one route. If you are, then split your rules into three, and give them the same variables.
If your routes are defined in an ini file (by convention, routes. ini), then I find it easier to have something like /user/:id/:format. You then can either use the Zend contextSwitcher helper in the controller or simply use the :format as a hint to your application. Under the reqs section of your route, you should have (\d+) as Zend_Route looks for sub strings.
Failing that, you might be able to get away with :id:file and define .json as a req for that particular route. This might work if you have to have the file extension. However, as you are kind of fooling the user by serving a PHP script as json, might be better handled at the web server level. If all else fails, and your regular expression foo is up to it, create an instance of the Regex router. While this is untested, this might do it:
/user/(\d+)\.json$