Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/243.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 动态生成的mysqli prepared语句的特殊行为_Php_Mysql - Fatal编程技术网

Php 动态生成的mysqli prepared语句的特殊行为

Php 动态生成的mysqli prepared语句的特殊行为,php,mysql,Php,Mysql,从昨天开始,在中找到的代码的答案或改进的开始,现在已经成为一个谜。我无法理解为什么动态生成的查询在mysqli客户机中运行时,或者甚至在php中作为标准准备语句写入时,会产生与等价查询不同的结果,从而丢失动态元素 对于希望进行实验的人,我提供了表模式和虚拟记录 动态查询是基于某些变量的存在而构建的。在最初的问题中,这些变量是POST变量,但这里是静态的——尽管可以通过注释它们来否定它们,这反过来会影响生成的WHERE子句 <style> body, body *{font-s

从昨天开始,在中找到的代码的答案或改进的开始,现在已经成为一个谜。我无法理解为什么动态生成的查询在mysqli客户机中运行时,或者甚至在php中作为标准准备语句写入时,会产生与等价查询不同的结果,从而丢失动态元素

对于希望进行实验的人,我提供了表模式和虚拟记录

动态查询是基于某些变量的存在而构建的。在最初的问题中,这些变量是POST变量,但这里是静态的——尽管可以通过注释它们来否定它们,这反过来会影响生成的WHERE子句

<style>
    body, body *{font-size:0.85rem;}
    h1,h2{font-size:0.95rem;text-decoration:underline}
    pre{white-space: pre-wrap;word-wrap: break-word;}
</style>
<?php

    /*

    to create a suitable table and populate with dummy data

    create table `volopp` (
        `id` int(10) unsigned not null auto_increment,
        `taskname` varchar(50) not null default '0',
        `industryname` varchar(50) not null default '0',
        `country` varchar(50) not null default '0',
        `orgname` varchar(50) not null default '0',
        `photo` varchar(50) not null default '0',
        primary key (`id`)
    )
    engine=innodb;

    insert into `volopp` (`id`, `taskname`, `industryname`, `description`, `country`, `orgname`, `photo`, `status`) values
        (1, 'squirrel juggling', 'outdoor pursuits', 'squirrels are members of the family sciuridae, a family that includes small or medium-size rodents. the squirrel family includes tree squirrels, ground squirrels, chipmunks, marmots, flying squirrels, and prairie dogs amongst other rodents.', 'scotland', 'squirrel jugglers association', 'squirrel.jpg', 1),
        (2, 'hedgehog pickling', 'food and drink', 'a hedgehog is any of the spiny mammals of the subfamily erinaceinae, in the eulipotyphlan family erinaceidae. there are seventeen species of hedgehog in five genera found through parts of europe, asia, and africa, and in new zealand by introduction.', 'england', 'hog heaven association', 'hedgehog.jpg', 0),
        (3, 'haggis hunting', 'outdoor pursuits', 'wild haggis is a creature of scottish folklore, said to be native to the scottish highlands. it is comically claimed to be the source of haggis, a traditional scottish dish that is in fact made from the innards of sheep.', 'scotland', 'campbell\'s haggis hunt', 'lesser-haggis.jpg', 1),
        (4, 'nessie netting', 'outdoor pursuits', 'the loch ness monster or nessie is said to be a creature that inhabits loch ness in the scottish highlands. it is often described as large in size with a long neck and one or more humps protruding from the water.', 'scotland', 'nessienets.org.uk', 'loch-ness.jpg', 0),
        (5, 'dwarf tossing', 'outdoor pursuits', 'dwarf-tossing, also called midget-tossing, is a pub/bar attraction in which people with dwarfism, wearing special padded clothing or velcro costumes, are thrown onto mattresses or at velcro-coated walls. participants compete to throw the person with dwarfism the farthest.', 'scotland', 'highlandgames.scot', 'highland-games.jpg', 1),
        (6, 'stickleback stuffing', 'indoor pursuits', 'sticklebacks are small, elongated fishes that reach a maximum length of about 18 cm (7 inches). the members of the family are characterized by a row of 2 to 16 spines on the back, which are positioned in front of a soft-rayed dorsal fin.', 'wales', 'stickleback.org', 'spinysucker.jpg', 0),
        (7, 'squirrel suckling', 'historic pastimes', 'tree rats', 'ireland', 'weirdness abounds', 'treerat.gif', 0);


    For reference
    +----+----------------------+-------------------+--------------------+----------+-------------------------------+--------------------+--------+
    | id | taskname             | industryname      | description        | country  | orgname                       | photo              | status |
    +----+----------------------+-------------------+--------------------+----------+-------------------------------+--------------------+--------+
    |  1 | squirrel juggling    | outdoor pursuits  | Squirrels are m... | scotland | Squirrel Jugglers Association | squirrel.jpg       |      1 |
    |  2 | Hedgehog Pickling    | food and drink    | A hedgehog is a... | england  | Hog Heaven Association        | hedgehog.jpg       |      0 |
    |  3 | Haggis Hunting       | outdoor pursuits  | Wild haggis is ... | scotland | Campbell's Haggis Hunt        | lesser-haggis.jpg  |      1 |
    |  4 | Nessie Netting       | outdoor pursuits  | The Loch Ness M... | scotland | NessieNets.org.uk             | Loch-Ness.jpg      |      0 |
    |  5 | Dwarf Tossing        | outdoor pursuits  | Dwarf-tossing, ... | scotland | highlandgames.scot            | highland-games.jpg |      1 |
    |  6 | Stickleback Stuffing | indoor pursuits   | Sticklebacks ar... | wales    | stickleback.org               | spinyfucker.jpg    |      0 |
    |  7 | squirrel suckling    | historic pastimes | tree rats...       | ireland  | weirdness abounds             | treerat.gif        |      0 |
    +----+----------------------+-------------------+--------------------+----------+-------------------------------+--------------------+--------+


    */

    /*
        utility functions to try to assist debugging
    */
    function pre( $data, $header ){
        $title = $header ? sprintf( '<h1>%s</h1>', $header ) : '';
        printf( '<pre>%s%s</pre>', $title, print_r($data,true) );
    }
    function preview_mysqli( $sql, $args ){
        $index=0;
        for( $i=0; $i < strlen( $sql ); $i++ ){
            $char = substr( $sql, $i, 1 );
            if( $char == '?' ) {
                $param = $args[ $index ];
                if( !strstr( $param, '"' ) )$param=sprintf( '"%s"', $param );
                $sql = substr_replace( $sql, $param, $i, 1 );
                $index++;
            }
        }
        return preg_replace( '@(\t)@', ' ', $sql );
    }
    function varname( $var ){
        foreach( $GLOBALS as $name => $value )if( $value === $var ) return $name;
        return false;
    }
    /*
        This writes out the equivilent php code one would use
        to run the query manually without generating on the fly.
        This produces different results but is, I'm sure, essentially
        the same query being executed.
    */
    function preview_mysqli_statement( $sql, $args ){
        $types=array();
        foreach( $args as $arg )$types[]=type( $arg );
        $vars=array();
        foreach( $args as $arg )$vars[]=sprintf( '$%s', varname( $arg ) );
        return preg_replace('@\t@',' ',sprintf('
            $sql="%s";

            $stmt=$db->prepare( $sql );
            $stmt->bind_param( "%s", %s );
            $res=$stmt->execute();
            if( $res ){
                $res=$stmt->get_result();
                while( $rs=$res->fetch_object() ){
                    pre( $rs, "-- record --" );
                }
            }',
            $sql,
            implode( '', $types ),
            implode( ', ', $vars )
        ));
    }
    /* 
        utility to return string for the variable type 
        used when creating the statement binding 
    */
    function type($arg){
        switch( gettype( $arg ) ){
            case 'integer':
            case 'int': return 'i';
            case 'float':
            case 'double': return 'd';
            default: return 's';
        }
    }








    /* standard db connection */
    $dbhost =   '127.0.0.1';
    $dbuser =   'root'; 
    $dbpwd  =   'xxx'; 
    $dbname =   'xxx';
    $db = new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );



    /* parameters used to generate where clause. Comment out to negate and modify query */
    $search_taskname='squirrel';
    $search_industry='outdoor pursuits';
    $search_country='scotland';
    $search_orgname='association';
    $search_description='folklore';

    /* placeholders */
    $where=array();
    $args=array();
    $types=array();


    /* Clause joining verb : AND | OR */
    $joiner='or';

    /* create where clause conditions */
    if( !empty( $search_taskname ) ){
        $where[]='`taskname` like ?';
        $search_taskname="%{$search_taskname}%";
        $args[]=$search_taskname;
    }

    if( !empty( $search_industry ) ){
        $where[]='`industryname`=?';
        $args[]=$search_industry;
    }

    if( !empty( $search_country ) ){
        $where[]='`country`=?';
        $args[]=$search_country;
    }

    if( !empty( $search_orgname ) ){
        $where[]='`orgname` like ?';
        $search_orgname="%{$search_orgname}%";
        $args[]=$search_orgname;
    }

    if( !empty( $search_description ) ){
        $where[]='`description` like ?';
        $search_description="%{$search_description}%";
        $args[]=$search_description;
    }

    if( isset( $search_status ) ){
        $where[]='`status`=?';
        $args[]=$search_status;
    }

    if( count( $where )==0 )exit('bad foo: no "WHERE" clause parameters');

    /* construct the full SQL statement with full where clauses */
    $sql=sprintf('select id,taskname,industryname,country,orgname,photo,status
        from `volopp`
        %s;', 
        count( $where ) > 0 ? sprintf( 'where %s', implode( sprintf( ' %s ', $joiner ), $where ) ) : ''
    );
    $params=&$args;



    $types=array();
    foreach( $params as $param )$types[]=type( $param );
    $types=implode( '', $types );



    /* debug statements */
    pre( preg_replace( '@\t@', ' ', $sql ), 'The generated sql statement to be passed to `prepare` method.' );
    pre( preview_mysqli( $sql, $params ), 'Effective query: Can be run in mysql client' );
    pre( preview_mysqli_statement( $sql, $params ), 'Generated php code to emulate the whole process. [copy]' );




    $stmt=$db->prepare( $sql );
    if( $stmt ){
        $vars=array();
        $vars[]=&$types;

        foreach( $params as $param ) $vars[]=&$param;

        $callback=array(  $stmt, 'bind_param' );
        call_user_func_array( $callback, $vars );


        $result = $stmt->execute();
        if( $result ){
            $result=$stmt->get_result();

            $i=1;
            while( $rs=$result->fetch_object() ){
                pre( $rs, sprintf(' --> Live record %d', $i ) );
                $i++;
            }
            $stmt->free_result();
            $stmt->close();
        }
    }


    /*
        if you copy the generated php code from debug output
        and run... it should run and produce different 
        results.
    */


