【问题标题】:PDO execution to database using bindParam through HTML form通过 HTML 表单使用 bindParam 对数据库执行 PDO
【发布时间】:2019-06-15 20:21:38
【问题描述】:

我正在努力实现的目标

我正在尝试使用用户在表单中填写的值来更新我的数据库。

我已经花了几个月的时间在无休止的 Google 搜索中避免向 StackOverflow 提问,每个网站都教会了我一些东西,但我还没有完成这个产品。

我正在努力解决的问题

提交时,PDO::execute 不执行且数据库不更新。 以前我收到"Undefined index" 的错误,但这些错误已通过正确传递变量得到解决。现在我没有收到任何错误。

我的问题

我做错了什么?考虑到我在控制台或任何地方都没有收到任何错误(并且error_reporting 已打开)。我检查它是否已执行的if 语句总是给出nope,所以在查询的某个地方它失败了。

另外我怎样才能更好地调试这个?

我尝试过的 (代码已被缩小以显示相关内容)

index.php(显示带有 Update 按钮的表格,将我重定向到 update.php)

<?php
session_start();

require 'assets/php/database.php';
require 'assets/php/usersession.php';

?>
<!DOCTYPE html>
<html>
<head>
<!-- irrelevant content -->
</head>
<body>
    <?php
    $sql = "SELECT * FROM utlansliste";

    $stmt = $conn->prepare($sql);
    $stmt->execute();
    $result = $stmt->fetchAll();
    ?>

    <table>
        <thead>
            <th>ID</th>
            <th>Brukernavn</th>
            <th>Datamaskin</th>
            <th>Periferiutstyr</th>
            <th>Start dato</th>
            <th>Slutt dato</th>
            <th>Oppdater tabell</th>
        </thead>

        <?php
        foreach($result as $rows) {
        ?>

        <tr>
            <td><?php echo $rows['id']; ?></td>
            <td><?php echo $rows['username']; ?></td>
            <td><?php echo $rows['hostname']; ?></td>
            <td><?php echo $rows['peripherals']; ?></td>
            <td><?php echo $rows['start_date']; ?></td>
            <td><?php echo $rows['end_date']; ?></td>
            <td><a href="update.php?id=<?php echo $rows['id'];?>&hostname=<?php echo $rows['hostname'];?>"><div class="btn btn-primary">Oppdater</div></a></td>
        </tr>

        <?php
        }
        ?>

    </table>
</body>
</html>

update.php(用户填写表格和执行的地方)

<?php

session_start();

require 'assets/php/database.php';
require 'assets/php/usersession.php';

if(isset($_GET['id'])) {

    $id = $_GET['id'];
    $hostname = $_GET['hostname'];

    global $conn;
    $sql = "SELECT * FROM utlansliste WHERE id='$id';";
    $stmt = $conn->prepare($sql);
    $stmt->execute();
    $row = $stmt->fetchAll();

    $username = $row[0]['username'];
    $peripherals = $row[0]['peripherals'];
    $start_date = $row[0]['start_date'];
    $end_date = $row[0]['end_date'];

    if(isset($_POST['submit'])) {

        try {

            global $conn;
            $sql = "UPDATE utlansliste SET username = ':username', peripherals = ':peripherals', start_date = ':start_date', end_date = ':end_date', WHERE id = ':id'";

            $stmt = $conn->prepare($sql);
            $stmt->bindParam(":username", $username, PDO::PARAM_STR);
            $stmt->bindParam(":peripherals", $peripherals, PDO::PARAM_STR);
            $stmt->bindParam(":start_date", $start_date, PDO::PARAM_STR);
            $stmt->bindParam(":end_date", $end_date, PDO::PARAM_STR);
            $stmt->bindParam(":id", $id, PDO::PARAM_STR);
            $stmt->execute();

            if ($stmt->execute()) { 
               echo "gg";
            } else {
               echo "nope";
            }

            /*header('Location:index.php');*/
            }

            catch(PDOException $exception)  {
            echo "Error: " . $exception->getMessage();
        }
    }
}
?>
<html>
<head>
<!-- irrelevant content -->
</head>
<body>
    <?php include 'assets/php/header.php' ?>
    <?php if( !empty($user) ): ?>
    <div class="content">
        <strong>Oppdater utlånsliste for <?php echo $hostname; ?></strong>
        <form name="form" method="POST" action="">
            <div class="updatebox" style="text-align:center;">
                <label for="username">Brukernavn</label>
                <div><input type="text" name="username" value="<?php echo $username;?>" id="username" required/></div>

                <label for="peripherals">Periferiutstyr</label>
                <div><input type="text" name="peripherals" value="<?php echo $peripherals;?>" id="peripherals"/></div>

                <label for="startdate">Låne fra - dato</label>
                <div><input data-date-format="YYYY/MM/DD" type="date" name="start_date" value="<?php echo $start_date;?>" id="start_date" required/></div>

                <label for="enddate">Låne til - dato</label>
                <div><input data-date-format="YYYY/MM/DD" type="date" name="end_date" value="<?php echo $end_date;?>" id="end_date" required/></div>

                <input name="id" type="hidden" id="id" value="<?php echo $id;?>"/>
                <input name="hostname" type="hidden" value="<?php echo $hostname;?>" id="hostname"/>
                <input type="submit" name="submit" value="Submit"/>
            </div>
        </form> 
    </div>
