Php 在回显$\u会话变量后取消设置该变量会改变视图

Php 在回显$\u会话变量后取消设置该变量会改变视图,php,unset,ob-start,Php,Unset,Ob Start,我正在使用$\u会话存储要显示给用户的消息 $_SESSION['message']['error']=" an error appear", $_SESSION['message']['warning']="not good !" 我的HTML页面是通过包含一些HTML视图和生成变量生成的 这是在ob\u start和ob\u get\u clean()之间完成的 然后我将结果回传给用户 $_SESSION['message']['error']=" an error appear", $_

我正在使用$\u会话存储要显示给用户的消息

$_SESSION['message']['error']=" an error appear",
$_SESSION['message']['warning']="not good !"
我的HTML页面是通过包含一些HTML视图和生成变量生成的

这是在
ob\u start
ob\u get\u clean()之间完成的

然后我将结果回传给用户

$_SESSION['message']['error']=" an error appear",
$_SESSION['message']['warning']="not good !"
在那之后,我取消了
$\u会话['message']
,为下一页留下了一个干净的环境

似乎未设置与
ob_start()

当我对unset进行注释时,显示了正确的消息。 但当我取消注释时,消息显示为空

我已尝试在代码中的不同位置取消设置
$\u会话['message']
。我已尝试将其设置为空数组

PHP内核似乎正在进行一些优化,并以不适当的顺序解释我的代码

看起来有点像这样:

ob_start();
$ctrl=new$classeControleur();
$ctrl->$action();
$contenu=ob_get_clean();
包括CHEMIN_VUE'header.view.php';
require('aside.php');
回声';
echo$contenu;
回声';
//HTML结尾
取消设置($_会话['message']);

请记住,PHP中的会话处于阻塞状态,一次只能有一个进程访问给定的会话文件-任何试图访问同一会话的其他进程都将等待轮到它。 一旦您打开会话,它将永远阻塞,直到您关闭它或程序自行完成并退出

$\u SESSION superglobal保存属于上次打开的会话的键/值对,但此变量不是会话本身。它允许您修改打开的会话,并记住以前打开的会话中的数据,仅此而已

您必须手动启动会话(除非在php.ini中另有配置-不要这样做),然后才能对其进行写入。您需要做的是打开会话,进行更改,然后立即关闭它。如果需要,您可以稍后重新打开它

始终在完成对会话的写入后立即关闭该会话,以便其他进程可以访问该会话并保存其更改。如果保持打开状态,则没有人能够保存任何更改

在这里,我举了一个小例子,说明如何在一次脚本运行期间多次访问会话数据

<?php

// we check if session is already open or not
// in another included file for example
if (!session_id()) {
  // now we create new session if it doesn't exists
  // or reopen and continue previous one
  session_start();
}

// session is now open so we can we can save a value inside
$_SESSION['last_seen'] = time();

// we can also remove existing values
unset($_SESSION['user_favourite_color']);

// we can read saved values if they exists
if (isset($_SESSION['username'])) {
  echo 'Hello '. $_SESSION['username'] .'!'. PHP_EOL;
  echo 'Yes I REMEMBER YOU!' . PHP_EOL;
} else {
  echo 'I DONT KNOW YOU! I see you for the first time.'. PHP_EOL;
  $_SESSION['username'] = 'Mr USERNAME';
  echo 'Now I noted your name, I will remember you.'. PHP_EOL;
}

// now we close session to not block it any longer
// maybe some other process is waiting to use it
session_write_close();

// here you do some other stuff
// lets sleep for example
sleep(2);

// you can reopen the same session
// but remember something might have changed
// since you had it open last time (before sleep)
// like maybe in different browser tab, just keep that in mind
session_start();
$_SESSION['visit'] += 1;
unset($_SESSION['something']);

// and we should close it again to make sure our changes are saved
session_write_close();

我们在办公室的一位高级开发人员那里找到了解决方案

还有一些解释:

我将MVC与前端控制器一起使用。我提供的代码是前端控制器的一部分

我们从
$\u get['action']
获得
$action
,从
$\u get['ctrl']
获得
$ctrl
。然后我们从控制器
ctrl()
执行方法
action()
。如果需要通知用户,该方法会执行一些逻辑并更新会话['message']
。然后,
$\u会话['message']
存储在
$message
中,随后出现
echo$消息在相应的视图中。最后,缓冲区被刷新到$contenu,由
echo$contenu发送给用户行。然后我认为取消设置
$\u会话['message']
是安全的,因为它已经被发送了。但令人惊讶的是,它是空的。这不是如果我评论未设置的行,而是我在程序的其他页面向用户发送未经请求的消息

我还使用action()方法中的Post Redirect Get模式,重定向到同一页面(以避免提交两次数据)。 问题就在那里!我通过
标题('location')
重定向。 我以为
header()
立即结束了脚本,但事实上(由于缓冲!!)它一直持续到结尾,然后php发送头

我在
标题('location')
后面放了一个
die()


我学到了一些新东西/那很好

那么您的问题是什么呢?将$_SESSION['message']分配给一个变量,然后取消设置$_SESSION['message'],这就是我要做的。在“$ctrl->$action()”下。方法检查$\u会话['message']是否存在,并将消息存储在$message中。然后我在视图中回显$message。似乎在ob_start和ob_get_clean之间完成了未设置!谢天谢地,我的问题是“有没有可能PHP内核决定在缓冲期间执行unset,尽管我会在之后执行呢!”。。。(顺便问一下,PHP7.2.24)
$ctrl->$action()
实际上是做什么的?看看您如何调用它,它似乎可以根据
$action
的值调用不同的方法。您是否在调用的方法中回显会话的值?因为我看不到你在其他地方输出会话值。谢谢你给我一些建议。我的代码在web门户下运行。是web门户为客户端代码启动会话。应用程序广泛使用会话来存储数据。但很少在会话下取消设置变量。该会话似乎工作正常,我没有能力直接修改它。它似乎是:。。。取消设置($_会话['message'])<代码>…在ob_开始和ob_获得_清洁之间执行。或者有一个“gohst引用”在将视图传输到浏览器后修改视图(我知道这很奇怪)。好吧,会话除了存储简单的标志外(比如$_SESSION['is_logged']=1),实在不适合存储任何东西。它们是基于文件的,它们总是处于阻塞状态,并且它们存储的数据实际上会丢失,不仅当您销毁它时,而且当用户丢失带有会话ID的cookie时,这样您就可以得到大量等待过期日期的僵尸临时文件。对于临时数据,我会使用共享内存,而不是像“shmop”这样的扩展—它非常快而且相当简单。