【问题标题】:How to display error message when nothing matches with the database?数据库不匹配时如何显示错误消息?
【发布时间】:2018-08-19 11:57:24
【问题描述】:

这是我的代码。但我有一个问题。

if ($kundevor!="" or $kundenach!="")
{
   if ($kundevor=="")
   {
      $kundezusatz=" WHERE Nachname LIKE '$kundenach%'";
   }
   else if ($kundenach=="")
   {
      $kundezusatz=" WHERE Vorname LIKE '$kundevor%'";
   }
   else
   {
      $kundezusatz=" WHERE (Vorname LIKE '$kundevor%') OR (Nachname LIKE '$kundenach%')";
   }

   $sql = $dbh->prepare ("SELECT Nachname, Vorname FROM tblkunden $kundezusatz ");
   $sql->execute() or die("SQL Fehler in: ".$sql->queryString." <br /> ".$sql->errorInfo()[2]);

   echo "<table>";
   echo '<p class="abfrage2">Abfrage 3:</p>';
   echo"<tr><th>Nachname</th><th>Vorname</th></tr>";

   while($ds = $sql->fetch())
   {
       echo "<tr><td>$ds[Nachname]</td><td>$ds[Vorname]</td></tr>";
   }
}

例如,如果有人在我的表单中键入一个既不像“Vorname”(= 名字)也不像“Nachname”(= 姓氏)的字母,它不会显示任何内容。但我想收到类似“抱歉,您的字母与数据库中的姓名都不匹配”这样的消息。

如何在这段代码中实现这一点?

【问题讨论】:

  • 我认为if有一些问题,因为如果$kundenach只有空格并且第二个变量为空,则添加第一个“where like”。使用trim 函数可以更好地工作
  • @Jenny O'Reilly:如果你纠正了缩进,那为什么要停在那里?完成HTML表格,将&lt;p&gt;标签放在表格之外,或者防止SQL注入如何?您可以进行无止境的更正。
  • @KIKOSoftware:编辑仅用于语法更正。其他任何内容都应发布在 cmets 或答案中。修复问题的逻辑问题超出了编辑的范围。

标签: php html mysql pdo


【解决方案1】:

备注:您的陈述准备被错误地应用并且失去了目的:避免sql injection。不应将任何值直接传递到 sql 语句中。相反,parameter markers(已命名或未命名)应在语句中定义 - 作为占位符。对于这些标记中的每一个,必须通过调用bindValue 方法或bindParam 方法来传递相应的值,或者将其定义为数组中的元素值,直接作为参数传递给PDOStatement::execute 方法。

一些建议:

  • 您可能还想阅读有关如何应用错误/异常处理的 thisthis 文章以及有关应用准备好的语句的 this 文章。
  • 避免从 PHP 创建 html 代码。将 php 代码与 html 代码分开。
  • 不应将 db 获取代码与 html 代码混合(就像您对 while($ds = $sql-&gt;fetch()){...} 所做的那样),您应该将所有 db 数据获取到一个数组中(在 php 代码部分中)并进一步迭代它(在 html 代码部分中) .

以下是我为您的任务/问题实施解决方案的代码版本。不过,我使用了自己的命名/编码约定(包括 db 表) - 所以,我会将它们应用到我自己的项目中。

由于您没有指定您使用的是哪个库(PDOmysqli),并且因为只有 PDO 具有 PDOStatement::errorInfo方法,我推断您使用的是 PDO 库。因此,我的代码使用 PDO

kunden.php

<?php
require 'connection.php';

