Home » Php » PHP Session with an Incomplete Object

PHP Session with an Incomplete Object

Posted by: admin April 23, 2020 Leave a comment

Questions:

I’m getting an error I don’t know how to fix so I wondering if I could get some help.

This is the error

Fatal error: process_form() [<a href='function.process-form'>function.process-form</a>]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition &quot;Template&quot; of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /home/twinmeddev/html/template_add.php on line 44

I get this error in the process_form() function. So what I get out of this is that, its thinking I didn’t load the class for the template. Which in fact I did up at the top. The include ‘inc/item.class.php’; Do I have to re-include it in the function?

Here’s the code for the particular page with the error. You can see I have everything included like it should be. Where have I gone wrong?

<?php
include 'inc/prep.php';
include 'inc/header.class.php';
include 'inc/item.class.php';
include 'inc/template.class.php';
include 'inc/formhelper.class.php';
include 'inc/formvalidator.class.php';
include_once( 'inc/config/config.php' ) ;
include_once( 'inc/DBE.class.php' ) ;
include_once( 'inc/GenFuncs.php' ) ;
include_once( 'inc/Search.class.php' ) ;

session_start();    

//Verify that user is logged in.
VerifyLogin($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING']);

if(array_key_exists('_submit',$_POST)) {
    if($fv_errors = validate_form()) {
        show_form($fv_errors);
    } else {
        process_form();
    }
}
else {
    // The form wasn't submitted or preview was selected, so display
    show_form();
}

function validate_form(){
}

function process_form(){
    global $mysqli;

    echo var_dump($_SESSION);

    $Template = $_SESSION['template'];
    $Template->name = $_POST['name'];
    $Template->descript = $_POST['descript'];
    $Template->user = $_SESSION['User'];
    $Template->customer = $_SESSION['CustID'];
    $Template->status = $_POST['status'];
    $Template->insert();

    //header("Location: template.php");
}
How to&Answers:

It’s missing the serialize/unserialize of your template class.

Take a look here for an working example I gave on another question of yours.

For instance, you probably want this:

<?php
  $_SESSION['template'] = serialize($template);
?>

and

<?php
  $template = unserialize($_SESSION['template']);
?>

Edit:

reading your comment about moving it to the top gives one hint.

The automatic serialization/unserialization occurs when you call session_start().
That means the order in which you include your files and call the session_start() is very important.

For example:

This would be wrong:

<?php
session_start();
include 'inc/template.class.php';
?>

While this would be correct:

<?php
include 'inc/template.class.php';
session_start();
?>

Now, I see in your example that it is in the CORRECT order, but I also notice you do many other includes before including template.class.php

Would it be possible that one of those includes (perhaps prep.php or header.class.php) does call start_session() too?
If yes, that was your issue (session_start() being called before your template.class.php).

Answer:

When you session_start() in php $_SESSION array is populated with corresponding objects. This means that all interfaces must be available (require). If the session has already been started previously by another script (eg framework) that had no visibility on the interfaces, objects in $ _SESSION will be incomplete, and do it again session_start() is useless because the session has already been started. One possible solution is to use the method session_write_close(), then session_start() which starts again populate $_SESSION, but with visibility into interface, so your object in $_SESSION will be good.

Answer:

I have posted my answer on a similar question, posting it again ’cause it answers this one as well.

PHP serializes its sessions using the built-in serialize and unserialize methods. serialize of PHP has the ability to serialize PHP objects (aka class instances) and convert them to string. When you unserialize those strings, It converts them back those same classes with those values. Classes who have some private properties and want to encode/decode that or do something complex in their serialization/deserialization implement the Serializable class and add serialize and unserialize methods to the class.

When PHP’s unserialize tries to unserialize a class object, but the class name isn’t declared/required, instead of giving a warning or throwing an Exception, it converts it to an object of __PHP_Incomplete_Class.

If you don’t want your session objects to convert to __PHP_Incomplete_Class, You can do it by either requiring the class files before you invoke session_start, or by registering an autoload function.

Answer:

How big are the objects that you are putting in the session? I got a similar error once when my objects were larger than the space we had allotted for the session in the php.ini file. If the object was too large, it would come back as being empty when it shouldn’t have been.

After that, I just started storing the object’s PK in the Session and looking it up if I needed it instead of carrying around the entire object itself.

You could also increase the size of the session in the INI file and see if that makes a difference.

Answer:

Please ensure that the class definition “Template” of the object you are trying to operate on was loaded before

I guess include 'inc/template.class.php'; is supposed to load the definition of the class Template?
Then maybe the include failed. Try require instead.

<?php
require 'inc/prep.php';
require 'inc/header.class.php';
require 'inc/item.class.php';
require 'inc/template.class.php';
require 'inc/formhelper.class.php';
require 'inc/formvalidator.class.php';
require_once( 'inc/config/config.php' ) ;
require_once( 'inc/DBE.class.php' ) ;
require_once( 'inc/GenFuncs.php' ) ;
require_once( 'inc/Search.class.php' ) ;

if ( !class_exists('Template') ) { die('No. Those include/requires did not define the class "Template"'); } session_start();

Answer:

i tried to store objects in session variable too. and yes i experienced the same problem as MackDaddy. and its solved by moving the include of the class to the first.

so..

require_once("class.someclass.php");
require_once("display.php");

worked

but not…

require_once("display.php");
require_once("class.someclass.php");

hmm…wonder whats the rational? and what if we have 2 or more different objects? which one comes first?

Answer:

In my case, order in which I included my files and called the session_start() was incorrect, as Carlos mentioned in his answer.

But I could not fix the order.

This workaround worked for me:

$_SESSION["template"] = unserialize(serialize($_SESSION["template"]))