I've created a simple application in ZF2. At some point I decided to create a new set of functionalities so I created a new folder this way:
module
Application
src
Application
Controller
IndexController.php
Issue
Controller
FooController.php
IndexController has the namespace Application\Controller and actions are working fine but when I try to run action from FooController (namespace Issue\Controller) it throws Class 'Issue\Controller\FooController'. Of course I've set routes and controllers in configuration (without it it was throwing 404 anyway).
The problem lies in the fact that your folder name in src should correspond to the folder name of the module. I think this is related to the autoloading namespace magic in ZF2.
So like #Demo suggests you need to do this:
module
Application
src
Application
Controller
IndexController.php
Issue
src
Issue
Controller
FooController.php
or this:
module
Application
src
Application
Controller
IndexController.php
FooController.php
Read more on the topic here at this question on StackOverflow
EDIT
Read also more on correctly setting up your module, properly autoloading through autoLoaderConfig in your module.php and PSR-0 naming conventions here in the ZF2 user-guid
It is indeed an autoload problem (but no magic).
You can register your namespace like this (just an quick example) :
<?php
namespace Application;
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;
class Module
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
'Application' => __DIR__ . '/src/Application',
'Issue' => __DIR__ . '/src/Issue',
),
),
);
}
}
EDIT
For PSR-0 compliance, you could put a Module.php file in Application and Issue folders, and the "global" Module.php would look like this :
<?php
require_once __DIR__ .'/src/Application/Module.php';
require_once __DIR__ .'/src/Issue/Module.php';
And you could also register your autoloading namespaces in each Module.php file.
And again, you should prefer using two modules.
Related
When using AbstractControllerTestCase (or it's subclasses) you get a convenient method setApplicationConfig() that let's you pass an array similar to config/application.config.php, so that you include only the modules you need in order to test.
How do you pass the array that goes into config/autoload/global.php to AbstractControllerTestCase?
PS: if it helps, I'm trying to pass a custom ORM connection that uses SQLite
You can simply make separate config files to be used when testing and load those inside your test controller.
for example;
copy config/application.config.php to config/application.config.test.php
Make a small change to allow us to load separate test config files without touching the global config files used by the production application.
'config_glob_paths' => array(realpath(__DIR__) . '/autoload/{,*.}{global,test}.php'),
This will allow us to override any config values we need as the test config files are loaded after the usual global config files. We can now please any test specific configureation inside test.php, anything.test.php etc.
now you can copy
autoload/global.php to autoload/test.php
You can now change config items and these will override those inside global.php
autoload/test.php
<?php
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'sqlite:' . __DIR__ .'/../../data/testing.sqlite',
//'dsn' => 'mysql:dbname=somedatabase;host=localhost',
'username' => 'dbuser',
'password' => 'passwordgoeshere',
),
You could also change the driver to use SQL lite or what ever your require to run your tests.
Now you just need to make your test controllers load our new application config file:
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class ExampleTest extends AbstractHttpControllerTestCase
{
public function setUp()
{
$this->setApplicationConfig(
include __DIR__ . '/../../config/application.config.test.php'
);
}
This allows you to keep all your test configuration separate to your main application config settings.
I want to make sure this works the way I think it does.
I have setup DB info inside of myapp/config/autoload/global.php like this:
return array(
'db' => array(
'driver' => 'Pdo',
'dsn' => 'mysql:dbname=zf2tutorial;host=localhost',
'driver_options' => array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
),
),
...
Now I'm messing around with a new module and would like to configure that specific module with a different db. If I add a 'db' config array to NewModule/config/module.config.php will it overwrite the global config? I'm not sure if the application wide global.php file is the same as a module specific config file or if it has a special specification- like accepting a db configuration while module specific config files do not.
edit: Well I tried this and it appears the db entry I added in module.config is being completely ignored. How can I override the db config per module? It would be very convenient for testing purposes.
If I add a 'db' config array to NewModule/config/module.config.php will it overwrite the global config?
Yes. All configs are merged together in to one monster array.
ZF support multiple adapters, you'll just have to refer to them by name in code so it knows which one you want. See this blog post for details on how to set it up: http://samsonasik.wordpress.com/2013/07/27/zend-framework-2-multiple-named-db-adapter-instances-using-adapters-subkey/
It seem that all config settings defined in Module.php in getConfig method are merged globally across the application. It's pretty weird for my case, because I need different configs for each module: database settings, some factories and view_manager settings which are currently overridden by the last module loaded. How can I use configs exclusive for some module is scope of $this->getServiceLocator()->get('Config') in that module. The only thoughts I have now are to merge my module config with $this->getServiceLocator()->get('Config') on dispatch event, if that is the only case, what priority is better to use so I can utilize all settings: view_manager, service_manager ect?
For me the ideal solution will be if configs settings in scope of some namespace will be used only under that namespace.
You can nest your configuration values as deeply as you like.
Imaging you've got a module called "mymodule", and it needs to connect to a special, module-specific database (distinct from the main DB for the overall application). You would do something like this:
mymodule.global.php.dist:
return array(
'mymodule' => array(
'db' => array('host'=>'localhost', ... )
)
)
Then just make sure that myModule is looking at $config['mymodule']['db'], and not $config['db']
You can get the configuration settings of the module in this way:
$moduleManager = $this->getServiceLocator()->get('ModuleManager');
$applicationModule = $moduleManager->getModule('Application');
$applicationConfig = $applicationModule->getConfig();
i want to extend the UserController with an setEventManager implementation, to display another layout - just with an login mask.
When i call the url www.example.com i get my Controller, with the other layout.
But if type in a wrong username, i redirected to www.exmpale.com/user/login and i get the default layout.
How i can overwrite all routes from ZfcUser Module and redirect them to my own controller, to ensure, the UserController can not called directly.
Thank you.
If I understand your question right, you probably just have to edit the file module.config.php. It contains all route definitions.
From how I understand your question you have an own controller called something like MyBetterUserController?
You can add an own module as extension to the ZfcUser module, maybe you want to call it something like ZfcUserMod. This new module will only contain a Module.php file and a folder config with the configuration file.
Then you can define your routes in this module’s configuration file and overwrite all routes from ZfcUser. Make sure that you use the exactly same route names (the keys in the array) as ZfcUser does (currently they use zfcuser as route name). Otherwise the routes will not be overwriten and the UrlHelper will not use your routes.
Then add ZfcUserMod to the global application.config.php after ZfcUser.
Wouldn't it be easier to override just the controllers -> invocables pointing 'zfcuser' => 'namespace\your\extendedusercontroller' instead of rewriting all the routes ?
I'm using the sfGuardPlugin in symfony 1.4 and I'm wondering how to get rid of its "default" routes. I mean by that the "guard/users", "guard/permissions" and "guard/groups" routes.
Indeed I have designed my own backend without admin generator, and I've recreated these three pages with customs urls. So how can I disable the access to the default sfGuard pages ?
app.yml:
all:
sf_guard_plugin:
routes_register: false
as stated in the documentation.
You should update the file
/config/sfDoctrineGuardPluginConfiguration.class.php
to the lasted version.
Before the lasted update, despite the documentation, the routes did get registed anyway.
It seems you are using the previous version of this file.
To desactivate these 3 modules : you just have to remove the sfGuardGroup, sfGuardUser, sfGuardPermission from the settings.yml for backend application.
all:
.settings:
enabled_modules: [default, sfGuardAuth, sfGuardGroup, sfGuardUser, sfGuardPermission]
In order to keep only the authentification module
all:
.settings:
enabled_modules: [default, sfGuardAuth]
However I have no idea what default is.
If you (i) still want to use the modules provided by the plugin, (ii) using your own routes, (iii) preventing people from using the default sfGuard routes and (iv) still have the default /:module/:action route (which is rather useful), you can override the sfGuardRouting class, which is here
plugins/sfGuardPlugin/lib/routing/sfGuardRouting.class.php
You can simply copy this file to your
lib/
directory and then play with the methods. For instance I just commented all the code of all methods of the class (since I made my own routes in my apps/myApp/config/routing.yml file) for the modules of the sfGuardPlugin), like this
class sfGuardRouting
{
static public function listenToRoutingLoadConfigurationEvent(sfEvent $event)
{
// $r = $event->getSubject();
// preprend our routes
// $r->prependRoute('sf_guard_signin', new sfRoute('/guard/login', array('module' => 'sfGuardAuth', 'action' => 'signin')));
// $r->prependRoute('sf_guard_signout', new sfRoute('/guard/logout', array('module' => 'sfGuardAuth', 'action' => 'signout')));
}
}