Correct way to access Yii2 components in your modules? - php

I have created and configured a module fooModule. I need to create a component inside the module.
This is my configuration for my module in main.php
'modules'=>array(
'fooModule'=>array(
'class' => 'app\modules\fooModule\Module',
'components'=>array(
'testComponent'=>array(
'class'=>'app\modules\fooModule\components\testComponent',
),
),
),
),
In the folder module fooModule i have created a folder components with a file testComponent.php
TestComponet.php has a class test which extend \yii\base\Component. See below
namespace app\modules\fooModule\component;
class test extends \yii\base\Component {
public function __construct() {
private $bar;
}
public function exampleFunction() {
echo 'am alive, come and look for me please!!';
}
}
How do i access test class in fooModule Controller ?

Use Yii::$app->getModule('fooModule')->testComponent->exampleFunction(); for access module component.

The most elegant way to access module component from module controller without hardcoding module's ID is as follows:
$this->module->testComponent->exampleFunction();

This looks very elegant
Module::getInstance()->testComponent

Related

Yii2: run console command from controller in vendor directory

I am doing some refactoring of our large work app. This involves separating out some tools I've build, like a schema/seed migration tool for the command line, in to their own repositories to be used by multiple applications.
If it's in console/controllers, it gets picked up. If I move them to their own repository and require it via Composer, how do I get Yii to know when I say php yii db/up, i mean go to the new\vendor\namespace\DbController#actionup ?
If you create an extension (and load it through composer of course), you can locate Module.php inside, which will hold path to console controllers (that you can call with your terminal).
I will write my example for common\modules\commander namespace, for vendor extension your namespace will differ, but it work for all of them the same way.
So I have the following file structure for my extension
<app>
common
modules
commander
controllers
• TestController.php
• Module.php
My Module class looks as follow:
namespace common\modules\commander;
use yii\base\Module as BaseModule;
class Module extends BaseModule
{
public $controllerNamespace = 'common\modules\commander\controllers';
public function init()
{
parent::init();
}
}
And TestController.php is inherited from yii\console\Controller:
namespace common\modules\commander\controllers;
use yii\console\Controller;
class TestController extends Controller
{
public function actionIndex()
{
echo 123;
}
}
And the main part to make everything work is to register out Module.php in console/config/main.php settings
'modules' => [
'commander' => [
'class' => \common\modules\commander\Module::className(),
],
...
],
Here it is, now you can use your command like:
yii commander/test/index
And it'll print you 123, showing that everything works and Console Controllers are located in different folders!

How to add custom controller to extension in vender folder in yii2?