if (isset($_POST['submit'])) {
    $nachname = isset($_POST['nachname']) ? $_POST['nachname'] : '';
    $vorname = isset($_POST['vorname']) ? $_POST['vorname'] : '';

    if (empty($nachname) && empty($vorname)) {
        $errors[] = 'Please provide either the first name, or the last name, or both.';
    }

    if (!isset($errors)) {
        // Array used for creating the WHERE conditions in the sql statement.
        $whereConditions = [];

        /*
         * Used for injecting the proper values for the named parameter markers found 
         * in the sql statement. It is passed as argument to the PDOStatement::execute method.
         */
        $inputParameters = [];

        if (!empty($nachname)) {
            $whereConditions[] = 'nachname LIKE :nachname';
            $inputParameters[] = '%' . $nachname . '%';
        }

        if (!empty($vorname)) {
            $whereConditions[] = 'vorname LIKE :vorname';
            $inputParameters[] = '%' . $vorname . '%';
        }

        $sql = sprintf(
                'SELECT kunde_id, nachname, vorname FROM kunden WHERE %s'
                , implode(' OR ', $whereConditions)
        );

        $statement = $connection->prepare($sql);
        $statement->execute($inputParameters);

        $kunden = $statement->fetchAll(PDO::FETCH_ASSOC);

        if (!$kunden) {
            $errors[] = 'No clients found for your request.';
        }
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo</title>

        <script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>

        <script type="text/javascript">
            $(document).ready(function () {
                $('#nachname').focus();
            });
        </script>

        <style type="text/css">
            body {
                padding: 30px;
            }

            label {
                /*display: block;*/
                font-weight: 400;
            }

            input[type="text"] {
                display: block;
                margin-bottom: 20px;
            }

            button {
                display: block;
                padding: 7px 10px;
                background-color: #8daf15;
                color: #fff;
                border: none;
            }

            .messages {
                margin-bottom: 20px;
            }

            .messages .error {
                color: #c00;
            }

            .kunden-list {
                margin-top: 20px;
                border-collapse: separate;
            }

            .kunden-list thead th {
                padding: 10px;
                background-color: #ccc;
            }

            .kunden-list tbody td {
                padding: 10px;
            }
        </style>
    </head>
    <body>

        <div class="messages">
            <?php
            if (isset($errors)) {
                foreach ($errors as $error) {
                    ?>
                    <div class="error">
                        <?php echo $error; ?>
                    </div>
                    <?php
                }
            }
            ?>
        </div>

        <div class="form-container">
            <form action="" method="post">
                <label for="nachname">Nachname:</label>
                <input type="text" id="nachname" name="nachname" value="<?php echo isset($nachname) ? $nachname : ''; ?>">

                <label for="vorname">Vorname:</label>
                <input type="text" id="vorname" name="vorname" value="<?php echo isset($vorname) ? $vorname : ''; ?>">

                <button type="submit" name="submit" value="submit">
                    Senden
                </button>
            </form>
        </div>

        <?php
        if (isset($kunden) && $kunden) {
            ?>
            <table class="kunden-list">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Nachname</th>
                        <th>Vorname</th>
                    </tr>
                </thead>
                <tbody>
                    <?php
                    foreach ($kunden as $kunde) {
                        $kundeId = $kunde['kunde_id'];
                        $nachname = $kunde['nachname'];
                        $vorname = $kunde['vorname'];
                        ?>
                        <tr>
                            <td><?php echo $kundeId; ?></td>
                            <td><?php echo $nachname; ?></td>
                            <td><?php echo $vorname; ?></td>
                        </tr>
                        <?php
                    }
                    ?>
                </tbody>
            </table>
            <?php
        }
        ?>

    </body>
</html>

connection.php

<?php

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'yourDb');
define('USERNAME', 'yourUser');
define('PASSWORD', 'yourPassword');
define('CHARSET', 'utf8');

/*
 * Create a PDO instance as db connection to db.
 * 
 * @link http://php.net/manual/en/class.pdo.php
 * @link http://php.net/manual/en/pdo.constants.php
 * @link http://php.net/manual/en/pdo.error-handling.php
 * @link http://php.net/manual/en/pdo.connections.php
 */
$connection = new PDO(
        sprintf('mysql:host=%s;port=%s;dbname=%s;charset=%s', HOST, PORT, DATABASE, CHARSET)
        , USERNAME
        , PASSWORD
        , [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => FALSE,
    PDO::ATTR_PERSISTENT => FALSE,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
);

创建表语法

CREATE TABLE `kunden` (
  `kunde_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `nachname` varchar(100) DEFAULT NULL,
  `vorname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`kunde_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

【讨论】:

  • 谢谢,@YourCommonSense。老实说,我有点惊讶,因为反对票来得很快。
【解决方案2】:

计算您从数据库中获取的行(结果)。

如果计数为零,则显示“未找到结果”消息。

如果有结果,则在输出第一行之前注意显示表头。

$count = 0; // This keeps track of the rows fetched

while($ds = $sql->fetch())
{
    // Before the first row let's put the table header

    if( $count === 0 )
    {
        echo "<table>";
        echo '<p class="abfrage2">Abfrage 3:</p>';
        echo"<tr><th>Nachname</th><th>Vorname</th></tr>";
    }

    // Output the row

    echo "<tr><td>$ds[Nachname]</td><td>$ds[Vorname]</td></tr>";

    // Update the row count

    $count++;
}

// No rows/results? display the message
// Otherwise close the table

if( $count === 0 )
{
    // Display "no matches" message ex:
    echo "<div class='some-class'>Sorry, but none of your letters match with the Names in the database</div>";  
}
else
{
    echo "</table>";
}

请注意,您的代码不安全,容易受到 sql 注入。

使用Prepared Statements 将用户数据注入到查询中。

当您在 LIKE 语句之后接受用户输入并将其放入查询中时,必须在输入字符串中转义 % 通配符。请参阅this question 接受的答案。

最后你应该trim()$kundevor$kundenach在使用它们之前;确保在某个时候关闭 &lt;table&gt; html,我将代码放在 while 循环之后。您需要解决一些问题...

【讨论】:

  • 非常感谢!但我不会更改我的代码,除了“$count”这件事因为我们实际上是为学校做的,我想坚持我们老师教给我们的方法 =)
  • 嗯,但还是有一点小问题。即使没有与名称匹配的后者,它仍然显示这部分:echo" Titel ISBN Herausgabedatum " ;
  • @JanNick 看到我的编辑。现在,如果没有找到匹配项,则表根本不会显示
  • 但是如果代码稍后执行,您能说您想尽早“获取获取的行数”吗?
  • @JanNick:不知道你在哪里使用 PDO。 PDO 没有 num_rows 方法,这就是您收到错误的原因。 再次编辑代码:现在我们又开始计算行数了。仅在第一行之前输出表头。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 1970-01-01
  • 1970-01-01
  • 2016-05-21
  • 1970-01-01
  • 2022-07-06
相关资源
最近更新 更多