0

This is my code. But I have a problem.

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>";
   }
}

If someone for example types a letter into my form which is neither like the "Vorname" (= first name) nor like the "Nachname" (= last name) it displays nothing. But I want to have a message like "Sorry, but none of your letters match with the Names in the database".

How can you achieve that in this code?

Krisztián Balla
  • 19,223
  • 13
  • 68
  • 84
Jan Nick
  • 11
  • 3
  • I think that there is some problem with the if, because if $kundenach is only space and the second variable is empty, you add the first "where like". That can work better with [trim](http://php.net/manual/en/function.trim.php) function – L. Ros. Mar 11 '18 at 10:02
  • @Jenny O'Reilly: If you correct the indentation, then why stop there? How about completing the HTML table, and put the `

    ` tag outside the table, or prevent SQL-injection? There's no end of corrections you could make.

    – KIKO Software Mar 11 '18 at 10:05
  • 3
    @KIKOSoftware: Edit is only for syntax corrections. Anything else should be posted in comments or answers instead. It is way out of the scope of an edit to fix the logical problems of a question. – Krisztián Balla Mar 11 '18 at 10:07

2 Answers2

0

A remark: Your statement preparation is wrongly applied and looses its purpose: to avoid sql injection. No values should be directly passed into the sql statement. Instead, parameter markers (named or not) should be defined in the statement - as placeholders. For each of these markers the corresponding value must be passed either by calling the bindValue method, or the bindParam method, or by defining it as an element value in an array passed directly as argument to the PDOStatement::execute method.

Some suggestions:

  • You might also want to read this and this articles on how to apply error/exception handling and this article on applying prepared statements.
  • Avoid creating html code from PHP. Separate the php code from the html code.
  • Instead of mixing db fetching code with html code (like you did with while($ds = $sql->fetch()){...}), you should fetch all db data into an array (in the php code part) and iterate through it further (in the html code part).

Below is a code version in which I implement a solution to your task/question. I used my own naming/coding conventions (inclusive for the db table) though - so, as I would apply them in my own project.

Since you didn't specified which library you are using (PDO or mysqli) and because only PDO has the PDOStatement::errorInfo method, I deducted that you are using the PDO library. Therefore, my code uses 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 syntax

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;
Pang
  • 9,564
  • 146
  • 81
  • 122
PajuranCodes
  • 303
  • 3
  • 12
  • 43
-1

Count the rows (results) you fetch form the database.

If the count is zero then display the "no results found" message.

If there are results then take care of displaying the table header before you output the first row.

$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>";
}

Note that your code is unsafe as prone to sql injection.

Use Prepared Statements to inject user data into the query.

When you take user input and put it into a query after a LIKE statement then % wildcards must be escaped in the input string. See this question an the accepted answer.

Finally you should trim() $kundevor and $kundenach before using them; make sure to close the <table> html at some point, I put the code after the while loop. You have some fixes to take care of...

Paolo
  • 15,233
  • 27
  • 70
  • 91
  • Thanks a lot! But I won't change my code except for the "$count" thing cuz we are actually doing this for school and I wanna stick with the approach our teacher showed us =) – Jan Nick Mar 11 '18 at 11:40
  • Well but there is still a little problem. Even though there matches no latter with the Names, it still displays this part : echo"TitelISBNHerausgabedatum"; – Jan Nick Mar 11 '18 at 11:46
  • @JanNick see my edit. Now the table is not displayed at all if no matches are found – Paolo Mar 11 '18 at 11:59
  • But can you say that you want to "get the count of rows fetched" that early, if the code does it later on? – Jan Nick Mar 11 '18 at 12:03
  • @JanNick **the code changed**. before the edit I was counting the rows as they were fetched. Now I need to know the count before displaying the table header so I get it just after the query with `num_rows()` (and I do not count the rows in the while loop anymore) – Paolo Mar 11 '18 at 12:05
  • Ah okay, right :) But now it says this : Fatal error: Uncaught Error: Call to undefined method PDOStatement::num_rows() in C:\xampp\htdocs\Buchhandlung\gut.php:46 Stack trace: #0 {main} thrown in C:\xampp\htdocs\Buchhandlung\gut.php on line 46 – Jan Nick Mar 11 '18 at 12:09
  • 1
    @JanNick: didn't know you where using PDO. PDO doesn't have the `num_rows` method that's why you get the error. **Edited the code again** : now we're back to counting the rows again. Output the table header only before the first row. – Paolo Mar 11 '18 at 12:40
  • @JanNick I'm glad it worked. Do you mind flagging the answer as accepted? Thank you – Paolo Mar 11 '18 at 13:25
  • Did it. Apprechiate your help :) – Jan Nick Mar 11 '18 at 14:11