Access my ZF models (application/models) without a prefix/namespace? - php

My Zend Framework setup is like this:
/application
/modules
/models
/configs
/library
/public
I want to access my models without needing prefixes or namespaces, like this:
new User() // Would refer to /application/models/User.php
I know this is a fairly simple problem, but I havn't been able to figure it out yet. I've also seen a lot of similar questions but none that I thing were this one exactly, but please forgive me if I am duplicating an existing question.
So far, I have tried changing appnamespace to "" in my config.ini with no success and adding
the following to my Bootstrap with no success:
protected function _initAutoload()
{
$autoloader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => '',
'basePath' => APPLICATION_PATH . '/models',
));
}
Thanks!

You have to use the fallback autoloader..
In your Bootstrap file (or wherever you like), do this:
protected function _initAutoloader()
{
Zend_Loader_Autoloader::getInstance()->setFallbackAutoloader(true);
}
That will allow you to load any arbitrary class that is in your path, even if you've registered specific autoload prefixes in your application.ini
And to clarify, make sure you are pushing APPLICATION_PATH . "/models" into your include_path at some point..

Related

RegisterNamespace in Zend Framework 1.12

I've deleted every Zend Framework class in the folder "library/Zend", I used the 1.7 version and wanted to upgrade to 1.12. After the deletion I've uploaded the Zend Framework 1.12 classes in "library/Zend".
I'm facing an issue in loading the classes. In "public/index.php" I used registerAutoload(). This was depricated so I changed it to this:
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
Then, for each class I use in the Controller I have to manually add it like this:
$loader->registerNamespace('Paths');
$loader->registerNamespace('Certificate');
$loader->registerNamespace('Zim_Properties');
$loader->registerNamespace('Zim_Controller_Dispatcher');
$loader->registerNamespace('Controller_Plugin_ActionSetup');
$loader->registerNamespace('Controller_Plugin_History');
$loader->registerNamespace('Zim_Model');
$loader->registerNamespace('Zim_Controller_Action');
$loader->registerNamespace('Controller_ProposalInvoice');
$loader->registerNamespace('Stats');
$loader->registerNamespace('Controller_ArticleService');
If I remove this registerNamespace I get an Fatal error: Class 'Controller_ArticleService' not found in /home/juliaxd8/domains/jmediatechnology.eu/public_html/factuurtogo2/application/controllers/ArticleController.php on line 3
Because of the manually registration I could forgot something/make a typo. Can I do auto load classes?
I have a function somewhat like this in the Bootstrap.php file in one of my projects, that I think does the trick:
protected function _initAutoload()
{
$modelLoader = new Zend_Application_Module_Autoloader(
array('namespace' => '',
'basePath' => APPLICATION_PATH . '/modules/default'));
return $modelLoader;
}

Zend - db table not found in another module

I have an application with three modules:default, disciplines and plans. In disciplines I have a dbtable which works fine in this module, but if I want to use the dbtable in module plans inside plans_dbtable I get
Class 'Disciplines_Model_DbTable_Disciplines' not found in C:\xampp\htdocs\proiect_mps\application\modules\plans\models\DbTable\Plans.php on line 43.
Require_once and include don't solve the problem. I have Disciplines_Boostrap and Plans_Bootstrap classes written. But it doesn't work. Any ideas?
class Plans_Model_DbTable_Plans extends Zend_Db_Table_Abstract
{
...
public function addPlan(
$year,
$name,
$code,
$domain,
$specialization,
$years)
{
// Id-ul disciplinei
$id_discipline = 0;
$discipline = new Disciplines_Model_DbTable_Disciplines();
....
}
...
}
Since you're using Zend I would not suggest your answer of having a require_once to be the best Basically if you have your configuration nice you dont need to have require_once any place. This might be of a help :
In file application.ini
;Module Configuration
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.moduleControllerDirectoryName = "controllers"
; Enables Modules bootstrap resource plugin, so each module directory has a bootstrap.php file
resources.modules = 1
and in you BootStrap.php file
protected function _initFrontController() {
// The Zend_Front_Controller class implements the Singleton pattern
$frontController = Zend_Controller_Front::getInstance();
// look in the modules directory and automatically make modules out of all folders found
$frontController->addModuleDirectory(APPLICATION_PATH . '/modules');
// forces the front controller to forward all errors to the default error controller (may already be false by default)
$frontController->throwExceptions(false);
return $frontController;
}
And yes you will need to have Bootstrap.php for your every module
class Disciplines_Bootstrap extends Zend_Application_Module_Bootstrap
{
/**
* This file is ABSOLUTELY NECESSARY to get module autoloading to work.
* Otherwise calls to "$form = new Module_Form_MyForm()" will fail.
*/
}
I think I've resolved it myself. I had to write
require_once(APPLICATION_PATH.'/modules/disciplines/models/DbTable/Disciplines.php');
instead of
require_once '/proiect_mps/application/modules/disciplines/models/DbTable/Disciplines.php';
This also works:
require_once('/../../../disciplines/models/DbTable/Disciplines.php');
for my folder structure.

Putting models in library directory in Zend Framework

