【问题标题】:PHP MySQLi issue with prepared statements causing error [duplicate]PHP MySQLi问题与准备好的语句导致错误[重复]
【发布时间】:2016-06-07 14:57:20
【问题描述】:

我在尝试让 php 脚本为我的网站工作时遇到问题,我可以在其中向我的在线商店添加新项目。

我遇到问题的代码 sn-p 是这样的:

$error = '';
$success = '';

if(isset($_POST['submit']))
{
    define("MAX_SIZE", "4096");

    $errors=0;

    $name = $_POST['name'];
    $price = $_POST['price'];
    $desc = filter_var($_POST['desc'], FILTER_SANITIZE_STRING);
    $image = $_FILES['image']['name'];
    $uploadedfile = $_FILES['image']['tmp_name'];

    if($image)
    {
        $filename = stripslashes($_FILES['image']['name']);
        $extension = getExtension($filename);
        $extension = strtolower($extension);
        if(($extension != "jpg") && ($extension != "jpeg") && ($extension != "png") && ($extension != "gif"))
        {
            $error .= '<p class="error">The file must be one of the following file types(jpg|jpeg|png|gif)</p>';
            $errors=1;
        }
        else
        {
            $size=filesize($_FILES['image']['tmp_name']);

            if($size > MAX_SIZE*1024)
            {
                $error .= '<p class="error">The file cannot exceed 4MB in size.</p>';
                $errors=1;
            }

            if($extension=="jpg" || $extension=="jpeg")
            {
                $uploadedfile = $_FILES['image']['tmp_name'];
                $src = imagecreatefromjpeg($uploadedfile);
            }
            else if($extension=="png")
            {
                $uploadedfile = $_FILES['image']['tmp_name'];
                $src = imagecreatefrompng($uploadedfile);
            }
            else
            {
                $src = imagecreatefromgif($uploadedfile);
            }

            list($width,$height)=getimagesize($uploadedfile);

            $newwidth=128;
            $newheight=128;
            $tmp=imagecreatetruecolor($newwidth,$newheight);

            imagecopyresampled($tmp,$src,0,0,0,0,$newwidth,$newheight,$width,$height);

            $filename = "../store/images/" . $_FILES['image']['name'];

            imagejpeg($tmp,$filename,100);

            $fname = $_FILES['image']['name'];

            imagedestroy($src);
            imagedestroy($tmp);
        }
    }

    if($name == '')
    {
        $error .= '<p class="error">You must enter a name for the product.</p>';
    }

    if(!preg_match('/^[a-zA-Z\s]+$/', $name))
    {
        $error .= '<p class="error">The product name can only contain letters and spaces.</p>';
    }

    if($_POST['type'] == 'KIT')
    {
        $type = 'KIT';
    }
    else if($_POST['type'] == 'VIP')
    {
        $type = 'VIP';
    }
    else if($_POST['type'] == 'OTHER')
    {
        $type = 'OTHER';
    }
    else
    {
        $error .= '<p class="error">You must select a valid type for the product.</p>';
    }

    if($price == '')
    {
        $error .= '<p class="error">You must enter a price for the product.</p>';
    }

    if(!preg_match('/^\d+(:?[.]\d{2})$/', $price))
    {
        $error .= '<p class="error">You must enter a valid price for the product.</p>';
    }

    if($desc == '')
    {
        $error .= '<p class="error">You must enter a description for the product.</p>';
    }

    $stmt = $db->prepare("SELECT * FROM products WHERE name = ?");
    if($stmt)
    {
        $stmt->bind_param('s',$name);
        $stmt->execute();

        if($stmt->num_rows > 0)
        {
            $error .= '<p class="error">This product already exists. Please choose a different name.</p>';
        }
    }
    else
    {
        $error .= '<p class="error">An error occurred at line 135. Please contact the site administrator.</p>';
    }

    if(empty($error) && !$errors)
    {
        $stmt = $db->prepare("INSERT INTO products (name, image, price, prod_desc, type) VALUES ( ?, ?, ?, ?, ? )");

        if($stmt)
        {
            $stmt->bind_param('sssss', $name, $fname, $price, $desc, $type);

            if($stmt->execute())
            {
                $success .= '<p class="success">Product added successfully.</p>';
            }
            else
            {
                $error .= '<p class="error">An error occured at line 158. Please contact the site administrator.</p>';
            }
        }
        else
        {
            $error .= '<p class="error">An error occured at line 154. Please contact the site administrator.</p>';
        }
    }
}

我遇到问题的部分是 if(empty($error) && !&errors) 语句之后的 if($stmt) 块。

