Yii2 Declaration beforeAction should be compatible with Controller - php

Whenever I include the beforeAction function event with something simple I get an error saying it has to be compatible. This does not happen on my live server only on my local one. The only difference I can think of is my local server is running PHP7 and my live one is running PHP5.6. Is that what is causing the issue? The only thing I have found that will fix it is removing it completely.
This is what my beforeAction looks like
public function beforeAction()
{
if(Yii::$app->user->isGuest){
return $this->redirect(['site/login']);
} else {
if(strtotime(UserInfo::findOne(Yii::$app->user->Id)->active_until) < strtotime(date("Y-m-d H:i:s"))){
Yii::$app->session->setFlash('warning', 'You need an active subscription to access events.');
echo("<script>location.href = '".Url::toRoute('site/subscription')."';</script>");
exit;
//return $this->redirect(['site/subscription']);
}else {
return true;
}
}
}
I also tried this simple one to check and got the same issue
public function beforeAction()
{
if (!parent::beforeAction($action)) {
return false;
}
return true;
}
Here is the error message I get
Declaration of frontend\controllers\EventController::beforeAction() should be compatible with yii\web\Controller::beforeAction($action)

See this error message :
should be compatible with yii\web\Controller::beforeAction($action)
Your override function must be compatible with parent. So, valid code :
public function beforeAction($action)
{
....
}

Just explaining
If you get this problem, it means that you have a function in your parent class and a function in your child class that have the same name but not the same input variable declaration.
Parent Class
beforeAction($action) {
....
}
Child Class
beforeAction() {
....
}
As you can see, the child class is missing the $action variable. This creates a warning in PHP E_Strict. All you have to do is make sure that the child class function is exactly the same as the parent.

Related

beforeAction() should be compatible with yii\web\Controller::beforeAction($action)

I am working on a project and it is working fine on live server and on my local. but when i upload it on another server it gives me error of
beforeAction() should be compatible with yii\web\Controller::beforeAction($action).
I set up all the needed things on the server.
But When i login to my project on new server it gives me blank page with no error. And when i access inner pages(pages after login) it gives me error that
beforeAction() should be compatible with yii\web\Controller::beforeAction($action).
I cant understand actual problem and i go through all the related answer given by this error but i can't find the exact answer.
This is my beforeAction Function
public function beforeAction() {
if (\Yii::$app->getUser()->isGuest) {
$this->redirect(Yii::$app->urlManager->createAbsoluteUrl('auth/login'));
return false;
} else {
return true;
}
}
When you override methods you need to use the same signature. Add the $action argument. Also it's good habit to check parent's results first in before* kind of methods:
public function beforeAction($action)
{
if (parent::beforeAction($action)) {
if (\Yii::$app->getUser()->isGuest) {
$this->redirect(Yii::$app->urlManager->createAbsoluteUrl('auth/login'));
return false;
}
return true;
}
return false;
}
Last thing here - it's better to use access filter for this.
Try this :
public function beforeAction($action)
{
....
}
pass $action in beforeAction method
You missed parameter which is required as per its definition in \yii\base\Controller.
Try this.
public function beforeAction($action)
{
parent::beforeAction($action);
if (\Yii::$app->getUser()->isGuest)
{
$this->redirect(Yii::$app->urlManager->createAbsoluteUrl('auth/login'));
return false;
} else
{
return true;
}
}

Prestashop override Blocktopmenu function

