Jump to content

updating from PHP 7.4 to 8.1: call to a member function () on null


wkilc
 Share

Recommended Posts

Hello.

Despite being at this for a while, I am in reality a grade-school teacher and a PHP novice.

I have a third-party PHP form mail script that I purchased years back. The company is in the Ukraine and appears to no longer be in business. (God Bless.)

Anyway, the script always appeared to work perfectly with PHP 7.4.  I set my site to 8.1 to test it out... saw a few minor warnings that even I could pretty easily remedy. However, there's one that has me stumped.

Fatal error: Uncaught Error: Call to a member function setContent() on null in /home/www/www/fp/classes/outputer.class.php:53 Stack trace: #0 /home/www/www/fp/classes/outputer.class.php(92): Outputer->output('<!DOCTYPE HTML ...') #1 /home/www/fp/ptd.php(93): Outputer->showDefaultPage() #2 {main} thrown in /home/www/www/fp/classes/outputer.class.php on line 53

I believe that this is the part of the form that processes form data and then outputs it to a HTML page template to show the results of the submission.

Line 53:

$this->response->setContent($content);

Line 93:

$this->output($content);

 

The code surrounding line 53:

function output($content, $isError = false){
    	    if ($isError){
    	    	$request = $this->getRequestData();
    	    	$this->response->setOuputOffset($request['fpp_output']);
    	    }    
            $this->response->setContent($content);
            $this->response->printOut();
		}
    	function redirect($url){
            if (function_exists('ob_start')){
            	ob_start();
            	ob_clean();
            }
            
            header('Location: ' . $url);
            exit();
    	}
    	
		/**
		 * Shows default page

I've been researching this and I realize this is likely a result of a value of "null" coming up... but everything I've tried to remedy doesn't help.

Again, rolling site back to 7.4 and everything works as it should, no errors or warnings.

Many thanks for any guidance you can provide.

 

Edited by wkilc
Link to comment
Share on other sites

Thank you. My problem is I have don't know how to remedy that.

I tried:

$this->response=new response();

That removes in fact removes the error, but then the form data won't get outputted to the HTML template.

Link to comment
Share on other sites

i suspect the code has a method with the same name as the class, where the initialization is/was occurring. such a method no longer gets called automatically when an instance of the class is created. you must specifically supply a __construct() method.

  • Great Answer 1
Link to comment
Share on other sites

The new version of php requires a class definition to use a different method of creating/initializing/instantiating a class.  The old way was to use the class name in a call to create a 'new' class which executed a method by that name.  Now you must use a method named  '__construct' to create a new one.  You will have to look at your class definition for the method using the class's name and rename that as __construct. 

Link to comment
Share on other sites

Thank you. Like this?

__construct() {

$this->response->setContent($content));

}

 

Here's the rest of the outputter file:

    	function Outputer(){
    		global $response;
    		
    	    $this->response = $response;
    	    $this->setType(ACTION_TYPE_OUTPUTER);
    	    return true;
    	}
    	
    	/**
    	 * Does contents output
    	 *
    	 * @param string $content
    	 * @return void
    	 */
    	function output($content, $isError = false){
    	    if ($isError){
    	    	$request = $this->getRequestData();
    	    	$this->response->setOuputOffset($request['fpp_output']);
    	    }    
            $this->response->setContent($content);
            $this->response->printOut();
		}
    	function redirect($url){
            if (function_exists('ob_start')){
            	ob_start();
            	ob_clean();
            }
            
            header('Location: ' . $url);
            exit();
    	}
    	
		/**
		 * Shows default page
     	 *
     	 * @return void
     	 */
    	function showDefaultPage(){
    		global $lang;
    		$lang		= new Lang();
    		
    		$content  = '';
    		$content .= '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"'."\n";
   			$content .= '"http://www.w3.org/TR/html4/loose.dtd">'."\n";
    		$content .= '<html>';
			$content .= '<head>';
			$content .= '<title>' . $lang->getValue('default_page_title') . '</title>';
			$content .= '</head>';
			$content .= '<body bgcolor="#FFFFFF" text="#000000" link="navy" vlink="navy" alink="red" style="font-family: verdana, arial, sans-serif; font-size: 8;">';
			$content .= '<center><table border="0" cellpadding="0" cellspacing="0" width="600" style="font-family: verdana, arial, sans-serif; font-size: 12;">';
  			$content .= '<tr><td>';
        	$content .= '<p align="center">' . $lang->getValue('default_page_content') . '</p>';
        	$content .= '<p align="center">' . $lang->getValue('default_page_footer') . '</td>';
  			$content .= '</tr>';
			$content .= '</table>';
			$content .= '</center>';
			$content .= '</body>';
			$content .= '</html>';
    	    $this->output($content);
    	}    	
    }

 

Link to comment
Share on other sites

I don't know enough to follow these suggestions.  I am sorry.