I want to put models outside module directory in Zend Framework. To be precise, in /library folder
library/
models/
actors/
ActorsMapper.php
Actor.php
books/
BooksMapper.php
Book.php
INSTEAD OF
application/
modules/
models/
actors/
ActorsMapper.php
Actor.php
books/
BooksMapper.php
Book.php
This is done so that I don't have to create separate model for each of the module I create.
What configurations will I have to change?
If you need more details, please ask.
Thank you :)
First answer works, but I will give you another answer in case if you want to register autoload in bootstrap.
1) put 'models' folder into library with all Table.php files.
Every model/class should have:
class Model_Table extends Zend_Db_Table_Abstract{ ... }
2) In bootstrap.php put:
protected function _initAutoLoad() {
// Add autoloader empty namespace
$autoLoader = Zend_Loader_Autoloader::getInstance();
$resourceLoader = new Zend_Loader_Autoloader_Resource(
array(
'basePath' => APPLICATION_PATH,
'namespace' => '',
'resourceTypes' => array(
'model' => array(
'path' => '../library/models/',
'namespace' => 'Model_'
),
),
)
);
return $resourceLoader;
}
That's it. Now you can use your models in controllers like this:
$model = new Model_Table();
If you want to use same models for all modules you can put it in application folder applications/models
and that works fine just like when you have web without modules.
But If you want to have models in library, You can put 'models' folder in your library path and autoload it.
Create folder 'Models' into library with all Table.php files.
In configs/application.ini Put:
autoloaderNamespaces.models = "Models_"
Then you can use namespace 'Models_' in your web application
In controller:
$model = new Models_Table();
in any case, I recommend that you keep the folder models in the path application/models
zend autoloader loading class which name beginning with prefix, that is registred on it.
If you have library in your include path, you can simple register "Models" like default namespace on autoloader and name your class for example Models_Actors_Actor.

Autoloading forms and models for each module in Zend?

How can someone autoload every form and model for each module? Consider the following file structure:
application/
modules/
foo/
forms/
Register.php
models/
Account.php
Bootstrap.php
bar/
forms/
Publish.php
models/
Article.php
Bootstrap.php
Bootstrap.php
And for example, in foo/Bootstrap.php you have the following (non-functional) code:
class Foo_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initAutoLoad()
{
$loader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH . '/modules/foo',
'namespace' => 'Foo',
));
$loader->addResourceType('form', 'forms', 'Form')
->addResourceType('model', 'models', 'Model');
return $loader;
}
}
Basic question: How can the bootstrap be modified so that it does load every form and model from the Foo module?
Extra question: Is it possible to have a global autoloader that loads in forms and models from every module? If so, how?
Edit (most common questions about the issue):
The default Zend naming conventions are being used for classes. Such as Bar_Model_Article, Bar_Model_Mapper_Article, Bar_Model_DbTable_Article, Bar_Form_Publish, ... (And are being placed in their respective folder.)
It isn't just one module that doesn't get its classes loaded, it's all of them.
There is no problem autoloading classes using the Zend autoloader when using a plain no-module application with multiple models, mappers, dbtables and forms.
Fix
As #Tim Fountain mentioned the module bootstraps weren't being run, meaning none of the automatic loading occurred that's baked into Zend. Eventually, I found where the problem was in my case. I had to remove the following lines from my configuration:
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
Agreed, the global bootstrap won't work anymore; but it's a lot better than having module bootstraps not functioning. If anyone knows how to still have the global bootstrap, feel free to leave a comment. Hope this can be of help to others with a similar problem.
The module bootstrap class sets up the module autoloader automatically, so you can remove your example _initAutoload() function leaving just an empty class and it should all just work. See: http://framework.zend.com/manual/en/zend.loader.autoloader-resource.html#zend.loader.autoloader-resource.module
Edit: It sounds like your module bootstraps aren't being run. This is not an uncommon problem as the way it all fits together can be a bit confusing. The quickest way to verify this would be to just add an init method to one of them with an echo and an exit and see if it ever gets output.
Module bootstraps are pulled in and run by the 'modules' resource within Zend Application. You need to trigger this resource in some way because ZF won't go hunting around for module bootstraps just in case they are there. The most common way to do this is to include this line in your application.ini:
resources.modules[] = ""
alternatively you can manually setup the resource from your main Bootstrap file.
I also had it always like that. But since the release of 1.10 (wild guess), you can remove that bootstrap code and just put the following line in your application.ini:
appnamespace = "Foo"
I personally leave mine empty.

Correct Location for Custom Zend_Action_Controller

The ZF Docs reference 'Subclassing the Action Controller' (bottom of the page), but don't reference a standard place to put the new Action_Controller class.
Application_Module_Autoloader sets up pats for a bunch of things, but never controllers. I guess putting it on library/APPNAMESAPCE/Action/Contoller would work. But that seems a bit odd since every other application specific file is stored under application/.
The class gets autoloaded like any other class, there isn't a 'standard' place for it as such. So the question becomes, where do you want it to live?
The convention I usually follow in modular applications is to have most stuff in the modules, but register an app namespace and use application/models for 'core' type classes. So in your case, say your app namespace was Wordpress, you'd have:
class Wordpress_Controller_Action extends Zend_Controller_Action
{
}
and the file would live in application/models/Wordpress/Controller/Action.php.
To make this work you'll need application/models on your include path, and you'll want to init the standard autoloader with something like this (in your bootstrap class):
protected function _initAutoloader()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Wordpress_');
return $autoloader;
}
alternatively you could setup the above in application.ini.

Categories