I'm trying to override the generateCategoriesMenu function from blocktopmenu.php
class BlocktopmenuOverride extends Blocktopmenu
{
public function generateCategoriesMenu($categories, $is_children = 0)
{
die( var_dump ('hello I am an override') );
}
}
I've set up this in the folder override/modules cleared the cache file class_index.php
when I load my index page I would expect a blank page with a string 'hello I am an override'
I'm on 1.6.0.12
edit
I know I can do it the old way 'cloning' the module but there's a new undocumented hidden way in prestashop if you look in module.php this function clearly says that we can override a module.
public static function getInstanceByName($module_name)
{
if (!Validate::isModuleName($module_name))
{
if (_PS_MODE_DEV_)
die(Tools::displayError(Tools::safeOutput($module_name).' is not a valid module name.'));
return false;
}
if (!isset(self::$_INSTANCE[$module_name]))
{
if (Tools::file_exists_no_cache(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php'))
{
include_once(_PS_MODULE_DIR_.$module_name.'/'.$module_name.'.php');
if (Tools::file_exists_no_cache(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/'.$module_name.'.php'))
{
include_once(_PS_OVERRIDE_DIR_.'modules/'.$module_name.'/'.$module_name.'.php');
$override = $module_name.'Override';
if (class_exists($override, false))
return self::$_INSTANCE[$module_name] = new $override;
}
if (class_exists($module_name, false))
return self::$_INSTANCE[$module_name] = new $module_name;
}
return false;
}
return self::$_INSTANCE[$module_name];
}
I already did successfully overrides on other modules with no problem,
this override works if I comment the parent function but that makes pointless the override.
why with blocktopmenu I can't override the desired function?
I hope I made it clear now.
I took a look at it again,
it may be because parent functions is private :
private function generateCategoriesMenu($categories, $is_children = 0)
As you know, private functions are only visible in that class in which it was declared. In this case the whole situation works a little bit like declaring it final.
Your only hope is to submit a patch to GitHub making these methods protected - this should become common practice once the module overrides take off.

Yii: Unexpected invocation of CHttpSession::close when running a method in custom class

strange problem here. Using Yii framework I have the following class
class HtmlTableUi
{
public function __construct(CWebModule &$module,$data,$actions)
{
//...code goes here...
}
protected function renderTable()
{
//... code goes here ...
}
}
I can call HtmlTableUi::renderTable() from instance of HtmlTableUi in SchedulerModule class which is the main class in a separate application module. My SchedulerModule.php file:
<?php
Yii::import('scheduler.components.HtmlTableUi');
class SchedulerModule extends CWebModule
{
public function init()
{
parent::init();
}
public function beforeControllerAction($controller, $action)
{
return true;
}
public function printUI($data,$actions,$submitPath)
{
$ui = new HtmlTableUi($this,$data,$actions,$submitPath);
$ui->renderTable();
}
}
Here comes the tricky part - when I call SchudulerModule::printUI from view (index.php) this way
<?php
$this->module->printUI($casino,$actions,null);
?>
the code flow goes through SchudulerModule::printUI until reaching the point where renderTable is invoked ($ui->renderTable();) and instead stepping at the first line inside the body of that method it, contrary to any logic and rules, surprisingly jumps to CHttpSession::close !!?
Notice the Call Stack before invoking renderTable
protected/modules/scheduler/SchedulerModule.php.SchedulerModule->printUI:153
protected/modules/scheduler/views/default/index.php.require:21
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CBaseController.php.CBaseController->renderInternal:127
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CBaseController.php.CBaseController->renderFile:96
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CController.php.CController->renderPartial:870
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CController.php.CController->render:783
protected/modules/scheduler/controllers/DefaultController.php.DefaultController->actionIndex:57
and after:
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CHttpSession.php.CHttpSession->close:134
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CHttpSession.php.SchedulerModule->printUI:0
protected/modules/scheduler/views/default/index.php.require:21
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CBaseController.php.CBaseController->renderInternal:127
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CBaseController.php.CBaseController->renderFile:96
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CController.php.CController->renderPartial:870
/home/default/workspace/src/vlt/web/yii-1.1.12.b600af/framework/web/CController.php.CController->render:783
protected/modules/scheduler/controllers/DefaultController.php.DefaultController->actionIndex:57
Has anyone had similar issue? Can anyone explain that behavior?
I found the solution!!! The access modifier of renderTable is supposed to be public, not protected. This wrong somehow in Yii framework results in unexpected runtime behavior instead of compilation error.

Kohana 3.x call_user_func() error

i keep on having this error message on Kohana 3
ErrorException [ Warning ]: call_user_func() expects parameter 1 to be a valid callback, function 'pages_save' not found or invalid function name
inside my controller i have the following codes:
public function action_pages(){
return call_user_func('pages_'.$this->request->param('id'));
}
function pages_save(){
$this->auto_render = false;
}
if i would access admin/pages/save i should be redirected to pages_save() function right? but somehow i cant? Kohana keeps on throwing me the following exception stated above. how should i go with this. optimizing is one thing in my mind, if i do switch-case / if-else block it would take me forever if there are too many that i need to do...
First of all you should trust the error message. Which means you did an error. Clean up your code a little:
public function action_pages()
{
$method = sprintf('pages_%s', $this->request->param('id'));
return call_user_func($method);
}
public function pages_save()
{
$this->auto_render = false;
}
The changes here are only little: Added the missing visibility specifier to pages_save and put the methodname into a variable called $method.
Now it's getting more visible, that you used a public function name here which is not defined, instead of the class method you'd like to invoke on $this. So let's fix that:
public function action_pages()
{
$method = sprintf('pages_%s', $this->request->param('id'));
return $this->$method();
}
This should solve your issue.
It's not Kohana, it's PHP that is throwing the error. To use call_user_func() from within a class, you need to use the following syntax:
call_user_func(array($this, 'pages_'.$this->request->param('id')));

What is causing this strange PHP fatal error?

I have a generic Logger class that looks like this:
class Logger {
...
public function add($userId, $siteId, $logTypeId, $message) {
$Log = LogMapper::create();
$Log->setUserId($userId);
$Log->setSiteId($siteId);
$Log->setLogTypeId($logTypeId);
$Log->setMessage($message);
$Log->save();
...
}
...
}
And the Log class:
class Log {
public function setUserId($userId) {
if ($this->userId !== $userId) {
$this->userId = $userId;
}
return $this;
}
public function getUserId() {
return $this->userId;
}
public function setSiteId($siteId) {
if ($this->siteId !== $siteId) {
$this->siteId = $siteId;
}
return $this;
}
public function getSiteId() {
return $this->siteId;
}
...
}
As well as the LogMapper class:
class LogMapper extends DataMapper {
...
public static function create($row = false) {
return new Log($row);
}
public static function getById($id) {
...
}
}
As you can see, I have two other classes, LogMapper and Log, which Logger uses to write records to a database.
I also have a mechanism that emails me when a fatal error occurs. I received the following in about a dozen emails:
Call to undefined method Log::setUserId()
My application uses autoloading, and I first thought that may be the problem, but clearly the Logger class is being loaded, and so autoloading has not broken. The path for the Log class is correct in the autoloader...and clearly the Log class has been loaded--otherwise a "Class 'Log' not found" error would have been thrown.
Any ideas what may be causing this error? I do use eAccelerator on the release.
Long shot, but do you have PEAR's Log class installed? This is something I ran across a while back. I tried to make a 'Log' class but it was colliding with PEAR's.
Since you didn't post your Log class here, the best guess anyone can probably make is that you forgot to write a setUserId() method in that class.
I can also take a guess that eAccelerator might have your class cached. It's possible you need to restart your web server for changes to take effect, or utilize some other method of clearing the cache.
Maybe reflection can tell you a bit more about the actual class Log used by your code.
public function add($userId, $siteId, $logTypeId, $message) {
$Log = LogMapper::create();
if ( !method_exists($Log, 'setUserId') ) {
$ro = new ReflectionObject($Log);
echo 'class defined in ', $ro->getFilename(), ' # ', $ro->getStartLine(), "\n";
foreach($ro->getMethods() as $rm) {
echo ' method ', $rm->name, " \n";
}
die('----');
}
$Log->setUserId($userId);
$Log->setSiteId($siteId);
$Log->setLogTypeId($logTypeId);
$Log->setMessage($message);
$Log->save();
}
It's hard to say, we can't see the Log class nor the LogMapper.
You sure the Log class has setUserId() method?
Also why do you name the variable with uppercase? $Log?
Just a quick guess:
Use:
public function __set($name,$value)
{
$this->{preg_replace('^set','',$name)} = $value;
}
This would be a real mapping, I guess.
//Call me stupid, but I still can not find the setUserId() method?
//Did you leave it out, while copy&pasting the code? OUTDATED
try this
if ($this->userId !== $userIdd)
make the var names diffrent, i had such a weird problem one day.

Categories