This question is related to an earlier question I had, but I learned a bit more now, and that question became too messy, so I start a new question here.
I am trying to use Yii and PHPUnit at the same time, and try to get the Autoloading working. I found an Autoloader here that I am using for PHPUnit. I read here that I should register the Yii autoloader last.
With the following bootstrap file:
<?php
require_once(__DIR__.'/../tests/AutoLoader.php');
Toolbox\Testing\AutoLoader::registerDirectory(__DIR__.'/../protected');
require_once(__DIR__.'/../yii-1.1.14.f0fee9/yii.php');
print_r(spl_autoload_functions());
?>
I see that the autoloaders are in place in the right order:
[1] => Array
(
[0] => Toolbox\Testing\AutoLoader
[1] => loadClass
)
[2] => Array
(
[0] => YiiBase
[1] => autoload
)
However, I still can't import the class I need. It goes wrong in YiiBase in the function autoload in the line include($className.'.php');, which tries to include a class name without a path attached to it.
Why does Yii try to load a class without a full path to the file needed?
How can I make this combination to work?
Related
I'm working on a Zend Framework (1.11) application that I am porting into modules so that the devs can plug and play various additions to our software and remove just as easily.
The issue I'm having (and don't seem to be able to find an answer for is) I have dependable library code, i.e my structure is currently this
- application
- (the standard ZF stuff)
- modules
- testModule
- Bootstrap.php
- controllers
- configs
- views
- library
- CoreStuff
- Class.php
- SpecialClass.php
- testModuleLibrary
- Class.php
- SpecialClass.php
And what I really want is this so that it is easier for the other devs to install modules to our system.
- application
- (the standard ZF stuff)
- modules
- testModule
- Bootstrap.php
- controllers
- configs
- views
- library
- Class.php
- SpecialClass.php
- library
- CoreStuff
- Class.php
- SpecialClass.php
Can I use the Autoloader in the module Bootstrap? or do I have to add it to my include path?
[EDIT]
This is my current module bootstrap, I've seen this code time and time again with my perilous Googling but it doesn't appear to make any difference
<?php
class Notifications_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initLibraryAutoloader () {
return $this->getResourceLoader()->addResourceType('library', 'library', 'library');
}
}
I have resolved my issue with the following code. I literally have no idea why I didn't come up with this earlier :( :(
class Notifications_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initConfig () {
set_include_path(implode(PATH_SEPARATOR, array(
dirname(__FILE__) . '/library',
get_include_path(),
)));
}
}
You can define your library paths in the application config file like:
This is example in YML
project:
bootstrap:
path: APPLICATION_PATH/Bootstrap/index.php
class: Bootstrap_Index
Autoloadernamespaces:
- Zend_
- Library1_
- Library2_
resources:
FrontController:
moduledirectory:
- APPLICATION_PATH/modules
......
Here is example in INI format
[bootstrap]
Autoloadernamespaces[] = "Zend_"
Autoloadernamespaces[] = "Library1_"
Autoloadernamespaces[] = "Library2_"
resources.FrontController.moduleDirectory = APPLICATION_PATH"/modules"
resources.FrontController.resetRouterOnEveryRequest = true
bootstrap.path = APPLICATION_PATH "/Bootstrap/index.php"
bootstrap.class = "Bootstrap_Index"
Regarding the project directory structure I advise you to use something similar to:
- application
- Bootstrap
- index.php
- Modules
- Mod1
- controllers
- views
- Mod2
- controllers
- views
...
- library
- Zend
- ...
- Library1
- ...
- Library2
- ...
Having done the directory structure you can have URLs like /:module/:controller/:action and keep all 3rd party code separate in its own pool Library directory
You may just use the modules' Boostrap.php.
Provide a function
protected function _initAutoload(){}
to make the lib available. Thus you may just make the module-developer do it, as it is part of the work developing a module to make it's resources loadable :)
I'm adding this response to hopefully both answer the original inquiry, as well as provide some clarification on a few items submitted here. I'm an active developer of modules in ZF 1.11, and use what I'm about to explain everyday in one of the several modules we maintain.
My apologies ahead of time for the length of this response. There are several items to cover and consider.
First, for the implementation.
The following snippet that was provided as far as I know worked ~1.8, and would not be what you want for 1.11.
<?php
class Notifications_Bootstrap extends Zend_Application_Module_Bootstrap {
protected function _initLibraryAutoloader () {
return $this->getResourceLoader()->addResourceType('library', 'library', 'library');
}
}
The following though would work fine provided a few key elements I'll explain below.
protected function _initLibraryAutoloader () {
return $this->getResourceLoader()->addResourceType('library', 'library', 'Library_');
}
You'll notice a slight difference in the third parameter ( the namespace ). The best explanation of this would be to possibly update the function to the following:
protected function _initLibraryAutoloader () {
$this->getResourceLoader()->addResourceType('library', 'library', 'Library_');
var_dump($this->getResourceLoader()->getResourceTypes());die;
}
Your output should be something similar to:
Array
(
[dbtable] => Array
(
[namespace] => Admin_Model_DbTable
[path] => /path/to/trunk/application/modules/admin/models/DbTable
)
[mappers] => Array
(
[namespace] => Admin_Model_Mapper
[path] => /path/to/trunk/application/modules/admin/models/mappers
)
[form] => Array
(
[namespace] => Admin_Form
[path] => /path/to/trunk/application/modules/admin/forms
)
[model] => Array
(
[namespace] => Admin_Model
[path] => /path/to/trunk/application/modules/admin/models
)
[plugin] => Array
(
[namespace] => Admin_Plugin
[path] => /path/to/trunk/application/modules/admin/plugins
)
[service] => Array
(
[namespace] => Admin_Service
[path] => /path/to/trunk/application/modules/admin/services
)
[viewhelper] => Array
(
[namespace] => Admin_View_Helper
[path] => /path/to/trunk/application/modules/admin/views/helpers
)
[viewfilter] => Array
(
[namespace] => Admin_View_Filter
[path] => /path/to/trunk/application/modules/admin/views/filters
)
[library] => Array
(
[namespace] => Admin_Library
[path] => /path/to/trunk/application/modules/admin/library
)
)
If you compare this to your previous "library" as the third parameter, you'll see in a second why it makes such an important difference.
To reiterate, at this point, you've declared a library type with the prefix of "Library_", which is translating to "Admin_Library". Now, to implement this, you'll have your library folder in your module just as you do in your main application module, with one slight adjustment. To have an Admin module specific controller action ( Admin_Library_Controller_Action ), you'll have library/Controller/Action.php, with a class name of Admin_Library_Controller_Action. This is what most find confusing at first, but it's very similar to the other resource namespaces you should be using in modules.
That concludes the technical explanation. If you read no further, you'll be able to have a library specific to your module and totally self-contained for easy copy/paste implementation of a reusable module.
Now for a few comments about some of the other responses I saw here.
infinity noted
"If you follow your structure you might end up with - Module1 (Lib1, Lib2) - Module2 (Lib1, Lib3) so you'll start duplicating the needed libraries."
This is technically correct, but really brings to light more issues in your actual development style if you find yourself routinely using the same libraries all over the place. We generally store these common items in another library, that we use as an external, identical to Zend, and is placed along side Zend in the main application library folder.
Provided you're already doing that, Where I believe some additional clarification might be needed is, if you're using the namespaces correctly, you absolutely don't have to worry about a collision of library class names. You may for a short period of time find that you need to have classes with identical code in multiple modules, but as soon as this happens, you should consider the common library in addition to Zend that I mentioned above.
My apologies again for the length of this response. I hope that it helps anyone who might come across this post in need of library implementation in modules.
I am new to zend framework and I am working on REST web service API. While my model output is protected object variables Zend_Rest_Server(). It is unable to handle that and throw an error.
Array
(
[0] => Webservices_Models_Token Object
(
[_id:protected] => 1
[_token_key:protected] => 123
[_mapper:protected] =>
)
)
While why model is returning above result, I am getting error. I got this result from zend model mapper.
Oh Dear!
You seem to have arrived here by error, or the page you are seeking
has been removed and can no longer be displayed.
Perhaps you are looking for a page that has been moved during the
recent improvements to our website. An error occurred ** This needs to
be altered before go live Exception information:
Message: Invalid Character Error
Bellow output works fine and generating xml from $this->_server = new Zend_Rest_Server()
Array
(
[0] => stdClass Object
(
[id] => 1
[token_key] => 123
)
)
Can anyone tell me whats the problem?
How can I solve it?
This is did the trick for me. toArray()
$select = $this->getDbTable()->select()->where($where);
return $this->getDbTable()->fetchAll($select)->toArray();
Thanks.
Fatal error: Call to a member function get() on a non-object on
pr($transaction->invoice->get());
I am getting a weird message. I know for sure the method is there, and is available to use, and even double checked before using it. What's wrong here?
pr(get_class_methods($transaction->invoice));
Array
(
[0] => __construct
[1] => get
[2] => __toString
[3] => getHref
[4] => setHref
[5] => _get
)
Update:
var_dump(is_object($transaction->invoice)); evaluated as bool(true)
None of the methods work. I'm so confused! I think this is one of those edge cases. I'm using Recurly library.
Update
Looks like some objects coming back were un-instantiating themselves. That's weird. I didn't know PHP does this.
What you experience here is Magic. As Magic is so hard to understand, it's even harder to debug. Expect a large chunk of that Recurly PHP library to be based on Magic.
Looks like some objects coming back were un-instantiating themselves. That's weird. I didn't know PHP does this.
It's not PHP, but the library. It makes use of magic getters and setters and other magic stuff for the properties. They must have been driven by some wizard being so much in love with magic. Don't you feel enchanted yet?
Best way to get above the Magic is that you install yourself a step debugger like Xdebug and then set a breakpoint and inspect the values directly. All common PHP IDEs have support for xdebug remote debugging (even this is called remote debugging, it works on your local development machine, too).
I know there are several threads asking similar questions - but I havent found any real answers to solve this specific syntax error, I have followed the tutorial over and over again and still end up with these error - I know its looking for a missing node in relationship between the ACL and ACO - ugh, please help
Warning (512): DbAcl::check() - Failed ARO/ACO node lookup in permissions check. Node references:
Aro: Array
(
[User] => Array
(
[id] => 1
[username] => admin
[group_id] => 1
[created] => 2012-06-15 14:20:44
[modified] => 2012-06-15 14:20:44
)
)
Aco: controllers/Pages/display [CORE/Cake/Controller/Component/Acl/DbAcl.php, line 79]
It looks like your app can't find the aco record for the display action of the Pages controller. The quickest way to ensure you have all your aco's loaded into your db is use the AclExtras Plugin, this will scan through your controller files and add all actions to your aco table.
Hi there people and greetings from Sweden!
I have a really tricky problem here. I'll try to show exactly what I mean.
I'm building a modulebased CMS, and some modules inherit from a parent module. My problem is that the parent modules need to be included before the "children".
I fetch moduleinfo from a XML file and store it in an array like this:
Array
(
[bloggy] => Array
(
[module_id] => blog
[module_name] => Blog
[module_desc] => Description
[module_url] => http://www.url.se
[author] => Dev Name
[author_url] => http://url.se
[version] => 1.0
[inherit] => core|twitter
[path] => /path/to/file
[dependon] => Array
(
[0] => core
[1] => twitter
)
)
I've done a explode on inherit and saved it into "dependon" as you see above. The problem now is, how can I sort which order to include the files. Every module inherits from core but if there is another module in the depenon array then the "child" module must be included after.
I hope you understand what I mean?
// Tobias
Look up "topological sort".
You could build you modules as classes and then use the __autoload magic function to automatically include/require all needed php files.
That way it's much less of a headache when you have complex dependencies.
Refer to the PHP manual for details on autoloading.
Just include all dependencies in your files. Try
// module1.php
require_once 'core.php'
// module2.php
require_once 'core.php'
require_once 'module1.php'
// module3.php
require_once 'core.php'
require_once 'module1.php'
require_once 'module2.php'
Including module3 will also include module2, module1 and core. You could leave out the core and module1 in module 3 and it would still load them all, but then you have to know what includes which.
Or use autoloading and don't bother about it.
Hmm I'll try to explain a little better.
I search the module folder for the xml info file and save the data into an array, I also save the path to the file in the array.
Then I use a foreach loop to include and instantiate the modules. My problem is that the parent modules must be instantiated before the "children".
I do not want to touch the core files when adding a new module, I need to use the hooks on a parent module.