根据我用于 PHP 本身和 MySQL 插入查询的每个语法检查器,它们都没有报告错误。但它不断吐出第 154 行的错误,我不知道为什么。我已经通过回显它们验证了这些变量是否已从表单中正确存储,并且我还验证了 mysql 表的列确实存在,并且拼写正确。

这开始让我抓狂了,当我尝试使用 $stmt->error 或 $db->e​​rror 回显 mysql 错误时,它返回空白,没有列出任何错误。

我得到的唯一结果是执行 mysqli_errno($db) 时返回 0。

有谁知道这段代码有什么问题,或者为什么它不起作用?

表单的 HTML 标记:

<div id="form">
<form action="" method="post" enctype="multipart/form-data">
<table>
<th colspan="2">Add to Store</th>
<tr>
<td colspan="2">
<p>Please use the form below to add items to the store.</p>
<?php

if($error)
{
    echo $error;
}

if($success)
{
    echo $success;
}

?>
<hr>
<tr>
<td><label for="name">Product Name:</label></td>
<td><input type="text" name="name" id="name" value="<?php if(isset($name)) { echo $name; } else { echo ''; } ?>" /></td>
</tr>

<tr>
<td><label for="price">Product Price:</label></td>
<td><input type="text" name="price" id="price" size="6" maxlength="6" value="<?php if(isset($price)) { echo $price; } else { echo ''; } ?>" /></td>
</tr>

<tr>
<td><label for="image">Product Image:</label></td>
<td><input type="file" name="image" id="image" /><br /><small>File must be 128x128 pixels, and no larger than 4MB.</small></td>
</tr>

<tr>
<td><label for="type">Product Type:</label></td>
<td>
<select name="type">
<option value="VIP">VIP Package</option>
<option value="KIT">Donator Kit</option>
<option value="OTHER">Other</option>
</select>
</td>
</tr>

<tr>
<td colspan="2"><label for="desc">Product Description:</label></td>
</tr>
<tr>
<td colspan="2"><textarea name="desc" style="width: 500px; height:250px;"><?php if(isset($desc)) { echo $desc; } ?></textarea></td>
</tr>

<tr>
<td colspan="2"><input type="submit" name="submit" id="submit" value="Add Product" /></td>
</tr>

</table>
</form>
</div>

【问题讨论】:

  • 吐出什么错误?第 154 行是什么?
  • 第 154 行涉及代码底部以下行之后的 if($stmt) 块: $stmt = $db->prepare("INSERT INTO products (name, image, price, prod_desc,类型)值(?,?,?,?,?)“);除了该消息之外,没有吐出任何错误。
  • 检查您的错误日志中是否存在 实际 错误。 $stmt 有问题,表示您的查询有问题。
  • 我必须联系我的主机,因为我无权访问服务器日志。
  • 在打开&lt;?php标签error_reporting(E_ALL); ini_set('display_errors', 1);后立即将错误报告添加到文件顶部

标签: php mysql mysqli prepared-statement


【解决方案1】:

您从未获取任何结果,因此num_rows 将始终为零。有一个简单的补丁,使用store_result()

$stmt->bind_param('s',$name);
$stmt->execute();
$stmt->store_result();

if($stmt->num_rows > 0)
{
    $error .= '<p class="error">This product already exists. Please choose a different name.</p>';
}

但是,您的代码需要的远不止这些。你真的应该重写它并避免嵌套if 语句。也使用适当的错误报告。

【讨论】:

    【解决方案2】:

    所以在头疼之后,我设法找到了解决方法。

    问题的根源在这里:

    $stmt = $db->prepare("SELECT * FROM products WHERE name = ?");
        if($stmt)
        {
            $stmt->bind_param('s',$name);
            $stmt->execute();
    
            if($stmt->num_rows > 0)
            {
                $error .= '<p class="error">This product already exists. Please choose a different name.</p>';
            }
        }
        else
        {
            $error .= '<p class="error">An error occurred at line 135. Please contact the site administrator.</p>';
        }
    

    将其更改为以下内容后:

    $sql = "SELECT * FROM products WHERE name = '".$name."' LIMIT 1";
        $result = $db->query($sql);
    
        if(is_object($result) && $result->num_rows == 1)
        {
            $error .= '<p class="error">This product already exists. Please choose a different name.</p>';
        }
    

    一切都很开心,现在可以正常工作了。仍然不确定为什么原始代码不起作用,但它现在起作用了。感谢大家的帮助。

    【讨论】:

    • 放弃准备好的语句使这项工作有效吗?这真是违反直觉。
    • 是的,不知道为什么准备好的语句不起作用,但未准备好的语句起作用。
    • 不要因为你犯了一个简单的错误就放弃准备好的语句。要解决这个问题,您只需在声明中致电store_result()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多