<body>
</html>

其他 cmets

我查看了许多寻求帮助和知识的网站。这些只是其中的几个。我主要是在寻找知识来学习这种更新数据库的安全方法,所以即使只是一个评论也有很大帮助!

PHPDelusions

Edit form with PHP PDO

Form in PDO to update data

The official PDO manual

The unofficial PDO manual, (PDODelusions)

【问题讨论】:

  • 在占位符 username = ':username', peripherals = ':peripherals', 周围丢失引号 ~ 尝试改用 username = :username, peripherals = :peripherals, 等,只有一个 $stmt-&gt;execute()
  • @RamRaider 没有解决。只有一个 $stmt-&gt;execute(); 是什么意思?我只有一个,另一个只是检查查询的if 语句。
  • 您链接了 PHPDelusions,更具体地说是该指南的更新部分,它显示了 named parameters 没有被引用,我知道 @RamRaider 已经提到了这一点,但我再次提出它的原因是尽管您列出了一堆您浏览过的资源,但您真正阅读过的资源有多少?
  • 关于错误报告,资源列表中的最后一个链接将引导您到this,它会教您设置属性,以便 PDO 抛出异常。
  • @Sanguinary 你能把那个答案链接给我吗?这样我就可以在答案上留下注释,以防止错误信息的传播。

标签: php mysql forms pdo


【解决方案1】:

之前的 sql 不正确 - 除了占位符周围的单引号外,where 子句之前还有一个逗号。

$sql = "UPDATE utlansliste SET 
            username = :username, 
            peripherals = :peripherals, 
            start_date = :start_date, 
            end_date = :end_date 
        WHERE id = :id";

你能确认更新语句确实被调用了吗?尝试在调用 execute 方法之前/之后打印 sql 以确保程序到达该点

快速浏览 PHP 并进行了一些可能(或可能没有)帮助的小改动。