I have an extension yii2-admin for RBAC, and I would like to add to this extension another controllers, views, models etc. Because in this module I would like to keep all operations who admin like CRUD for User table and for another.
What is the right way to add it? Because to add custom file in folder vendor it's bad way.
If you are using a module for manage the authorization control you can do this way
assuming you module is name auth
in you config/main.php you assign the module for auth
'modules' => [
.....
'auth'=> [ // your module for authorization (rbac)
'class' => 'vendor\your_vendor_name\auth\Module',
],
then in vendor\your_vendor_name\auth\Module.php
you should have this code for set the controllerNamespace for all the controller related to auth module
namespace vendor\your_vendor_name\auth;
use \yii\base\Module as BaseModule;
/**
* This is the main module class for the auth .
*
*
*
*/
class Module extends BaseModule
{
public $controllerNamespace = 'vendor\your_vendor_name\auth\controllers';
const VERSION = '1.0.0-dev';
public function init()
{
parent::init();
// custom initialization code goes here
}
}
at this point you can add all the controller you need in
`vendor\your_vendor_name\auth\controllers\`
and model in
`vendor\your_vendor_name\auth\models\`
and views
in
`vendor\your_vendor_name\auth\views\`
eg: for controller in vendor\your_vendor_name\auth\controllers\ i have
AuthAssignmentController.php
AuthItemChildController.php
AuthItemController.php
AuthRuleController.php
DefaultController.php
each of this manage the CRUD for the related model

zf2 view helper across module

I created a helper in the application module, and it works perfectly. When I try to load it from another modules, such as user, it tells me that it can not find the class.
Class 'Application \ View \ Helper \ Footertable' not found
I tried to put this code in module.config.php well as the application module even in the same file of the user module.
'view_helpers' => array (
'invokables' => array (
'footertable' => 'Application\View\Helper\Footertable'
)
),
I think it's a problem autoloading class but I can not find information on how to load this helper when you are in another module
I invoke helper in view file using
$this->footertable()
work perfectly in application module but not in user module
any idea?
Hello,
but my code is correct
<?php
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
class Footertable extends AbstractHelper{
protected $inizioFine;
protected $numero;
public function __invoke($inizioFine,$numero){
$this->inizioFine = $inizioFine;
$this->numero = $numero;
echo sprintf('Mostra %d a %d di %d record',$this->inizioFine['start'],$this->inizioFine['end'],$this->numero);
}
}
the space in config is an copy & past errors.
I still have the same problem: can't load helper from another module
update full error
Fatal error: Class 'Application\View\Helper\Footertable' not found in D:\www\httpdocs\test\vendor\zendframework\zendframework\library\Zend\ServiceManager\AbstractPluginManager.php on line 170
path is
D:\www\httpdocs\test\module\Application\src\View\Helper\Footertable.php
The path you posted doesn't look right. All the files in src for your Application module should be inside a folder called Application, since that's your top level namespace. So the path should be:
D:\www\httpdocs\test\module\Application\src\Application\View\Helper\Footertable.php
That would explain why the helper can't be autoloaded, but I don't understand how it works in the application module if this is the case.
Your configuration seems good. Probably the problem is in your helper class signature.
Since PhpRenderer composes a HelperPluginManager instance to manage helpers, your helper should implement the HelperInterface (1) to be registered correctly. Also you should write an __invoke() method within your helper to invoke it by method call. (2)
So, in your Footertable class, simply extend the AbstractHelper and make sure you have an _invoke() method. This is recommended way to write custom view helpers in documentation.
For example:
<?php
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
class Footertable extends AbstractHelper
{
public function __invoke()
{
return 'bar';
}
}
And use it in your views like this:
echo $this->footertable();
It should work.
Note: You also have to register all helpers (and other classes) in your module configuration's invokables section without spaces between the backslashes:
Wrong:
'footertable' => 'Application \ View \ Helper \ Footertable'
Correct:
'footertable' => 'Application\View\Helper\Footertable'

Instantiation of component class Yii

I'm trying to understand a sequence of instatiation component class. As I understood an application component class has a lazy initialization (I've logged starting invokation of init() method). Let I've created a simple test component called document:
class Document extends CApplicationComponent{
private $_width='150';
public function init(){
echo "This is document component init method.";
}
public function getWidth(){
return $this->_width;
}
}
I've add a corresponding component's array to the config.php:
'components'=>array(
'document' => array( 'class' => 'document')
)
And it works, but I dont understand the sense. Actually, let we renamed component's file from Document.php to DDocument.php. Exception is raised after this renaming. Why? We doesn't renaming component's class name which specified in config.php. And what does keys of components array mean? Is it just property of Yii::app() object which are instances of CApplicationComponent?

zend framework 2 getServiceLocator Empty

I've been trying to figure it out by myself reading online and applying tons of answers form here, but to no avail unfortunately.
I have two Modules on my zf2 application, one called Services and one called Agent.
Now, in my Services module everything seems to work fine, I can get my serviceLocator, hence my configuration, and work with it. In my Agent Module's controller however, I don't seem to be able to do the same.
This is part of my AgentController:
use Zend\Mvc\Controller\AbstractActionController;
class AgentController extends AbstractActionController
{
protected $serviceLocator;
public function ValidateAction()
{
$this->serviceLocator = $this->getServiceLocator()->get('config');
//... Using the config
}
}
In my module.cofig.php I have the following:
'controllers' => array(
'invokables' => array(
'Agent\Controller\Agent' => 'Agent\Controller\AgentController',
),
),
I have tried many solutions: changing and adding methods to the Module.php, changing the module.config etc.. Where am I wrong?
Thanks,
Andrea
The class variable $this->serviceLocator is used by the controller class to hold the service locator instance. In your example you assigning the config array to this variable (thus replacing the service locator instance with an array). Subsequent calls to $this->getServiceLocator() will then return the config array instead of the service locator object, which is the likely cause of the error you're getting.
I'd suggest either using a local variable instead:
public function ValidateAction()
{
$config = $this->getServiceLocator()->get('config');
//... Using the config
}
or assigning to a class variable with a different name:
public function ValidateAction()
{
$this->config = $this->getServiceLocator()->get('config');
//... Using the config
}

Categories