?>
上面的屏幕截图显示了使用默认参数运行脚本时返回的1条记录

运行生成的PHP代码版本(如下所示)会产生与在mysql客户端中运行时相同的结果,请参见上面的屏幕截图

if( $stmt ){
     $vars=array();
     $vars[]=&$types;

     foreach( $params as $param ) $vars[]=&$param;

     $callback=array(  $stmt, 'bind_param' );

     print_r($vars);

     call_user_func_array( $callback, $vars );

抱歉发了这么长的邮件。如果有人知道发生了什么,我很乐意听到。毫无疑问,我错过了一些明显的东西,会觉得自己很愚蠢。有人指出了一个明显的错误

您的问题在细分市场中

if( $stmt ){
    $stmt->bind_param($types, ...$params);
其输出为

为了让这个电话更简单,我倾向于使用splat


我想这会给你想要的输出。

你试过echo$sql;出口看看,生成了什么?是的,生成的sql看起来不错~正如在向下投票时生成的屏幕快照中所看到的那样-因为它太长了,或者什么?几乎有20K个代表-并且你发布了低质量的文本图片?太好了-谢谢你找到了!我已经看过了,但没有使用splat操作符~使用它肯定比复杂的call\u user\u func\u数组方法容易得多。在该循环中,foreach$params作为$param,$param变量是正确的,但是添加到$vars的引用是错误的。。。嘿嘿。谢谢@Nigel!
Array
(
    [0] => sssss
    [1] => %folklore%
    [2] => %folklore%
    [3] => %folklore%
    [4] => %folklore%
    [5] => %folklore%
)
if( $stmt ){
    $stmt->bind_param($types, ...$params);