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.
Related
I'm writting tests and task for a new app for an application and I need to access to the "app config parameters" of this new app defined in /apps/mynewapp/config/app.yml. I thought it will be as easy as written in the Symfony doc, but it seems I've forgotten something.
When I get my config: $actions = sfConfig::get("app_actions") it is NULL. I thought the config name is wrong, but when I get all the config parameters available with sfConfig::getAll(), I don't have my app config parameters.
Maybe I've forgotten to include my /apps/mynewapp/config/app.yml?
There is the content of my file:
all:
.array:
actions:
bind_destroy: BindDestroyAction
bind_subscribe: BindSubscriptionAction
messages:
bind_destroy: BindDestroyMessage
bind_subscribe: BindSubscriptionMessage
And there is how I try to access to my parameters in /apps/mynewapp/lib/GRM/GRMSender.class.php:
class GRMSender
{
private $actionClassNames;
private $messageClassNames;
public function __construct()
{
$this->actionClassNames = sfConfig::get("app_actions");
$this->messageClassNames = sfConfig::get("app_messages");
}
}
The class has already been autoloaded and I'm able to instantiate the class in my unit test scripts.
Thank you for your help.
EDIT
The problem is about my tests (in /test/unit) and my tasks (in /lib/task). I have to use what I did in my application "mynewapp". I did some things :
For the tasks, I defined the application in my task options :
class mynewappActionTask extends sfBaseTask
{
protected function configure()
{
// Do some configuration...
try {
$this->addOptions(array(
new sfCommandOption(
'application',
"app",
sfCommandOption::PARAMETER_REQUIRED,
'The application name',
"mynewapp" // There
),
));
} catch (sfCommandException $e) {}
}
}
For the tests, I wrote a file which loads my mynewapp config. IMHO it's a hack and there is a better way to do it :
$configMynewapp = ProjectConfiguration::getApplicationConfiguration("mynewapp", sfConfig::get("sf_environment"), true);
There must be better ways to get mynewapp config parameters in tasks and in tests. In mynewapp files (controller, lib, etc.) it's ok.
Try to do this:
/apps/mynewapp/config/app.yml
all:
actions:
bind_destroy: BindDestroyAction
bind_subscribe: BindSubscriptionAction
messages:
bind_destroy: BindDestroyMessage
bind_subscribe: BindSubscriptionMessage
Then you can get:
$actions = sfConfig::get('app_actions');
It will return:
$actions => array(
'bind_destroy' => 'BindDestroyAction',
'bind_subscribe' => 'BindSubscriptionAction'
)
Anyway, you can access one of them directly:
$action = sfConfig::get('app_actions_bind_destroy')
$action => 'BindDestroyAction'
I have a Yii 1.x component loaded in the configuration file like so
$config['components']['simplesamlphp'] = array(
'class' => 'application.components.yii-simplesamlphp.components.Simplesamlphp',
'autoloadPath' => SAML_DIR.'/test2/lib/_autoload.php',
'authSource' => 'default-sp',
);
I need to make the autoloadPath property dynamic based on who the user is in the controller. Is this possible? And if so how do I overwrite it?
Probably the best way is to extend Simplesamlphp and configure property in init():
class MySimplesamlphp extends Simplesamlphp {
public $adminAutoloadPath;
public $nonAdminAutoloadPath;
public function init() {
if (Yii::app()->user->isAdmin()) {
$this->autoloadPath = $this->adminAutoloadPath;
} else {
$this->autoloadPath = $this->nonAdminAutoloadPath;
}
parent::init();
}
}
And use new component in config:
$config['components']['simplesamlphp'] = array(
'class' => 'MySimplesamlphp',
'adminAutoloadPath' => SAML_DIR.'/test2-admin/lib/_autoload.php',
'nonAdminAutoloadPath' => SAML_DIR.'/test2/lib/_autoload.php',
'authSource' => 'default-sp',
);
I figured it out overriding yii components is fairly easy even if you dont initialize it in the config.
$component = array(
'class' => 'application.components.yii-simplesamlphp.components.Simplesamlphp',
'autoloadPath' => SAML_DIR.'/'.$tenant_path.'/lib/_autoload.php',
'authSource' => 'default-sp',
); //where $tenant_path is the directory of the component i need based on the tenant
Yii::app()->setComponent('simplesamlphp',$component);
then use the component in your controller like so
Yii::app()->simplesamlphp;
Note that you will only have access to the component within your controller method so all i did was move the that code to its own class and call it when i needed to create a new instance of the component
NOTE: This is an old question and the answers here no longer works (since beta5). See this question on how to do it with ZF2 stable version.
I have looked at this example from the manual. Note that this is version 2 of the Zend Framework.
I create this helper:
<?php
namespace Mats\Helper;
use Zend\View\Helper\AbstractHelper;
class SpecialPurpose extends AbstractHelper
{
protected $count = 0;
public function __invoke()
{
$this->count++;
$output = sprintf("I have seen 'The Jerk' %d time(s).", $this->count);
return htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
}
}
?>
and then try to register it like this:
return array(
'di' => array('instance' => array(
'Zend\View\HelperLoader' => array('parameters' => array(
'map' => array(
'specialpurpose' => 'Mats\Helper\SpecialPurpose',
),
)),
)),
);
but when doing this in a view, for instance add.phtml
<?php echo $this->specialPurpose(); ?>
It will crash, saying it cannot find the helper.
However, in the same add.phtml file I can do
<?php $helper = new Mats\Helper\SpecialPurpose(); ?>
and have access to it, so I guess the namespace should be right?
Currently I register it in Module.php, but I have also tried elsewhere.
My goal is to have access to the view helper in all views in my module, without having to create an instance of it in each phtml file, and not having to add it every time in the controller.
How can this be achieved? Thanks.
ZF2 moved to service managers with programmatic factories, while di used as fallback factory.
For view there is view manager now and as service resolution stops as soon as it found factory, helpers configured via di no longer work.
Example how you should register helpers now you can find in ZfcUser module config
Add custom helper is very simple, just add one line to your module config file like this:
return array(
'view_manager' => array(
'helper_map' => array(
'specialPurpose' => 'Mats\Helper\SpecialPurpose',
),
),
);
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