web-dev-qa-db-fra.com

PHP Session avec un objet incomplet

Je reçois une erreur que je ne sais pas comment corriger, alors je me demande si je pourrais obtenir de l'aide.

C'est l'erreur

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

Je reçois cette erreur dans la fonction process_form (). Donc ce que je tire de ceci est que, sa pensée je n'ai pas chargé la classe pour le modèle. Ce que j'ai fait en haut. Le include 'inc/item.class.php'; Dois-je le ré-inclure dans la fonction? 

Voici le code de la page avec l'erreur. Vous pouvez voir que j'ai tout inclus comme il se doit. Où est-ce que je me suis trompé?

<?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");
}
35
MackDaddy

Il manque la sérialisation/désérialisation de votre classe de modèle.

Jetez un coup d'oeil ici pour un exemple de travail j'ai donné sur une autre question de la vôtre.

Par exemple, vous voulez probablement ceci:

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

et

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

Modifier:

lire votre commentaire sur le déplacement en haut donne un indice.

La sérialisation/désérialisation automatique se produit lorsque vous appelez session_start().
Cela signifie que l'ordre dans lequel vous incluez vos fichiers et appelez le session_start() est très important.

Par exemple:

Ce serait faux:

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

Bien que cela soit correct:

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

Maintenant, je vois dans votre exemple que c'est dans l'ordre CORRECT, mais je remarque aussi que vous faites beaucoup d'autres inclus avant d'inclure template.class.php 

Serait-il possible qu'un de ces inclusions (peut-être prep.php ou header.class.php) appelle aussi start_session()?
Si oui, c'était votre problème (session_start() étant appelé avant votre template.class.php).

66
Carlos Lima

Lorsque vous session_start() dans php $_SESSION, le tableau est rempli avec les objets correspondants. Cela signifie que toutes les interfaces doivent être disponibles (requis). Si la session a déjà été lancée précédemment par un autre script (par exemple, le framework) qui n'avait aucune visibilité sur les interfaces, les objets dans $ _SESSION seront incomplets et recommencez session_start() est inutile car la session a déjà été démarrée. Une solution possible consiste à utiliser la méthode session_write_close(), puis session_start() qui recommence à peupler $_SESSION, mais avec une visibilité dans l'interface, donc votre objet dans $_SESSION sera bon.

9
Vinx

J'ai posté ma réponse sur une question similaire , la postant à nouveau car elle répond également à celle-ci.

PHP sérialise ses sessions en utilisant les méthodes serialize et unserialize intégrées. serialize of PHP peut sérialiser des objets PHP (également appelés instances de classe) et les convertir en chaîne. Lorsque vous (unserialize _ ces chaînes, il les reconvertit avec ces mêmes valeurs. Les classes qui ont des propriétés privées et qui souhaitent encoder/décoder cela ou faire quelque chose de complexe dans leur sérialisation/désérialisation implémentent les méthodes Serializable et ajoutent serialize et unserialize à la classe.

Lorsque unserialize de PHP essaie de désérialiser un objet de classe, mais que le nom de la classe n'est pas déclaré/requis, au lieu de donner un avertissement ou de lancer un Exception , il le convertit en objet de __PHP_Incomplete_Class.

Si vous ne voulez pas que vos objets de session soient convertis en __PHP_Incomplete_Class, vous pouvez le faire en exigeant les fichiers de classe avant d'appeler session_start , ou en enregistrant une fonction de chargement automatique.

5
Steel Brain

Quelle est la taille des objets que vous mettez dans la session? J'ai eu une erreur similaire une fois lorsque mes objets étaient plus grands que l'espace que nous avions alloué pour la session dans le fichier php.ini. Si l'objet était trop grand, il redeviendrait vide alors qu'il n'aurait pas dû l'être.

Après cela, j'ai juste commencé à stocker la PK de l'objet dans la session et à la rechercher si j'en avais besoin au lieu de transporter tout l'objet lui-même.

Vous pouvez également augmenter la taille de la session dans le fichier INI et voir si cela fait une différence.

2
AndyMcKenna

Veuillez vous assurer que la définition de la classe "Modèle"de l'objet que vous essayez d'opérer a été chargé avant ...
J'imagine que include 'inc/template.class.php'; est censé charger la définition de la classe Template?
Alors peut-être que l'inclusion a échoué. Essayez require à la place.
<?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();

2
VolkerK

j'ai essayé de stocker des objets dans la variable de session aussi. et oui j'ai eu le même problème que MackDaddy. et son résolu en déplaçant l'inclusion de la classe à la première.

alors..

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

travaillé

mais non...

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

hmm ... me demande quel est le rationnel? Et si nous avions 2 ou plusieurs objets différents? lequel vient en premier?

1
resting

Dans mon cas, l'ordre dans lequel j'ai inclus mes fichiers et appelé le session_start() était incorrect, comme l'a mentionné Carlos dans sa réponse.

Mais je ne pouvais pas réparer l'ordre.

Cette solution a fonctionné pour moi:

$_SESSION["template"] = unserialize(serialize($_SESSION["template"]))
0
Savenkov Alexey