In the main index.php file for this script, it has:

    /**
     * Path definitions
     */
    define('PLUGINS_DIR',    './plugins/');
    define('CLASSES_DIR',    './classes/');
    define('CONFIG_FILE',    './ptd_config.php');
    define('ATTACHMENT_DIR', './attachments/');
    define('LANGUAGE_DIR',	 './lang/');
    define('TMP_DIR',	 	 './tmp/');
    
    /**
     * Default language definition
     */
    define('DEFAULT_LANG',	 'en');
    
    /**
     * Loading common classes
     */
    require_once(PLUGINS_DIR . 'common.php');
    require_once(CLASSES_DIR . 'error.class.php');
    require_once(CLASSES_DIR . 'file.class.php');
    require_once(CLASSES_DIR . 'config.class.php');
    require_once(CLASSES_DIR . 'lang.class.php');
    require_once(CLASSES_DIR . 'request.class.php');
    require_once(CLASSES_DIR . 'response.class.php');
    require_once(CLASSES_DIR . 'action.class.php');
    require_once(CLASSES_DIR . 'validator.class.php');
    require_once(CLASSES_DIR . 'executor.class.php');
    require_once(CLASSES_DIR . 'outputer.class.php');
    require_once(CLASSES_DIR . 'parser.class.php');
    require_once(CLASSES_DIR . 'formerror.class.php');

    /**
     * Main classes construction
     */
    $lang		= new Lang();
    $config		= new Config();
    $formError	= new FormError();
    $request	= new Request();
    $response	= new Response();


    if (isset($_POST['fpp_reset'])) {
    	$request->data['fpp_form'] = trim($_POST['fpp_form']);
    	$request->data['fpp_output'] = 1;
    }
    
    /**
     * Checking writable dirs
     */
    if (!is_writable(ATTACHMENT_DIR)){
    	$e = new Error($lang->getValue('err_dir_not_writable', ATTACHMENT_DIR));
    }
	if (!is_writable(TMP_DIR)){
    	$e = new Error($lang->getValue('err_dir_not_writable', TMP_DIR));
    }
        

Is this where the changes need to be made?

Link to comment
Share on other sites

Thank so much! That does indeed squash the error... but now with PHP 8, the form outputs simply:

default_page_content

default_page_footer

rather than the HTML form template that loads when processing with PHP 7.4.

Link to comment
Share on other sites

There may be other classes that need the same fix, but aren't broken enough to cause an error.  Look in the other PHP files for classes which have a function with the same name as the class, for example:

class MyFancyClass {
    function MyFancyClass(){
        //stuff
    }
}

Then rename the method to __construct like you did before so the code would become:

class MyFancyClass {
    function __construct(){
        //stuff
    }
}

If you can't find any or fixing the remaining ones doesn't resolve the problem then you may have some other compatibility issue. 

 

That the code has this particular issue indicates is was probably written around the PHP 4 / early PHP 5 days.  Much has changed since then, so you'll likely have to do one of

  • Spend time learning and fixing the issues or
  • Hire someone to fix the scripts for you or
  • Find a newer up to date script that does the same thing.

 

Link to comment
Share on other sites

it's also possible that the method in question is being explicitly called from somewhere within the code, given that it returns a value. there would be a fatal error, which could be hidden in the 'view source' of the output or may be hidden due to php's error_reporting/display_errors settings.

if this is the case, you would need to keep the original outputter() method definition, then have the new __construct() method call the outputter() method.

Link to comment
Share on other sites

Posted (edited)

Thank you.

I took ginerjm's advice from his signature and enabled ALL errors and found that while it worked in PHP 7.4 there were deprecated issues... I will start there.

Deprecated: Non-static method Action::isAvailable() should not be called statically...

Deprecated: Non-static method Action::Factory() should not be called statically...

...both appear 7 or 8 times, always point to the same line.

The former:

if (Action::isAvailable($var['name'])) {

This is the latter one:

$action = Action::Factory($action_data['name']);

I actually hired a Freelancer to try to fix the scripts a few days ago but we were not able to. Although, from what I've learned from this thread, along with all those new warnings from 7.4 and I think we'd have a better chance if we have another go at it.

Edited by wkilc
Link to comment
Share on other sites

it you post all this code on github, less any private settings, someone can have a look at it.

things that were previously Deprecated and have been removed in php8 will be producing errors, though if the code is running to the point of producing output, they are at least non-fatal errors. if the code itself is setting the error related settings, anything you do to set them, might be overwritten.

this looks like a typical misuse of OOP and from the small amount of actual posted logic, the author(s) misunderstood some of how php even works (the output buffering code in the redirect method does absolutely nothing.) this is a form to email application. are you using multiple user languages? are you using file attachments? it doesn't actually take a lot of code to validate a form submission and send an email.

 

Edited by mac_gyver
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.