Сессия PHP с незавершенным объектом - PullRequest
35 голосов
/ 29 июня 2009

Я получаю сообщение об ошибке, я не знаю, как исправить, поэтому мне интересно, могу ли я получить какую-то помощь.

Это ошибка

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

Я получаю эту ошибку в функции process_form (). Итак, что я извлек из этого, так это то, что я подумал, что я не загружал класс для шаблона. Что на самом деле я сделал наверху. Включите 'inc / item.class.php'; Должен ли я включить его в функцию?

Вот код для конкретной страницы с ошибкой. Вы можете видеть, что у меня есть все как положено. Где я ошибся?

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

Ответы [ 7 ]

67 голосов
/ 29 июня 2009

Отсутствует сериализация / десериализация вашего класса шаблона.

Посмотрите здесь рабочий пример , который я дал по другому вашему вопросу.

Например, вы, вероятно, хотите это:

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

и

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

Edit:

чтение вашего комментария о перемещении его наверх дает одну подсказку.

Автоматическая сериализация / десериализация происходит при вызове session_start().
Это означает, что порядок, в котором вы включаете свои файлы и называете session_start(), очень важен.

Например:

Это было бы неправильно:

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

Пока это будет правильно:

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

Теперь я вижу в вашем примере, что это в ПРАВИЛЬНОМ порядке, но я также заметил, что вы делаете много других включений, прежде чем включать template.class.php

Возможно ли, что один из них (например, prep.php или header.class.php) тоже вызовет start_session()?
Если да, то это была ваша проблема (session_start() вызывается до вашего template.class.php).

9 голосов
/ 08 января 2014

Когда вы session_start() в массиве php $_SESSION заполняются соответствующими объектами. Это означает, что все интерфейсы должны быть доступны (требовать). Если сеанс уже был запущен ранее другим сценарием (например, каркасом), который не имел видимости на интерфейсах, объекты в $ _SESSION будут неполными и делать это снова session_start() бесполезно, так как сеанс уже был запущен. Одним из возможных решений является использование метода session_write_close(), затем session_start(), который снова начинает заполнять $_SESSION, но с видимостью в интерфейсе, поэтому ваш объект в $_SESSION будет хорошим.

5 голосов
/ 06 сентября 2015

Я отправил свой ответ на аналогичный вопрос , опубликовав его снова, потому что он также отвечает на этот вопрос.

PHP сериализует свои сессии, используя встроенные методы serialize и unserialize. serialize PHP имеет возможность сериализовать объекты PHP (также известные как экземпляры классов) и преобразовывать их в строку. Когда вы unserialize эти строки, он преобразует их обратно те же классы с этими значениями. Классы, которые имеют некоторые частные свойства и хотят кодировать / декодировать это или делать что-то сложное в своей сериализации / десериализации, реализуют класс Serializable и добавляют serialize и unserialize методов к классу.

Когда PHP unserialize пытается десериализовать объект класса, но имя класса не объявляется / не требуется вместо предупреждения или выдачи Exception, он преобразует его в объект __PHP_Incomplete_Class.

Если вы не хотите, чтобы ваши сеансовые объекты конвертировались в __PHP_Incomplete_Class, вы можете сделать это, либо запросив файлы классов перед вызовом session_start, либо зарегистрировав функцию автозагрузки.

2 голосов
/ 29 июня 2009

Убедитесь, что определение класса " Шаблон " объекта, с которым вы пытаетесь работать, было загружено до ...
Я предполагаю include 'inc/template.class.php'; предполагается загрузить определение класса Template?
Тогда, возможно, включить не удалось. Попробуйте вместо .
<?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' ) ;</p>

<p>if ( !class_exists('Template') ) {
  die('No. Those include/requires did not define the class "Template"');
}
session_start();
2 голосов
/ 29 июня 2009

Насколько велики объекты, которые вы помещаете в сеанс? Однажды я получил похожую ошибку, когда мои объекты были больше, чем пространство, выделенное для сеанса в файле php.ini. Если бы объект был слишком большим, он бы вернулся пустым, когда его не должно было быть.

После этого я просто начал сохранять PK объекта в сеансе и искать его, если он мне нужен, вместо того, чтобы носить с собой весь объект.

Вы также можете увеличить размер сеанса в INI-файле и посмотреть, имеет ли это значение.

1 голос
/ 29 января 2010

Я тоже пытался хранить объекты в переменной сессии. и да, я испытал ту же проблему, что и MackDaddy. и это решается перемещением включения класса в первый.

так ..

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

работал

но не ...

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

хм ... интересно, что рационального? а что если у нас есть 2 или более разных объектов? какой из них на первом месте?

0 голосов
/ 26 декабря 2017

В моем случае порядок, в котором я включил свои файлы и назвал session_start(), был неправильным, как Карлос упомянул в своем ответе.

Но я не смог исправить заказ.

Этот обходной путь работал для меня:

$_SESSION["template"] = unserialize(serialize($_SESSION["template"]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...