First of all, I know there are a few quite similar questions here on stackoverflow about that form problem but none of them could actually help me so I'm giving it a try myself. I've been stuck with this for the past 10 hours and I'm really desesperate right now.
So, let's start with my directory structure:
gpos/
---- application/
--- forms/
------- CustomerForm.php
--- modules/
--- default/
--- controllers/
--- CustomerController.php
--- views/
--- Bootstrap.php
---- public/
---- library/
--- Doctrine/
--- GPos/
--- Doctrine/
--- ActiveEntity.php
--- Models/
--- Customer.php
As you can see, I'm using Zend's standard forms/ folder to store my forms and I'm also using Doctrine as DB manager.
So I've been trying to reach my CustomerForm.php from CustomerController.php but simply getting a not found error.
Here is the error I'm getting:
Fatal error: Class 'Form_CustomerForm' not found in C:\wamp\www\GPos\gpos\application\modules\default\controllers\CustomerController.php on line 9
CustomerController.php:
class CustomerController extends Zend_Controller_Action {
public function init() {
/* Initialize action controller here */
}
public function indexAction() {
$form = new Form_CustomerForm(); //line 9
$form->setAction('/customer/index');
$form->setMethod('post');
$this->view->form = $form;
}
and CustomerForm.php:
class Form_CustomerForm extends Zend_Form {
public function init() {
and finally views/scripts/customer/submit.phtml:
<h2>Customer</h2>
<p>To create blabla</p>
<?php echo $this->form; ?>
I've been desesperately trying to add Form namespace to the autoloader but I learned today that it was already in thanks to Zend doing it for us. So... What am I doing wrong? I found tons of posts saying how to add resources and how to manage custom forms and I feel I'm doing exactly what's asked but it just won't work not matter what.
I'm afraid that it comes from somewhere else cause I've been trying to add different namespaces unsuccessfully too such as GPos_Doctrine for my ActiveEntity.php file in library/GPos/Doctrine/ with:
protected function _initAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH,
));
$autoloader->addResourceType('gpos', '/../../library/GPos', 'GPos');
$autoloader->addResourceType('doctrine', '/../../library/GPos/Doctrine', 'GPos_Doctrine');
return $autoloader;
}
This didn't work either. I'm quite unsure of the 'path' parameter (2nd param) but I saw in a tutorial that the path of eath resource type you add must be relative to autoloader's basePath, so I came up with these paths.
The only way I could make my GPos_Doctrine_ActiveEntity() work was by adding autoloadernamespaces[] = "GPos_" to application.ini. Adding autoloadernamespaces[] = "Form_"didn't work though... I really don't understand what's wrong with my resource types I'm adding.
Please note that I didn't use zf tools to build that project. I'm considering doing it if I don't find a way to make it all work correctly.
I've also tried to rename my form class to "Application_Form_CustomerForm" but didn't do any good either. I feel I've tried everything I could now. I'm just deseperate :(
Oh and by the way, the only work around I found at first is to put forms/ folder in my library, that worked. Don't understand why, but I don't want to use that hack. See, I'm doing this project as my IT Bachelor work graduation and I really shouldn't get into hacking things to make them work :P.
Thank you for anybody paying attention!
either add an bootstrap to the default module (which in turn sets the resourcetypes automaticly)
class Default_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAutoload() {
$moduleLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Default_',
'basePath' => APPLICATION_PATH . '/modules/default'));
return $moduleLoader;
}
}
or add this to your global bootstrap (extend it with your two custom resourcetypes):
public function _initDefaultResourceTypes() {
$al = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH.'/modules/default/',
'resourceTypes' => array(
'dbtable' => array(
'namespace' => 'Model_DbTable',
'path' => 'models/DbTable',
),
'mappers' => array(
'namespace' => 'Model_Mapper',
'path' => 'models/mappers',
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms',
),
'model' => array(
'namespace' => 'Model',
'path' => 'models',
),
'plugin' => array(
'namespace' => 'Plugin',
'path' => 'plugins',
),
'service' => array(
'namespace' => 'Service',
'path' => 'services',
),
'viewhelper' => array(
'namespace' => 'View_Helper',
'path' => 'views/helpers',
),
'viewfilter' => array(
'namespace' => 'View_Filter',
'path' => 'views/filters',
)
)
));
$al->setDefaultResourceType('model');
}
take a look at this ZF 1 Skeleton for further info:
https://github.com/eddiejaoude/Zend-Framework--Doctrine-ORM--PHPUnit--Ant--Jenkins-CI--TDD-
I don't use modules but here what I do, which is very basic :
In /public/index.php, I add "/forms" to the include path :
(important part is the line with "forms" of course
set_include_path(implode(PATH_SEPARATOR, array(
realpath(APPLICATION_PATH . '/../library'),
realpath(APPLICATION_PATH . '/forms'),
get_include_path(),
)));
My form are then named :
class Default_Form_Login extends Zend_Form
Then I would do :
$form = new Default_Form_Login();
Related
I'm having trouble setting up a route for a very simple controller. I'm getting the "The requested URL could not be matched by routing." error. I've viewed similar solved questions on SO and can't pinpoint what I'm doing wrong (Ex: ZF2 - Zend Framework 2, understanding routing)
I've followed the skeleton tutorial with the albums subject and everything functioned perfectly fine. I tried duplicating the album module and then changing the name of the controller, folder, module config, etc. I figured this would be a good way to confirm I can at least replicate working code. I'm just trying to echo "123" to the page, so I tried eliminating the directories for forms, models and some of the views from the new module.
Is there some way to see what route I'm really looking for and what routes I defined? I know CI actually created a log file I was able to check. It was kind of like Apache logs but specific to framework functionality.
I'd like to post some of my code so someone could point out the mistake I am making and possibly explain why it is wrong. I tried paying close attention to case since different variations of the word album are used throughout the tutorial and I'm not 100% sure which ones are supposed to match up with what just yet. I'm trying to make it work for http://www.example.com/productbriefs.
Folder Structure
module.config.php:
return array(
'controllers' => array(
'invokables' => array(
'Productbriefs\Controller\Productbriefs' => 'Productbriefs\Controller\ProductbriefsController',
),
),
// The following section is new and should be added to your file
'router' => array(
'routes' => array(
'productbriefs' => array(
'type' => 'Literal',
'options' => array(
'route' => '/productbriefs',
'defaults' => array(
'controller' => 'Productbriefs\Controller\Productbriefs',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'productbriefs' => __DIR__ . '/../view',
),
),
);
ProductbriefsController.php
namespace Productbriefs\Controller;
use Zend\Mvc\Controller\AbstractActionController;
class ProductbriefsController extends AbstractActionController
{
public function indexAction()
{
echo "123";
}
}
Module.php
namespace Productbriefs;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements AutoloaderProviderInterface, ConfigProviderInterface
{
public function getAutoloaderConfig()
{
return array(
'Zend\Loader\ClassMapAutoloader' => array(
__DIR__ . '/autoload_classmap.php',
),
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
// Add this method:
public function getServiceConfig()
{
return array(
'factories' => array(),
);
}
}
As per my comment, you need to add Productbriefs to the module array in application.config.php or the module (including its configuration) will not be loaded.
To answer your second question, the controller manager needs to know how to load the controller classes your application uses. An 'invokable' is a class that can be instantiated without needing any arguments passed to it, so by adding controllers to that array you're telling the controller manager that it can instantiate that class simply by doing $controller = new Productbriefs\Controller\ProductbriefsController(). The key for the array is an alias, yes. This can be anything, although the ZF convention is to use the fully qualified name of the class but omit the 'Controller' suffix from the end. When you refer to controllers in your routing config you use these aliases.
I am working through the zend framework 2 tutorial application. I have set up my Album Module directory as follows:
I am running into an error when I start my MAMP server, Fatal error: Uncaught exception 'Zend\ModuleManager\Exception\RuntimeException' with message 'Module (Album) could not be initialized.'
If I comment out the Album module from the following code (in /config/application.config.php):
'modules' => array(
'Application',
'Album',
),
I get to the skeleton application homepage.
Here is my /module/Album/Module.php code:
namespace Album;
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Album\Model\Album;
use Album\Model\AlbumTable;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module implements AutoloaderProviderInterface, ConfigProviderInterface {
public function getAutoloaderConfig() {
return array(
’Zend\Loader\ClassMapAutoloader’ => array(
__DIR__ . ’/autoload_classmap.php’,
),
’Zend\Loader\StandardAutoloader’ => array( ’namespaces’ => array(
__NAMESPACE__ => __DIR__ . ’/src/’ . __NAMESPACE__,
),
),
);
}
public function getConfig() {
return include __DIR__ . ’/config/module.config.php’;
}
public function getServiceConfig() {
return array(
’factories’ => array(
’Album\Model\AlbumTable’ => function($sm) {
$tableGateway = $sm->get(’AlbumTableGateway’);
$table = new AlbumTable($tableGateway);
return $table;
},
’AlbumTableGateway’ => function ($sm) {
$dbAdapter = $sm->get(’Zend\Db\Adapter\Adapter’);
$resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Album());
return new TableGateway(’album’, $dbAdapter, null, $resultSetPrototype);
},
),
);
}
}
And here is my module.config.php code in /module/Album/config/:
return array(
’controllers’ => array(
’invokables’ => array(
’Album\Controller\Album’ => ’Album\Controller\AlbumController’,
),
),
’view_manager’ => array(
’template_path_stack’ => array(
’album’ => __DIR__ . ’/../view’,
),
),
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
),
),'
);
I have read through a few people who have ran in to similar situations, but their issues were due to misspelled/incorrectly named classes. I don't see anything wrong with my code (even went as far as copying/pasting directly from tutorial).
Can someone give me some suggestions?
Thanks
I had the same problem, and the solution was to start every .php file with <?php
This is not clear in the tutorial (if you just copy the code from there), and it was the reason I was getting the same exception.
The only reason i could see is that you should replace all ’ with normal single quotes '.
using ’ can results in unexpected behaviors.
There is an error in the tutorials module.config.php file.
Change 'id' => '[0-9]+',
to 'id' => '[0-9]*',
+ means one or more digits. If you just call http://zf2-tutorial.localhost/album/ there is no digit in the url so the rewriterule doesn't match. Change from + to * (0 or more)
I had the exact same issue, my issue and solution were
the very first command in the tutorial is:
php composer.phar create-project --stability="dev" zendframework/skeleton-application path/to/install
It was cut off my screen so I copy/pasted the command to the command line without reading the end. So my app directory structure included a directory ./path/to/install where all of the installation files were, including application.config.php.
Moving everything in /path/to/install/ to the root directory of the app allowed Zend to find the Album module.
Note: /path/to/install/module contains the album module but will fail if you do
mv ./path/to/install/* .
so be sure to move the Application module at /path/to/install/module into app_root_dir/module/.
You can check composer.json weather include the following:
"autoload": {
"psr-4": {
"Application\\": "module/Application/src/",
"Album\\": "module/Album/src"
}
},
Please check your Module::getConfig() ,
and play with :
return include __DIR__ . '/../config/module.config.php';
I have added '../' prefix and it works well .
I have ZF 1 where i got working Bootstrap.php with lots of routing and other preDispatch stuff.
But in ZF2 there is no Bootstrap.php concept anymore? Or i mean how can i do this same in Zf2?
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initPdispatch() {
$this->bootstrap('frontController');
require_once APPLICATION_PATH . '/controllers/plugin/LanguageSelector.php';
$plugin = new LanguageSelector();
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin($plugin);
return $plugin;
}
protected function _initRoutes() {
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$dynamic1 = new Zend_Controller_Router_Route(
'/:variable1',
array(
'controller' => 'router',
),
// array('variable1' => '^[a-zA-Z0-9_-]*$')
array('variable1' => '^[\w.-]*$')
);
$router->addRoute('dynamic1', $dynamic1);
}
One of the best features of ZF2 is something that I actually hated at first, which are the routes. It's both great and annoying because now you're required to set the routes for all of your modules.
Part of understanding ZF2 (more quickly) is understanding modules. If you can get past this, you will begin to adapt much more quickly. (At least that's how it was for me). So, what in ZF2 is a module? Anything!
Anyway, all of the config files for every module and for the application eventually get merged within the Zend Framework, so that means you can define routes anywhere really.
That said, you don't need to "bootstrap" your routes anymore as that is part of your ModuleName/config/module.config.php file. now.
Now, I'm not an expert on regex routes within ZF2, but it would be something like:
// MyModule/config/module.config.php
return array(
'router' => array(
'routes' => array(
'dynamic1' => array(
'type' => 'regex',
'options' => array(
'route' => '/[:variable1]'
)
)
)
)
);
Somewhere in there you define the regex. Additionally, I saw in their docs that you can also define a regex route manually:
use Zend\Mvc\Router\Http\Regex;
// ...
$route = Regex::factory(array(
'regex' => '/blog/(?<id>[a-zA-Z0-9_-]+)(\.(?<format>(json|html|xml|rss)))?',
'defaults' => array(
'controller' => 'Application\Controller\BlogController',
'action' => 'view',
'format' => 'html',
),
'spec' => '/blog/%id%.%format%',
));
$router->addRoute($route);
You should be able to add this as a service or put it in onBootstrap() within the Application module if you're using the Skeleton Application.
Keep in mind, that was their example and again, I'm not an expert on this. Here is some more information.
Hope this helps!
I'm writing a PHP application using
PHP 5.3 and Zend Framework 1.11.7.
I created model resource using the following command:
protected function _initLoader()
{
$loader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Default',
'basePath' => APPLICATION_PATH,
));
$loader -> addResourceType ( 'model', 'models', 'Model');
}
now whenever i use a class name that starts with Default_Model_ it goes and searches in models directory. under models directory i have a directory called mapper.
how can I configure that whenever a class is being used that starts with Default_Model_Mapper_ to auto-load it from models/mapper ?
ZF should find any directory under models automatically. Also you shouldn't need to include the default module either.
Model_
Model_Mapper_
Also to setup ZF modules I have the following 2 lines of code in my application.ini file
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] =
And the following in my bootstrap
protected function _initModuleAutoload()
{
$modelLoader = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH . '/modules/default'));
return $modelLoader;
}
I hope this is of some help
Kind regards
Garry
Add this one:
$loader->addResourceType('mapper', 'models/mapper', 'Model_Mapper_');
The order in which you declare the two resource types might matter. So try it both ways; one of them should work.
It is set by default in Zend_Application_Module_Autoloader in initDefaultResourceTypes:
$this->addResourceTypes(array(
'dbtable' => array(
'namespace' => 'Model_DbTable',
'path' => 'models/DbTable',
),
'mappers' => array(
'namespace' => 'Model_Mapper',
'path' => 'models/mappers',
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms',
),
....
I can't get Zend to autoload a custom form element class. I did things exactly as Marcin describes here (except that my classes start with 'Zend' and not 'my' but I'm getting this error:
Warning: include_once(Zend\Form\Element\Div.php) [function.include-once]: failed to open stream: No such file or directory
I have Zend_Form_Element_Div inside forms\elements\ and Zend_View_Helper_FormDiv inside views\helpers\
Basically, every folder in the error message is missng an 's', the right path is Zend\Forms\Elements\Div.php
I also have this in my bootstrap, though I'm not sure if it's necessary, but I'm also using this for my forms and models folder (and some others, but I don't think there's need to post them all):
<?php
$resourceLoader->addResourceTypes(array(
'model' => array(
'namespace' => 'Model',
'path' => 'models'
),
'element' => array(
'namespace' => 'Element',
'path' => 'elements'
),
'form' => array(
'namespace' => 'Form',
'path' => 'forms'
)
));
?>
(Is there actually any other way of doing this autoloading? Instead of declaring every single folder?)
Update:
Element_Div in application/forms/elements/Div.php
In my forms init() method: $this->addElementPrefixPath('Element_', APPLICATION_PATH . '/forms/elements');
Error I'm getting: Fatal error: Class 'Element_Div' not found in C:\xampplite\htdocs\code\application\forms\PostForm.php on line 63
You essentially have to tell the form where to find custom elements by using:
$form->addElementPrefixPath()
In your case, you would use - either within the form's init() or __construct() method - something like:
$this->addElementPrefixPath('Zend_Form_Element_', APPLICATION_PATH . '/elements);;
However, I have agree with #Marcin. Naming your own classes with the Zend_ pseudo-namespace is ill-advised. Either:
Decide on an application namespace and declare it in your Bootstrap when you create your $resourceLoader
Create an custom library that resides on your include path - probably at the same level as the Zend library - and put your custom stuff out there.
Let me know if you need more details on either of these suggestions and I'll fatten up the explanations a bit.
Update based on comments
Using an empty appnamespace, your call to addElementPrefixPath() now changes to:
$this->addElementPrefixPath('Element_', APPLICATION_PATH . '/elements);
And I guess you could remove the elements entry from the $resourceLoader definition in your Bootstrap since it's really not doing anything.
Update 2
I assumed that you were adding the element to the form using the shortname, something like:
$form->addElement('div', 'my_div');
In this circumstance, we need to tell the $form and its plugin registry where to find an element of type 'div'. That's why we dealt with $form->addElementPrefixPath().
However, from the error message you are reporting, it appears that you are adding your custom element to the form using something like:
$div = new Element_Div();
$form->addElement($div, 'my_div');
In this case, it is not the $form and its plugin registry that has to worry about finding/loading/instantiating the custom element; it is the $autoloader via its $resourceLoader. In that case, there is no need for the $form->addElementPrefixPath(), which is essentially a hint to the form on how to find custom elements invoked by shortname.
What we need is to configure the $resourceLoader back in Bootstrap so it knows where to find the class. Assuming you stick with empty appnamespace (so your class is named Element_Div) and you place the file in application/forms/elements/Div.php, then the $resourceLoader call is as follows:
$resourceLoader->addResourceTypes(array(
'model' => array(
'namespace' => 'Model_',
'path' => 'models'
),
'element' => array(
'namespace' => 'Element_',
'path' => 'forms/elements'
),
'form' => array(
'namespace' => 'Form_',
'path' => 'forms'
)
));
That should do it. [Famous last words, eh?]
I prefer creating forms like this:
$form->addElement(new My_Form_Element_Whatever(array(
'name' => 'my_element',
'label' => 'My element',
)));
or
$form->addElement($whatever = new My_Form_Element_Whatever(array(
'name' => 'my_element',
'label' => 'My element',
)));
$whatever->removeDecorator('Errors');
when I need to further modify the element.