<?php

    try{
        session_start();
        $id='';

        require 'assets/php/database.php';
        require 'assets/php/usersession.php';

        if( isset( $_GET['id'], $_GET['hostname'] ) ) {

            $id = $_GET['id'];
            $hostname = $_GET['hostname'];


            /*
                global $conn;

                The `global` keyword is used within functions to allow a variable declared outside the function
                to be used within the function... think `scope`
            */


            /*
            $sql = "SELECT * FROM utlansliste WHERE id='$id';";
            As the problem revolves around prepared statements why not use a prepared statement here
            and avoid the possibility of sql injection??
            */

            $sql='select * from `utlansliste` where id=:id;';
            $args=array( ':id' => $id );
            $stmt = $conn->prepare($sql);
            $res=$stmt->execute( $args );

            if( !$res )throw new Exception(' Failed to SELECT records ');



            $row = $stmt->fetchAll();

            $username = $row[0]['username'];
            $peripherals = $row[0]['peripherals'];
            $start_date = $row[0]['start_date'];
            $end_date = $row[0]['end_date'];

            /* make sure that all variables are available... */
            if( isset( $_POST['submit'], $username,$peripherals,$start_date,$end_date ) ) {

                try {
                    /* same issue, global is NOT required */
                    #global $conn;

                    $sql = "UPDATE utlansliste SET username = :username, peripherals = :peripherals, start_date = :start_date, end_date = :end_date WHERE id = :id";

                    $stmt = $conn->prepare( $sql );
                    $stmt->bindParam(":username", $username, PDO::PARAM_STR);
                    $stmt->bindParam(":peripherals", $peripherals, PDO::PARAM_STR);
                    $stmt->bindParam(":start_date", $start_date, PDO::PARAM_STR);
                    $stmt->bindParam(":end_date", $end_date, PDO::PARAM_STR);
                    $stmt->bindParam(":id", $id, PDO::PARAM_STR);

                    $result = $stmt->execute();

                    if ( $result ) { 
                       echo "gg";
                    } else {
                       echo "nope";
                    }

                    /*header('Location:index.php');*/
                }catch(PDOException $exception)  {
                    echo "Error: " . $exception->getMessage();
                }
            }
        }


    }catch( Exception $e ){
        exit( $e->getMessage() );
    }

?>

顺便说一句,在下面没有必要使用prepared statement,因为没有用户提供的变量,也没有sql注入的可能性

$sql = "SELECT * FROM utlansliste";

$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();

如果有 where 子句,那么它可能会有所不同......也许

更新 为了帮助调试 PDO 查询,我使用了以下函数 debugpdo ~ 给出了它的用法示例。

function debugpdo( $sql=false, $args=array() ){
    if( $sql && !empty( $args ) ){
        $params = array();
        $keys = array();
        foreach( $args as $placeholder => $value ){
            if( is_numeric( $value ) )$params[]=sprintf('set @%s=%d;',str_replace( ':', '', $placeholder ), $value );
            else $params[]=sprintf('set @%s="%s";',str_replace( ':', '', $placeholder), str_replace( '"',"'", $value ) );
            $keys[]=str_replace(':','@',$placeholder);
        }
        printf( 
            "<pre><h1>Copy & Paste this SQL into mySQL GUI Application</h1>%s\n\n%s;</pre>",
            implode( PHP_EOL, $params ),
            str_replace( array_keys( $args ), $keys, $sql )
        );
    }
}


$sql = "update `utlansliste` set `username`=:username, `peripherals`=:peripherals, `start_date`=:start_date, `end_date`=:end_date where `id`=:id";
$args = array(
    ':username'     =>  $username,
    ':peripherals'  =>  $peripherals,
    ':start_date'   =>  $start_date,
    ':end_date'     =>  $end_date,
    ':id'           =>  $id
);


/* To debug the sql, uncomment this and run... */
exit( debugpdo( $sql, $args ) );

/* code continues... */
$stmt = $conn->prepare( $sql );
$result = $stmt->execute( $args );

【讨论】:

  • 就好像它忽略了其他列,只返回id
  • 打印$row 工作正常,所有值都会显示。那么问题必须出在 SQL 查询本身。奇怪的是它根本不更新数据库。
  • Anywho,我非常感谢您为我提供的帮助。这比我写的更安全,从现在开始我将继续使用它。我也很感谢您不仅删除了我的代码,而是将其注释掉并解释了原因的 cmets。对我的学习过程有很大帮​​助。谢谢。如果我以后找到解决方案,我很可能会接受这个作为答案。
  • It is as if it's ignores the other columns and only returns the id ?你指的是select * from ...查询吗?
  • 不。我在 PDO 执行后echo $result;,它只返回$id
猜你喜欢
  • 2012-09-05
  • 2013-11-05
  • 2017-02-24
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 2015-02-10
  • 2017-10-20
  • 1970-01-01
相关资源
最近更新 更多