I have a test module. In test module I have a Form in forms folder.
myproject/application/modules/test/forms/TestForm.php
class Test_Form_TestForm extends Zend_Form {
//form elements
}
myproject/application/modules/test/controllers/TestController.php
class Test_TestController extends Zend_Controller_Action {
public function indexAction() {
$this->view->form = new Test_Form_TestForm(); // this is generating error
}
} // end class
Form initialization in controller is generating following error:
Fatal error: Class 'Test_Form_TestForm' not found in C:\wamp\www\student\application\modules\notification\controllers\NotificationController.php on line 16
How to make this form accessable in controller. Same type of case is working with default controller. I know I have to register my module in bootstrap with Form_ indicator but dont know exact syntax.
You can also initialize multiple modules in a separate function in one Bootstrap file like:
protected function _initAutoloaders() {
$test_loader = new Zend_Application_Module_Autoloader( array( 'namespace' => 'Test',
'basePath' => APPLICATION_PATH . '/modules/test'
));
$mynew_loader = new Zend_Application_Module_Autoloader( array( 'namespace' => 'Mynew',
'basePath' => APPLICATION_PATH . '/modules/mynew'
));
}
In order for Zend Autoloader to work for your modules, you need to have bootstraps for all of your modules, and also modules resource initialized.
So, in your application/modules/test/Bootstrap.php:
class Test_Bootstrap extends Zend_Application_Module_Bootstrap {}
Upd:
And in your application/configs/application.ini:
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.modules[] =
More info about autoloading in modules here
Vika's answer is correct on how to setup modules autoloader.
Your error states that the form class cannot be found in notification module under NotificationController controller.
So you need to have bootstrap class for the notification module
In your application/modules/notification/Bootstrap.php:
class Notification_Bootstrap extends Zend_Application_Module_Bootstrap {}
I don't know if this is the best way, but it works.
In your bootstrap
...
$autoloader = new Zend_Loader_Autoloader_Resource(array('namespace' => '', 'basePath' => APPLICATION_PATH));
$autoloader->addResourceType('Test_Form', '/test/forms', 'Test_Form');
...
Vika's answer seems to be correct.
If you still having problems, try modify your application.ini
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.moduleDefault = "test"
resources.modules[] = "test"
resources.modules[] = "other"
If you specify exact module names in resource list, Zend will auto-magically register the Form and other resource auto-loaders. In debugging case modules/test/Boostrap.php should be triggered and any _init method inside. Have fun.
Related
I am new to yii and i have to create a yii component for Enom api .I have followed this url Enom application for refrence . It is in core php and i want to implement this in yii as component or module .I have done in this way
put the files interface and class in the yii component folder.
modify the class as mentioned here yii custom component . Now my class name is EnomService and interface name is EnomInterface
i have added these lines also in my class
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
modified the main.php file in config folder:
'import'=>array(
'application.models.*',
'application.components.*',
),
'defaultController'=>'post',
// application components
'components'=>array(
'user'=>array(
// enable cookie-based authentication
'allowAutoLogin'=>true,
),
'mycomponent' => [
'class' => 'app\components\EnomService',
],
calling in the controller in this way .
public function actionEnom ()
{
echo "asdgsgsag";
$enom = new EnomService('manoj_rudra', 'manoj#41#', false, true);
$enom->debug = true;
$result= Yii::$app->EnomService->checkDomain('systurn', 'com', true);
//$result = $enom->checkDomain('systurn', 'com', true); // This enables domain spinner
echo '<pre>';
var_dump($result);
echo '</pre>';
}
But it is not working . I am not so much familiar with yii custom component . Please help me to create this .
Are you using Yii or Yii2?
If it is Yii, then you could use plenty of other existing extensions to inspire yourself, for example this one: https://github.com/HeavyDots/yii-sms
As for Yii2 you could do something similar, look into already existing extensions for Yii2 on YiiFramework website and you can see how component classes are defined.
I would recommend:
1) Create a new directory inside "components" named "enom"
2) Place inside that directory all your enom files from https://github.com/comdexxsolutionsllc/MoondayFramework/tree/master/engine/enom
3) Create the component class called "Enom.php" inside the directory, something like this:
<?php
// include enom service class
require(dirname(__FILE__).'/class.EnomService.php');
namespace components\enom;
use Yii;
class Enom extends \yii\base\Component
{
// define private property to store service
private $service;
public function init()
{
parent::init();
// init the service
$this->service=new EnomService('manoj_rudra', 'manoj#41#', false, true);
}
/**
* #return EnomService
*/
public function getService() {
return $this->service;
}
}
?>
4) Then in the configuration properly define the component
'enom' => [
'class' => 'app\components\enom\Enom',
],
5) And finally use it like this
Yii::$app->enom->getService()->checkDomain
As I said before, haven't used Yii2 yet so this might need tweaking but could point you on the right path.
Hello all im trying to load multiple libraries which is in different folders in library folder using namespaces but i keep getting not found
My directory structure is like this
app/
controllers/
models/
library/
views/
My loader.php is like this
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerNamespaces(array(
'Test\Name' => __DIR__ . "/../library/",
));
$loader->registerDirs(
array(
$config->application->controllersDir,
$config->application->modelsDir
)
)->register();
And my basecontroller is trying to call like this
$var = new Test\Name\functions();
and btw the file functions in library is like this
class functions extends Phalcon\Mvc\User\Component
{
public function __construct()
{
}
public function initialize()
{
}
public function checking(){
echo 'checks';
}
}
i Keep getting
Fatal error: Class 'Test\Name\functions' not found in C:\wamp\www\app\controllers\ControllerBase.php on line 38
Any help is appreciated guys thnx
I think that your class should have:
namespace Test\Name;
class functions extends Phalcon\Mvc\User\Component
{
// ... rest of it
on top.
I would also make this configuration:
$loader->registerDirs(
array(
$config->application->controllersDir,
$config->application->modelsDir,
__DIR__ . "/../library/",
)
)->register();
So your class would be in (also I would rename your class to Functions:
app/library/Test/Name/Functions.php
So it would be obvious that your Functions class is in Test\Name namespace.
Having trouble finding the discussion that clued me in but, my understanding is that when using namespaces, you use namespaces. When using directories and other rules, you don't use namespaces.
Namespaces are faster so probably best to just stick with them, dropping the registerDirs as they are superfluous and mean the same thing as the namespaces:
library\Test\Name.php
becomes:
$loader->registerNamespaces(array(
'Apps\Module\Controllers' => $config->application->controllersDir,
'Apps\Module\Models' => $config->application->modelsDir,
'Test' => __DIR__ . "/../library/Test",
));
Then available as Test\Name.
$loader->registerNamespaces(array(
'App' => __DIR__ . "/../library/",
), true);
it will merge all sub dir, if you librarry dir architecture like this
library
- Test
- Name.php
You can call new \App\Test\Name();
How I can get access to my module config from the controller?
I am really surprised at how obscure this is, because I had exactly the same problem and could not find a definitive answer. One would think the ZF2 documentation would say something about this. Anyhow, using trial and error, I came across this extremely simple answer:
Inside controller functions:
$config = $this->getServiceLocator()->get('Config');
Inside Module class functions (the Module.php file):
$config = $e->getApplication()->getServiceManager()->get('Config');
whereas $e is an instance of Zend\Mvc\MvcEvent
In general, the config is accessible from anywhere you have access to the global service manager since the config array is registered as a service named Config. (Note the uppercase C.)
This returns an array of the union of application.config.php (global and local) and your module.config.php. You can then access the array elements as you need to.
Even though the OP is quite old now, I hope this saves someone the hour or more it took me to get to this answer.
What exactly do you want to do in your controller with the module configuration? Is it something that can't be done by having the DI container inject a fully configured object into your controller instead?
For example, Rob Allen's Getting Started with Zend Framework 2 gives this example of injecting a configured Zend\Db\Table instance into a controller:
return array(
'di' => array(
'instance' => array(
'alias' => array(
'album' => 'Album\Controller\AlbumController',
),
'Album\Controller\AlbumController' => array(
'parameters' => array(
'albumTable' => 'Album\Model\AlbumTable',
),
),
'Album\Model\AlbumTable' => array(
'parameters' => array(
'config' => 'Zend\Db\Adapter\Mysqli',
)),
'Zend\Db\Adapter\Mysqli' => array(
'parameters' => array(
'config' => array(
'host' => 'localhost',
'username' => 'rob',
'password' => '123456',
'dbname' => 'zf2tutorial',
),
),
),
...
If you need to do additional initialization after the application has been fully bootstrapped, you could attach an init method to the bootstrap event, in your Module class. A blog post by Matthew Weier O'Phinney gives this example:
use Zend\EventManager\StaticEventManager,
Zend\Module\Manager as ModuleManager
class Module
{
public function init(ModuleManager $manager)
{
$events = StaticEventManager::getInstance();
$events->attach('bootstrap', 'bootstrap', array($this, 'doMoarInit'));
}
public function doMoarInit($e)
{
$application = $e->getParam('application');
$modules = $e->getParam('modules');
$locator = $application->getLocator();
$router = $application->getRouter();
$config = $modules->getMergedConfig();
// do something with the above!
}
}
Would either of these approaches do the trick?
for Beta5, you can add function like this in Module.php
public function init(ModuleManager $moduleManager)
{
$sharedEvents = $moduleManager->getEventManager()->getSharedManager();
$sharedEvents->attach(__NAMESPACE__, 'dispatch', function($e) {
$config = $e->getApplication()->getConfiguration();
$controller = $e->getTarget();
$controller->config = $config;
});
}
in controller, you can get config :
print_r($this->config);
To read module-only config your module should just implement LocatorRegisteredInterface
Before:
namespace Application;
class Module
{
// ...
}
After:
namespace Application;
use Zend\ModuleManager\Feature\LocatorRegisteredInterface;
class Module implements LocatorRegisteredInterface
{
// ...
}
That implementation says LocatorRegistrationListener to save module intance in service locator as namespace\Module
Then anywhere you can get access to your module:
class IndexController extends AbstractActionController
{
public function indexAction()
{
/** #var \Application\Module $module */
$module = $this->getServiceLocator()->get('Application\Module');
$moduleOnlyConfig = $module->getConfig();
// ...
}
}
There is a pull request ready now which pulls the module class (so the modules/foo/Module.php Foo\Module class) from the DI container. This gives several advantages, but you are also able to grab that module instance another time if you have access to the Zend\Di\Locator.
If your action controller extends the Zend\Mvc\Controller\ActionController, then your controller is LocatorAware. Meaning, upon instantiation your controller is injected with the locator knowing about modules. So, you can pull the module class from the DIC in your controller. Now, when your module consumes a config file and stores this inside the module class instance, you can create a getter to access that config data from any class with a locator. You probably have already an accessor with your module Foo\Module::getConfig()
While ZF2 is heavily under development and perhaps this code will change later on, this feature is currently covered by this test, with this the most relevant part:
$sharedInstance = $locator->instanceManager()->getSharedInstance('ListenerTestModule\Module');
$this->assertInstanceOf('ListenerTestModule\Module', $sharedInstance);
So with $sharedInstance your module class, you can access the config from there. I expect a shorthand for this feature soon, but this can only be done after PR #786 has been merged in ZF2 master.
You need to implements ServiceLocatorAwareInterface from your model. And then you can set setServiceLocator() and getServiceLocator() which give you direct access to the service manager. Take a look at this code sample https://gist.github.com/ppeiris/7308289
I created the module with controller plugin and view helper for reading a config in controllers and views. GitHub link __ Composer link
Install it via composer
composer require tasmaniski/zf2-config-helper
Register new module "ConfigHelper" in your config/application.config.php file
'modules' => array(
'...',
'ConfigHelper'
),
Use it in controller and view files
echo $this->configHelp('key_from_config'); // read specific key from config
$config = $this->configHelp(); // return config object Zend\Config\Config
echo $config->key_from_config;
you can also access any config value anywhere by this hack/tricks
$configReader = new ConfigReader();
$configData = $configReader->fromFile('./config.ini');
$config = new Config($configData, true);
I have a questiom regarding the Zend Framework 2:
I have
library/System and library/Zend. the system is my custom library, which I want to configure de aplication (routes, modules, etc., and redirect user to correct module, controller and/or action).
I don't want to do this inside each application/modules/ModuleName/Module.php file. So, my library/System can do everything related to application configuration.
As said in the comments above: register to the bootstrap-event and add new routes there:
<?php
namespace Application;
use Zend\Module\Manager,
Zend\EventManager\StaticEventManager;
class Module
{
public function init(Manager $moduleManager)
{
$events = StaticEventManager::getInstance();
$events->attach('bootstrap', 'bootstrap', array($this, 'initCustom'), 100);
}
public function initCustom($e)
{
$app = $e->getParam('application');
$r = \Zend\Mvc\Router\Http\Segment::factory(array(
'route' => '/test',
'defaults' => array(
'controller' => 'test'
)
)
);
$app->getRouter()->addRoute('test',$r);
}
}
$app = $e->getParam('application'); does return an instance of Zend\Mvc\Application. Have a look there to see which additional parts you can get there. The bootstrap event is fired before the actual dispatching does happen.
Note that the ZendFramework 1 routes are not always compatible to the ZendFramework 2 ones.
Update to comments
public function initCustom($e)
{
$app = $e->getParam('application');
// Init a new router object and add your own routes only
$app->setRouter($newRouter);
}
Update to new question
<?php
namespace Application;
use Zend\Module\Manager,
Zend\EventManager\StaticEventManager;
class Module
{
public function init(Manager $moduleManager)
{
$events = StaticEventManager::getInstance();
$events->attach('bootstrap', 'bootstrap', array($this, 'initCustom'), 100);
}
public function initCustom($e)
{
$zendApplication = $e->getParam('application');
$customApplication = new System\Application();
$customApplication->initRoutes($zendApplication->getRouter());
// ... other init stuff of your custom application
}
}
This only happens in one zf2 module (named Application which can be the only one as well). This doesn't fit your needs? You could:
extend a custom module autoloader
extend Zend\Mvc\Application for your own logic
make your code zf2-compatible
I'm using the default framework code that was created with the Zend Framework Application tool, I added some autoloader magic so that any classes named Default_<*>_<*> would automatically be loaded from the correct directory, in this case Default_Model_TableName.
application/models/ProjectCategories.php:
<?php
class Default_Model_ProjectCategories extends Zend_Db_Table_Abstract {
protected $_name = 'categories';
protected $_dependentTables = array('Projects');
}
application/models/Projects.php:
<?php
class Default_Model_Projects extends Zend_Db_Table_Abstract {
protected $_name = 'projects';
protected $_referenceMap = array(
'Category' => array(
'columns' => 'cid',
'refTableClass' => 'ProjectCategories',
'refColumns' => 'id',
'onUpdate' => self::CASCADE,
'onDelete' => self::CASCADE,
)
);
}
What I am attempting to do is the following:
<?php
$categories = new Default_Model_ProjectCategories();
$category = $categories->find('1');
$category->findProjects();
At which point I get an error thrown at me that it is unable to find Projects.php, and or that the file might not have contained a class named Projects.
At that point I place Projects.php in the include path that was set up by the framework (/../library/) and the file is found, but now I lose my whole directory structure, and naming because I had to rename Default_Model_Projects to Projects. I am able to get everything to work if I place the file back in its original location, and change
protected $_dependentTables = array('Projects');
to
protected $_dependentTables = array('Default_Model_Projects');
but this also means that my ->findProjects() now becomes ->findDefault_Model_Projects().
Is there a way to tell it that when I am looking for findProjects() that it has to instantiate Default_Model_Projects? Is this something that is missing from Zend Framework, or am I attempting to shoehorn something in a way that it does not belong? How have you solved this issue?
This problem may have been introduced by the new Autoloader, and the way in which it prefers to load namespaced classes (e.g. those prefixed as you have ).
In my applications I simply name models like 'Projects' and add a separate models folder to the include path for that application. This is one solution - unfortunately I don't know how you can make the namespaced models load correctly, but I would suggest looking at Zend_Loader in greater detail, and possible the pluginLoaders.
i used to be able to do something like
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
'basePath' => APPLICATION_PATH,
'namespace' => 'App',
));
$resourceLoader->addResourceType('model', 'models/', '');
to shrink my model classes to App_TableName but seems like its not working now...
Change
protected $_dependentTables = array('Projects');
to
protected $_dependentTables = array('Default_Model_Projects');