Yii2 extend console MessageController - php

I have some functionality, that I want to add to yii\console\controllers\MessageController::actionExtract().
So normally what I have done - extended yii controller with my own controller and placed it to app\commands directory.
<?php
namespace app\commands;
class MessageController extends \yii\console\controllers\MessageController{ /* .. */ }
For test purposes I added method named actionTest.
When I do > yii command, all I get is
Now I copy-pasted exactly same controller and just renamed it to MsgController. Previous controller left intact.
So now > yii gives me
yii message/test - 'Unknown command message/test'
yii msg/test - 'OK'
My app\config\console.php has 'controllerNamespace' => 'app\commands'
How should I properly extend MessageController and continue use standard yii command (means not changing controller name to have new command)?

Extend the controller like you did and in console configuration add:
'controllerMap' => [
'message' => 'app\commands\MessageController',
],

Related

Use a Zend function in every controllers

I need to be able to use a function (redirect with some parameters) from different controlers of my application.
I need to use $this->_helper->redirector($param1, $param2), and declare it just one time somewhere. Then I'll put this function in others controllers. If one day I modify the function, I don't need to modify it in each controller.
What I'm looking for is an equivalent of Symfony's services I guess.
Thanks for help :) .
What you 're asking for is called controller plugin in Laminas or Zend. You can code your own controller plugin, that you can use in every controller you want.
<?php
declare(strict_types=1);
namespace Application\Controller\Plugin;
use Laminas\Mvc\Controller\Plugin\AbstractPlugin;
class YourPlugin extends AbstractPlugin
{
public function __invoke($param1, $param2)
{
// your logic here
}
}
You have nothing more to do as to mention this plugin in your module.config.php file.
'controller_plugins' => [
'aliases' => [
'doSomething' => \Application\Controler\Plugin\YourPlugin::class,
],
'factories' => [
\Application\Controller\Plugin\YourPlugin::class => \Laminas\ServiceManager\Factory\InvokableFactory::class,
]
]
If you want to use some dependencies in your controller plugin, you can write your own factory for your plugin and add that dependencies via injection.
As your new plugin is mentioned in the application config, you can call your plugin in every controller you want.
<?php
declare(strict_types=1);
namespace Application\Controller;
class YourController extends AbstractActionController
{
public function indexAction()
{
$this->doSomething('bla', 'blubb');
}
}
Please do not use traits as a solution for your issue. Laminas / Zends already ships a redirect controller plugin. Perhaps a ready to use solution is already there or you can extend the redirect controller plugin ...

How do you access a template from inside a Symfony Bundle that is located in "<BundleLocation>/Ressources/views"?

I'm creating an application for a Symfony web project that I have made previously as a portable bundle. I've created a "media.html.twig" template and want it to be called by the render() helperfunction.
I've activated the bundle in /config/bundles.php with
App\OM\MediaManagerBundle\OMMediaManagerBundle::class => ['all' => true],
and followed the instructions on this site https://symfony.com/doc/current/bundles.html for setting up the Symfony-Bundle folder structure and the required files.
I've prefixed the path with "#MediaManager" as told by this site https://symfony.com/doc/4.1/bundles/best_practices.html#resources.
This is my Controller class:
<?php
namespace App\OM\MediaManagerBundle\Controller;
use App\OM\MediaManagerBundle\Form\ImageType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class MediaManagerController extends AbstractController
{
const TEMPLATE = "#MediaManager/MediaManager/media.html.twig";
/**
* #Route("/media/", name="om_mediamanager_media")
* */
public function index(Request $request)
{
$form = $this->createForm(ImageType::class);
return $this->render(self::TEMPLATE,
[
'form' => $form->createView(),
]);
}
}
This is how my folder structure looks like inside src:
https://i.imgur.com/9UomIEK.png
I hoped my form would be displayed but instead I got an error message saying:
There are no registered paths for namespace "MediaManager".
I know that it starts looking from the /templates folder so I tried setting the path to "../src/OM/MediaManagerBundle/Resources/views/MediaManager/media.html.twig" but got
Looks like you try to load a template outside configured directories (../src/OM/MediaManagerBundle/Resources/views/MediaManager/media.html.twig).
The code does work when I move the "media.html.twig" template inside the /templates folder but I expect it to ruin the portability of the bundle and therefor don't want to do that.
How do I access this template from inside my OMMediaManagerController class?
Am I even using Symfony Bundles the right way?
Is there any more documentation about Bundles in general? I found the ones provided by the official site to be very lacking.

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!

Yii Framework action before every controller

is there any "main" controller which fires before every other controller from folder "controllers"? I have a project where every user has his different site language, so I want to check the setting first and then set the language using:
Yii::$app->language='en-EN';
Right now I do this in every controller I have, but I guess it should be an easier option.
I had same problem while ago, and found a solution by adding another component.
How to load class at every page load in advanced app
Add class in config to components part and load it at start by adding to bootstrap.
config.php
$config = [
// ..
'components' => [
'InitRoutines' => [
'class' => 'app\commands\InitRoutines', // my custom class
],
],
];
$config['bootstrap'][] = 'InitRoutines';
Then make your class to extend Component with init() method
InitRoutines.php
namespace app\commands;
use Yii;
use yii\base\Component;
use app\commands\AppHelper;
use app\commands\Access;
class InitRoutines extends Component
{
// this method runs at start at every page load
public function init()
{
parent::init();
Access::checkForMaintenance(); // my custom method
Yii::$app->language = AppHelper::getUserLanguageCode(); // my custom method
}
}
You can attach to the application event beforeAction or beforeRequest and do your stuff here. It seems easier to me e.g.:
$config = [
// ..
'on beforeRequest' => function($event) {
Yii::$app->language='en-EN';
}
];

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'

Categories