Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在自定义会话函数中使用闭包_Php_Session_Closures - Fatal编程技术网

Php 在自定义会话函数中使用闭包

Php 在自定义会话函数中使用闭包,php,session,closures,Php,Session,Closures,我试图为PHP编写一个自定义会话类,将会话移动到数据库中,并从文件系统中移除。 只有在调用闭包$connect2DB时,才会在\u read()方法中引发错误。在所有其他方法中,调用$connect2DB不会导致任何错误。 此外,如果我自己将该类实例化为对象,则所有方法(包括臭名昭著的\u read()都会按预期工作。你能找到错误吗 我有以下代码: class sessionDBHandler { public function __construct() { sessi

我试图为PHP编写一个自定义会话类,将会话移动到数据库中,并从文件系统中移除。 只有在调用闭包
$connect2DB
时,才会在
\u read()
方法中引发错误。在所有其他方法中,调用
$connect2DB
不会导致任何错误。 此外,如果我自己将该类实例化为对象,则所有方法(包括臭名昭著的
\u read()
都会按预期工作。你能找到错误吗

我有以下代码:

class sessionDBHandler {
    public function __construct() {
        session_set_save_handler(
            array($this, "_open"),
            array($this, "_close"),
            array($this, "_read"),
            array($this, "_write"),
            array($this, "_destroy"),
            array($this, "_gc")
        );
        register_shutdown_function('session_write_close');
    }

    public function _open() {
        global $sessCon;
        global $HOST;
        global $USER;
        global $PW;
        global $DATABASE;

        $sessCon=new mysqli($HOST,$USER,$PW,$DATABASE); //mysqli connection
    }

    public function _close() {
        global $sessCon;

        $sessCon->close();
    }

    public function _read($id) {
        global $sessCon;
        global $connect2DB;
        global $SESSIONTAB;

        $qRes=$connect2DB($sessCon,'select `data` from `'.$SESSIONTAB.'` where `ID`=?',array("s",$id)); //<-- error message here

        if(!empty($qRes["res"][0]["data"])) return $qRes["res"][0]["data"];
        else return '';
    }

    public function _write($id,$data) {
        global $sessCon;
        global $connect2DB;
        global $SESSIONTAB;

        $qRes=$connect2DB($sessCon,'select `ID` from `'.$SESSIONTAB.'` where `ID`=?',array("s",$id));

        $param=array(); //buliding SQL query parameters
        $param[0]="sis";
        $param[]=$id;
        $param[]=time();
        $param[]=$data;
        if(!empty($qRes["res"][0]["ID"])) {
            $param[0].="s";
            $param[]=$id;
        }

        $qRes=$connect2DB($sessCon,(!empty($qRes["res"][0]["ID"]) ? 'update' : 'insert').' `'.$SESSIONTAB.'` set `ID`=?, `access`=?, `data`=?'.(!empty($qRes["res"][0]["ID"]) ? ' where `ID`=?' : ''),$param);

        if($qRes["info"]["affectedRows"]>0) return true;
        else return '';
    }

    public function _destroy($id) {
        global $sessCon;
        global $connect2DB;
        global $SESSIONTAB;

        $qRes=$connect2DB($sessCon,'delete from `'.$SESSIONTAB.'` where `ID`=?',array("s",$id));

        if($qRes["info"]["affectedRows"]>0) return true;
        else return '';
    }

    public function _gc($max) {
        global $sessCon;
        global $connect2DB;
        global $SESSIONTAB;

        $qRes=$connect2DB($sessCon,'delete from `'.$SESSIONTAB.'` where `access`<?',array("i",(time()-$max)));

        if($qRes["info"]["affectedRows"]>0) return true;
        else return '';
    }
}
我的问题似乎是我使用的MySQL抽象层的闭包。我得到的错误是:

Fatal error: Function name must be a string in /Users/user/Sites/script.php on line 401
这对我来说意味着它不知何故找不到$connect2DB的名称空间。 问题是,如果我调用那些没有_构造函数及其
session\u set\u save\u handler
指令的函数,它将正常工作:

$test=new sessionDBHandler();
$test->_open();
echo $test->_read("d6e08112ff6fc8a7eb6e76832327bf81");
$test->_close();
以上操作没有错误。 现在我在这里使用闭包,因为我必须将这个脚本的占用空间保持在非常低的水平,并且在脚本的底部取消$connect2DB,还有其他原因,所以我希望保留当前的抽象层

你知道我能在这里做什么吗

谢谢大家

调用会话时,$connect2DB可能未初始化

CONNECT2DB 有趣的是,这将在没有错误的情况下运行并输出:

_open running with: login credentials
closure running!
requested id is: 746b70a979d9ef8c6686e659707b4b38
sessCon is: connection established!
requested id is: 746b70a979d9ef8c6686e659707b4b38 and data:
sessCon is: connection established!
connection closed!
现在,这表明我的特定实现中似乎存在错误。谁想尝试一下,欢迎加入:)

更新#3 我想在运行应用程序后取消关闭,因此,
unset($connect2DB)位于脚本的最底部。然而,这似乎在某种程度上造成了“过早”的不安。删除此选项将删除错误

然而
是否有一种方法可以在脚本运行后安全地取消关闭,使其不会流入主脚本?

我没有看到任何分配给
$connect2DB
。你是什么意思?您想让我发布connect2DB吗?您使用的是一个变量,因此必须在某个地方为该变量赋值。这与函数定义不同。好吧,我不知道那会是什么样子,我认为这听起来像是解决方案:)目前我正在做:
$connect2DB=function($mysqli,$query,$v=array(),$o=0){…}
@beetrootbeetroot:听起来这可能是关于meta的一个有趣的讨论话题,除此之外,PHP使用了许多不符合其通常定义的术语。
/**
* Simple MySQLi abstraction layer
*
* @param resource $mysqli The MySQLi connection link
* @param string   $query  The MySQL query for prepaired statement
* @param array    $v      The parameters to replace ? in $query. First element must be the type
* @param integer  $o      Option for more debug infos [0]=no infos(default) [1]=adding debug infos
*
* @return array [for select]=associative array of table result  [for everything else]=associative array with affectedRows,info and insertID
*
* @author Dominik Wilkowski
*/
$connect2DB=function($mysqli,$query,$v=array(),$o=0) {

    if($mysqli->connect_errno) {
        return array('info'=>array('error'=>'Connect failed: '.$mysqli->connect_error)); //error handling here
        exit();
    }

    if($v && (substr_count($query,"?")!=strlen($v[0]) || strlen($v[0])!=((count($v)-1)>=0 ? (count($v)-1) : 0))) {
        return array('info'=>array('error'=>'Placeholders are unequal! placeholders:'.substr_count($query,"?").', replacements:'.strlen($v[0]).', param:'.(count($v)-1).' ('.$v[0].')')); //error handling here...
        exit();
    }

    if($res=$mysqli->prepare($query)) {
            //dynamically bind all $v
            if($v) {
            $values=array($v[0]);
            for($i=1; $i<count($v); $i++) {
                ${'bind'.$i}=$v[$i];
                $values[]=&${'bind'.$i};
            }
            call_user_func_array(array($res,'bind_param'),$values);
        }
        $res->execute();

        //bind all table rows to result
        if(strtolower(substr($query,0,6))=="select") {
            $field=$fields=$tempRow=array();
            $meta=$res->result_metadata();
            while($field=$meta->fetch_field()) {
                $fieldName=$field->name;
                $fields[]=&$tempRow[$fieldName];
            }
            $meta->free_result();
            call_user_func_array(array($res,"bind_result"),$fields);

            //return associative array
            $results=array();
            $i=0;
            while($res->fetch()) {
                $results["res"][$i]=array();
                foreach($tempRow as $k=>$v2) $results["res"][$i][$k] = $v2;
                $i++;
            }
            $res->free_result();

        }
        else { //return infos about the query

            if($mysqli->warning_count) {
                if($err=$mysqli->query("SHOW WARNINGS")) {
                    $row=$err->fetch_row();
                    $results["info"]["error"].=$row[0].' ('.$row[1].'): '.$row[2];
                    $err->close();
                }
            }
            $results["info"]["affectedRows"]=$mysqli->affected_rows;
            $results["info"]["info"]=$mysqli->info;
            $results["info"]["insertID"]=$mysqli->insert_id;
        }

        $res->close();
    }

    if($o===1) { //adding debug infos
        $q=$query;
        for($i=1;$i<count($v);$i++) $q=preg_replace("/\?/",(substr($v[0],($i-1),1)=="s" ? '"' : '').$v[$i].(substr($v[0],($i-1),1)=="s" ? '"' : ''),$q,1);
        $results["info"]["query"]=$q;
        $results["info"]["param"]=json_encode($v);
    }

    if(strtolower(substr($query,0,6))=="update" || strtolower(substr($query,0,6))=="delete") { //optimize at update and delete
        preg_match_all('/((update|delete) `(.*)` )/i',$query,$tables);
        foreach($tables[3] as $t) $mysqli->query('OPTIMIZE TABLE '.$t);
    }

    return $results;
};
<?php
$LOGIN='login credentials';

//Closure
$nob=function() {
    return 'closure running!<br>';
};

//Session handler
class sessionDBHandler {
    public function __construct() {
        session_set_save_handler(
            array($this, "_open"),
            array($this, "_close"),
            array($this, "_read"),
            array($this, "_write"),
            array($this, "_destroy"),
            array($this, "_gc")
        );
        register_shutdown_function('session_write_close');
    }

    public function _open() {
        global $sessCon;
        global $LOGIN;

        echo '_open running with: '.$LOGIN.'<br>';
        $sessCon='connection established!<br>';
    }

    public function _close() {
        global $sessCon;

        echo $sessCon='connection closed!<br>';
    }

    public function _read($id) {
        global $sessCon;
        global $nob;

        echo $nob();
        echo 'requested id is: '.$id.'<br>';
        echo 'sessCon is: '.$sessCon;
    }

    public function _write($id,$data) {
        global $sessCon;

        echo 'requested id is: '.$id.' and data: '.$data.'<br>';
        echo 'sessCon is: '.$sessCon;
    }

    public function _destroy($id) {
        global $sessCon;

        echo 'requested id is: '.$id.'<br>';
        echo 'sessCon is: '.$sessCon;
    }

    public function _gc($max) {
        global $sessCon;

        echo 'requested max is: '.$max.'<br>';
        echo 'sessCon is: '.$sessCon;
    }
}

new sessionDBHandler();
session_start();
?>
_open running with: login credentials
closure running!
requested id is: 746b70a979d9ef8c6686e659707b4b38
sessCon is: connection established!
requested id is: 746b70a979d9ef8c6686e659707b4b38 and data:
sessCon is: connection established!
connection closed!