Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Session with an Incomplete Object

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");
}
like image 675
MackDaddy Avatar asked Jun 28 '09 20:06

MackDaddy


3 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).

like image 85
Carlos Lima Avatar answered Sep 24 '22 18:09

Carlos Lima


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.

like image 35
Vinx Avatar answered Sep 24 '22 18:09

Vinx


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.

like image 22
Steel Brain Avatar answered Sep 23 '22 18:09

Steel Brain