带有不完整对象的 PHP 会话

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1055728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:48:24  来源:igfitidea点击:

PHP Session with an Incomplete Object

phpsessionobject

提问by MackDaddy

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?

我在 process_form() 函数中收到此错误。所以我从中得到的是,它认为我没有为模板加载类。事实上,我做到了。包含'inc/item.class.php'; 我是否必须将其重新包含在函数中?

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

回答by Carlos Lima

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

它缺少模板类的序列化/反序列化。

Take a look here for an working exampleI 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.

调用时会发生自动序列化/反序列化session_start()
这意味着包含文件和调用 的顺序session_start()非常重要。

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

现在,我在你的例子中看到它的顺序是正确的,但我也注意到你在包含 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).

是否有可能其中一个包含(可能是 prep.php 或 header.class.php)也调用start_session()
如果是,那是你的问题(session_start()在你的 template.class.php 之前被调用)。

回答by Vinx

When you session_start()in php $_SESSIONarray 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 $ _SESSIONwill 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 $_SESSIONwill be good.

当您session_start()在 php$_SESSION数组中填充相应的对象时。这意味着所有接口都必须可用(需要)。如果会话之前已经由另一个在接口上不可见的脚本(例如框架)启动,则对象$ _SESSION将是不完整的,再次执行session_start()是无用的,因为会话已经启动。一种可能的解决方案是使用 method session_write_close(),然后session_start()再次开始 populate $_SESSION,但具有界面可见性,因此您的对象 in$_SESSION将是好的。

回答by Steel Brain

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 serializeand unserializemethods. serializeof PHP has the ability to serialize PHP objects (aka class instances) and convert them to string. When you unserializethose 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 Serializableclass and add serializeand unserializemethods to the class.

PHP 使用内置的serializeunserialize方法序列化其会话。serializePHP 能够序列化 PHP 对象(又名类实例)并将它们转换为字符串。当您使用unserialize这些字符串时,它会将它们转换回具有这些值的相同类。谁拥有一些私人性质,并希望编码/解码是或做复杂的东西在自己的序列化/反序列化类实现Serializable类,并添加serializeunserialize方法的类。

When PHP's unserializetries 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.

当 PHPunserialize尝试对类对象进行反序列化,但未声明/需要类名时,它不会发出警告或抛出Exception,而是将其转换为__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.

如果您不希望会话对象转换为__PHP_Incomplete_Class,您可以通过在调用之前要求类文件session_start或注册自动加载函数来实现。

回答by AndyMcKenna

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.

您放入会话中的对象有多大?当我的对象大于我们在 php.ini 文件中为会话分配的空间时,我遇到了类似的错误。如果对象太大,它会在不应该是空的时候返回。

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.

之后,我开始将对象的 PK 存储在 Session 中,并在需要时查找它,而不是随身携带整个对象本身。

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

您还可以增加 INI 文件中会话的大小,看看是否有所不同。

回答by VolkerK

Please ensure that the class definition "Template" of the object you are trying to operate on was loaded before...
请确保您尝试操作的对象的类定义“模板...
我猜include 'inc/template.class.php';include 'inc/template.class.php';是应该加载类Template的定义?


那么可能包含失败了。尝试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();

回答by resting

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.

我也尝试将对象存储在会话变量中。是的,我遇到了与 MackDaddy 相同的问题。并通过将类的包含移到第一个来解决。

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?

嗯...想知道什么是理性?如果我们有 2 个或更多不同的对象怎么办?哪个先来?

回答by Savenkov Alexey

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

就我而言,session_start()正如卡洛斯在他的回答中提到的那样,我包含我的文件并调用的顺序是不正确的。

But I could not fix the order.

但我无法修复订单。

This workaround worked for me:

这个解决方法对我有用:

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