2009-06-28 3 views
33

Ricevo un errore Non so come risolvere, quindi mi chiedo se potrei ricevere aiuto.Sessione PHP con un oggetto incompleto

Questo è l'errore

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 

ottengo questo errore nella funzione process_form(). Quindi quello che ne ricavo è che, pensando che non ho caricato la classe per il modello. Che in effetti ho fatto in cima. L'inclusione 'inc/item.class.php'; Devo ri-includerlo nella funzione?

Ecco il codice per la pagina specifica con l'errore. Puoi vedere che ho incluso tutto come dovrebbe essere. Dove ho sbagliato?

<?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"); 
} 
+0

Qual è la sua impostazione di session.auto_start file php.ini? –

risposta

64

Manca la serializzazione/unserialize della classe del modello.

Dai un'occhiata qui per un working example Ti ho dato un'altra tua domanda.

Per esempio, è probabile che desidera che questo:

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

e

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

Edit:

leggere i suoi commenti su spostandolo verso l'alto dà un suggerimento.

La serializzazione/la serializzazione automatica si verifica quando si chiama session_start().
Ciò significa che l'ordine in cui si includono i file e chiamare lo session_start() è molto importante.

Ad esempio:

Questo sarebbe sbagliato:

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

Anche se questo sarebbe corretto:

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

Ora, io vedo nel tuo esempio che è nell'ordine corretto , ma noto anche che fai molte altre inclusioni prima di includere template.class.php

Vorrei È possibile che uno di quelli inclusi (forse prep.php o header.class.php) chiami anche start_session()?
Se sì, quello era il tuo problema (session_start() chiamato prima del tuo template.class.php).

+4

Da quello che ho capito PHP serializza automaticamente un oggetto se lo aggiungi a una sessione e poi lo deserializza se lo assegni a una variabile. Almeno questo è quello che ho letto qui: http://www.devshed.com/c/a/PHP/Working-with-MySQL-and-Sessions-to-Serialize-Objects-in-PHP/1/ Tutto ciò che riguardava il mio oggetto funzionava bene, tranne questo. – MackDaddy

+0

Prendendo l'esempio che ti ho dato sull'altro post e rimuovendo il serialize/unserialize otterrai questo: $ $ unserialized template: oggetto (__ PHP_Incomplete_Class) # 1 (3) {...} –

+0

Non fidarti di me provate il codice che vi ho dato come esempio, quindi provate ad aggiungere un/serialize al vostro codice e vediamo se funziona :) –

2

Quanto sono grandi gli oggetti che si stanno inserendo nella sessione? Ho avuto un errore simile una volta quando i miei oggetti erano più grandi dello spazio che avevamo assegnato per la sessione nel file php.ini. Se l'oggetto fosse troppo grande, tornerebbe vuoto quando non avrebbe dovuto essere.

Dopodiché, ho appena iniziato a memorizzare il PK dell'oggetto nella Session e a cercarlo se ne avessi avuto bisogno invece di portare in giro l'intero oggetto stesso.

Si potrebbe anche aumentare la dimensione della sessione nel file INI e vedere se questo fa la differenza.

2

Assicurarsi che la definizione della classe " Template" dell'oggetto che si sta tentando di operare su è stato caricato prima ...
Credo include 'inc/template.class.php'; dovrebbe caricare la definizione del modello di classe?
Quindi forse l'inclusione non è riuscita. Prova invece a require.
<?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();

+3

'require' e' include' sono identici in tutti i modi tranne il modo in cui gestiscono l'errore. Entrambi producono un avvertimento, ma "richiedono" si traduce in un errore fatale. –

1

Ho provato a memorizzare oggetti anche nella variabile di sessione. e sì ho sperimentato lo stesso problema di MackDaddy. e si risolve spostando l'inclusione della classe sul primo.

così ..

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

lavorato

ma non ...

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

hmm ... si chiedono che cosa è il razionale? e cosa succede se abbiamo 2 o più oggetti diversi? quale viene prima?

9

Quando session_start() in php $_SESSION matrice è popolato con oggetti corrispondenti. Ciò significa che tutte le interfacce devono essere disponibili (richiedono). Se la sessione è già stata avviata in precedenza da un altro script (ad esempio framework) che non ha visibilità sulle interfacce, gli oggetti in $ _SESSION non saranno completi e lo eseguiranno nuovamente session_start() perché la sessione è già stata avviata. Una possibile soluzione consiste nell'utilizzare il metodo session_write_close(), quindi session_start(), che ricomincia a popolare $_SESSION, ma con visibilità nell'interfaccia, quindi il tuo oggetto in $_SESSION sarà buono.

+0

Brillante. Questo ha risolto un problema che avevo con l'utilizzo della mia classe di carrello degli acquisti (che utilizza $ _SESSION come contenitore per il carrello) in combinazione con Wordpress (che aveva già avviato la sessione). Grazie! – cjs1978

5

Ho pubblicato la mia risposta su un similar question, pubblicandolo di nuovo perché anche questo risponde.

PHP serializza le sessioni utilizzando i metodi incorporati serialize e unserialize. serialize di PHP ha la possibilità di serializzare oggetti PHP (ovvero istanze di classe) e convertirli in stringa. Quando hai unserialize stringhe, le converte indietro con quelle stesse classi. Le classi che hanno alcune proprietà private e vogliono codificarle/decodificarle o fare qualcosa di complesso nella loro serializzazione/deserializzazione implementano la classe Serializable e aggiungono i metodi serialize e unserialize alla classe.

Quando unserialize cerca di PHP per unserialize un oggetto di classe, ma il nome della classe non è dichiarata/richiesta, invece di dare un avvertimento o lanciare un Exception, si converte in un oggetto di __PHP_Incomplete_Class.

Se non si desidera convertire gli oggetti di sessione in __PHP_Incomplete_Class, è possibile farlo richiedendo i file di classe prima di richiamare session_start o registrando una funzione di caricamento automatico.

0

Nel mio caso, l'ordine in cui ho incluso i miei file e chiamato lo session_start() non era corretto, come Carlos ha menzionato nella sua risposta.

Ma non ho potuto correggere l'ordine.

Questa soluzione ha funzionato per me:

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