Calling a Component function from helper - cakephp-3.0

Some times ago I wrote a component that I find very convenient to use instead of other kind of authorization tools. I have converted it to CakePHP 3 and it still suits perfectly to my needs, but now I need to call one of its functions from a helper, and I can't figure out how to do that. The component name is PermissionsComponent.
Here is a draft of my helper:
namespace App\View\Helper;
use Cake\View\Helper;
use App\Controllers\Component\PermissionsComponent;
class PermissionsHelper extends Helper {
function check($action, $redirect = false) {
// how can I call my component's action check($action, $redirect)?
}
}
How can I call that component's action from a helper?

You can't. It sounds more like you should use another object that you can use in both the component and the helper.
// In PermissionsComponent
$permissions = new Permissions();
...
$this->_controller->set('_permissions', $permissions);
And then you can use it in your helper:
// In PermissionsHelper
$permissions = $this->_View->get('_permissions');

Related

How do I override a widget method in Yii2?

I need to override the renderPageButton() method in the Yii2 LinkPager widget. The method documentation specifically says "You may override this method to customize the generation of page buttons" but I can't figure out how to do that. Thanks.
Overriding LinkPager can be done this way:
Create a new file ./widgets/MyLinkPager.php:
<?php
namespace app\widgets;
use yii\widgets\LinkPager;
class MyLinkPager extends LinkPager
{
protected function renderPageButtons()
{
// do whatever you want, it may help to
// copy code from parent::renderPageButtons()
// or even call
return parent::renderPageButtons();
}
}
And then use it this way in your view (see here: https://www.yiiframework.com/doc/guide/2.0/en/output-pagination):
use yii\widgets\LinkPager;
echo LinkPager::widget([
'pagination' => $pagination,
]);
The class you want to override is documented here.
You can override it in the following way:
Create a new directory in your yii2 app root folder, like widgets
Create a new php file (like MyLinkPager.php) and a new class in it (MyLinkPager) which extens yii\widgets\LinkPager
You can use "app\widgets" namespace (i.e. if you are working with the basic yii2 app)
In your class, implement only the function you want to override from the original class
Use your new class wherever you want instead of the original one

How to make reference to method in PHPDoc

I use a Lumen Laravel-based framework and it allows me to create custom method like this:
/**there should be a proper doc*/
\Laravel\Lumen\Http\ResponseFactory::macro('customMethod', function ()
{
return $this;
});
It creates method customMethod called as method which belongs response() function.
/**or probably there should be a proper doc*/
return response()->customMethod()
I want to make a hint to my IDE (PhpStorm 2020.1.2) which allows it to see reference from where customMethod is called to where it is declared, and follow it with click on function name in IDE.

ASP .Net Core Razor: Can't return ViewComponent from my PageModel

I am trying to use Ajax to call a handler in my Razor page that returns the result of a ViewComponent, however when I try the code below, it says:
Non-invocable member "ViewComponent" cannot be used like a method.
public IActionResult OnGetPriceist()
{
return ViewComponent("PriceList", new { id= 5 });
}
When using MVC, the Controller base class includes a ViewComponent method, which is just a helper method that creates a ViewComponentResult for you. This method does not yet exist in the Razor Pages world, where instead you use PageModel as the base class.
One option to work around this is to create an extension method on the PageModel class, that would look something like this:
public static class PageModelExtensions
{
public static ViewComponentResult ViewComponent(this PageModel pageModel, string componentName, object arguments)
{
return new ViewComponentResult
{
ViewComponentName = componentName,
Arguments = arguments,
ViewData = pageModel.ViewData,
TempData = pageModel.TempData
};
}
}
Apart from it being an extension method, the code above is just ripped out of Controller. In order to use it, you can call it from your existing OnGetPriceList (typo fixed) method, like this:
public IActionResult OnGetPriceList()
{
return this.ViewComponent("PriceList", new { id = 5 });
}
The key to making it work here is to use this, which will resolve it to the extension method, rather than trying to invoke the constructor as a method.
If you're only going to use this once, you could forego the extension method and just embed the code itself inside of your handler. That's entirely up to you - some people might prefer the extension method for the whole separation-of-concerns argument.

accessing an array in a component from the layout in yii2

I need to check the records in the notifications table at every page load of every controller.
So I wrote it in a component and the component is executed in the bootstraping process.
I need the notifications to be available in the layout so that i can show them in the notification menu.
below is what I have tried so far:
component:
namespace admin\components;
use Yii;
use yii\base\Component;
use admin\models\Notification;
class NotificationManager extends \yii\base\Component{
public function init() {
$notifications = Notification::find()->orderBy('id DESC')->asArray()->all();
//echo "<pre>"; print_r($notifications);exit;
if(count($notifications)>0){
foreach ($notifications as $notif) {
if($notif['type'] == 'courier')
$courier_notifications[] = $notif;
elseif($notif['type'] == 'order')
$order_notifications[] = $notif;
}
Yii::$app->view->params['courier_notifications'] = $courier_notifications;
Yii::$app->view->params['order_notifications'] = $order_notifications;
}
}
}
Layout:
$courier_notifications = $this->params['courier_notifications'];
I am not sure which part am I going wrong: in component or in the layout?
I appreciate your help.
Im not sure why your component execution during bootstrap fails to add the value to params.But believe it to be an overkill.
You can rather move the logic to component method and access in layout whenever necessary
Component.
namespace admin\components;
use Yii;
use yii\base\Component;
use admin\models\Notification;
class NotificationManager extends Component{
public function notifications($type = 'courier') {
$notifications = Notification::find()
->where(['type' => $type])
->orderBy('id DESC')
->asArray()->all();
return $notifications;
}
}
Add the component class under Components section in your config file
'notificationManager ' => [
'class' => 'admin\components\NotificationManager'
]
Layout
$courier_notifications = yii::$app->notificationManager->notifications('courier');
If you really want to go bootstrap mode, you need to implement yii\base\BootstrapInterface and put your logic in the bootstrap($app) method in order for the param to be available site-wide by setting the value of Yii::$app->params['notifications'] to the result of your logic.
Another common approach is to add a new method public function displayNotifications or whatever you want to name it, to your component, move all the logic in it and then in your layout/view etc., call it with Yii::$app->notificationManager->displayNotifications(). You can also pass additional parameters to it and enhance your logic.
notificationManager has to be replaced with the name you registered your custom component in the Yii app config (web.php for basic app, main.php for advanced app).
LE - If you only registered your component for bootstrap, you should also register it in the components array.
'notificationManager' => [
'class' => '\admin\components\NotificationManager'
]

The _redirect() function in zend framework

I made a file in library/My/Utils/Utils.php. The content of the file is :
class My_Utils_Utils{
public function test(){
$this->_redirect('login');
}
}
This class is called from a layout; the problem is with the _redirect(); I get this error : The page isn't redirecting properly. My question is how call the _redirect() function from a class made by you in ZEND framework 1 .
Thanks in advance.
Use redirect() instead of _redirect(). Usage is:
$this->redirect(<action>, <controller>, <module>, <param>);
In your case $this->redirect('login'); should do the trick.
You can use the redirector action-helper, which you can get statically from the HelperBroker using:
// get the helper
$redirectHelper = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
// call methods on the helper
$redirect->gotoUrl('/some/url');
It should be noted, however, that the layout is considered part of the view layer. Typically, any checks that result in a redirect should probably take place earlier in the request dispatch-cycle, typically in a controller or in a front-controller plugin.
The _redirect function is provided by the class Zend_Controller_Action. You can fix this in two ways :
Extend Zend_Controller_Action and use _redirect
class My_Utils_Utils extends Zend_Controller_Action {
public function test(){
$this->_redirect('login');
}
}
in layout:
$request = Zend_Controller_Front::getInstance()->getRequest();
$response = Zend_Controller_Front::getInstance()->getResponse()
$util = new My_Utils_Utils($request, $response); // The constructor for Zend_Controller_Action required request and response params.
$util->test();
Use gotoUrl() function Zend_Controller_Action_Helper_Redirector::gotoUrl()
$redirector = new Zend_Controller_Action_Helper_Redirector();
$redirector->gotoUrl('login');
//in layout :
$util = new My_Utils_Utils();
$util->test();