将PHP对象传递给$.post()

3
我希望将两个PHP对象作为数据传递给$.post,而不做任何改变。
        $(function() {
            $("button").click(function() {  
                $.post("fight.php",{player: "<?php $player;?>", enemy: "<?php $enemy; ?>"},function(result) {
                    $("#displayFight").html(result);
                });
            });
        });

$player$enemy是两个不同的对象,每个对象都有一些属性。我希望将它们作为完整的对象传递,以便fight.php可以处理它们。

我也尝试过使用serialize,但没有成功:

{player: $("<?php $player ?>").serialize()}

我该如何做到这一点?

注意:在我尝试的所有方法中,要么出现了一些“未知标识符”,要么$_POST在接收页面上为空。

编辑:json_encode部分可以正常工作,但解码失败。 在接收页面上:

$player = json_decode($_POST["player"])

操作失败并返回错误:json_decode()期望第一个参数为字符串,但实际传入的是数组


你可以在它们上使用 json_encode - MacMac
你的对象需要能够转换为/从文本中转换。 - John Dvorak
4个回答

3
您需要使用json_encode,如下所示:
$.post("fight.php",{
    player: <?php echo json_encode($player);?>, 
    enemy: <?php echo json_encode($enemy);?>
}, ... );

请注意,在<?php ?>标签周围没有引号;如果需要,json_encode会自动添加引号。
除此之外,您需要了解json_encode的要求:最重要的是,如果您的对象包含字符串内容(作为属性或任何子对象的属性),则这些字符串必须以UTF-8编码。

一开始似乎可以工作,但是当从 $_POST 中取出数据时,每个对象都会以数组的形式出现。如果我尝试对它们进行 json_decode(),就会收到错误消息:"json_decode() 期望参数 1 是字符串,但实际得到的是数组"。有什么想法吗? - frrlod
@frrlod:jQuery确保序列化的表单在从PHP读取时会转换为数组;实际上是PHP从POST数据创建数组。没有办法让PHP从该数据中提供一个对象,因此从那时起你就需要自己解决了。适当的解决方案取决于您打算从请求中获取什么类型的对象。 - Jon
@frrlod:对于最简单的情况(一个没有子对象的普通stdClass对象),只需使用 $player = (object)$_POST['player'] 即可。 - Jon
@frrlod:对于最困难的情况(例如状态保存在非公共变量中的复杂对象),您需要编写代码将数组形式反序列化为所需的形式(这是我所做的)。如果到了这一步,您还可以使用serialize / deserialize并传递一个字符串,而不是使用json_encode,但这种方法仍然需要您自定义代码,并且具有我不关心的一些缺点(主要是:您不能从JS和/或HTML“分段”传递对象数据,您需要从一个地方一次性完成所有操作)。 - Jon
感谢您的时间和努力。我相信在这种情况下一个简单的stdClass就足够了。 - frrlod

1

1

一个建议是使用json_encode对PHP对象进行JSON编码。

然而,让我们考虑一下:您有一个生成输出的PHP脚本。该输出-其中包含此Javascript片段和2个对象-被发送到客户端(浏览器)执行,并通过AJAX调用将这两个对象重新发送回服务器。

因此,另一个想法可能是在会话中始终仅存储服务器端的对象,并仅发送标识符而不是整个对象:

<?php
    // apologies for errors - my PHP's rusty
    $_SESSION[$player->uuid()] = $player;
    $_SESSION[$enemy->uuid()] = $enemy;
?>
$.post("fight.php",{player: "<?php $player->uuid();?>", enemy: "<?php $enemy->uuid(); ?>"},function(result) {
    // ...
});

然后fight.php脚本会将它们恢复。
// is this still how PHP handles sessions?
$player = $_SESSION[$_POST['player']];
$enemy  = $_SESSION[$_POST['enemy']];

如果您使用传统框架构建数据库驱动应用程序,则这种方法特别适用,因为您的对象很可能存储在数据库中,并且可以轻松地从数据库中读取 - 这可能比使用 $_SESSION 数组更好的解决方案:
// if recollection serves this is CakePHP-ish
$player = $this->Player->find($_POST['player']);
$enemy  = $this->Enemy->find($_POST['enemy']);

你能解释一下第一行吗?为什么要用 [json_encode][1],而不是 json_encode($player)? - frrlod
@frrlod - 只是一个打字错误。我搞砸了我的Markdown注释,所以超链接没有正确呈现。 - Richard JP Le Guen
我喜欢这个想法。使用会话是否会因为过期而出现问题?我认为使用数据库是一个更好的想法,但只是为了学习。 - frrlod
@frrlod: "使用会话是否会因为过期而出现问题?" - 这取决于第一次请求和 AJAX 调用之间的时间间隔。您是否可以控制服务器配置以更改过期时间?此外,这些对象的生命周期/范围是什么?这些都是您在决定使用会话数据还是数据库时应该考虑的问题。 - Richard JP Le Guen

1
为了方便PHP和Javascript之间的通信,您应该正确序列化对象。最简单的方法是在PHP代码中调用json_encode($player)。然后,当您再次使用PHP获取它时,需要对其调用json_decode()并正确初始化对象。 PHP和Javascript没有共享对象实例的方式。只有序列化数据。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接