SQLite INSERT& SELECT不起作用

时间:2017-09-11 12:43:48

标签: php sqlite pdo

简单的事情:我的代码不起作用。 INSERT和SELECT都没有在我的PDO中工作。可能我有问题,但我不是代码大师,所以我需要你的帮助。

if (isset($_POST['submit']))
{
try 
    {
        $connection = new PDO('sqlite:../tracker.db');

        $name       = $_POST['name'];
        $unitsize   = $_POST['unitsize'];
        $line       = $_POST['line'];
        $mmr        = $_POST['mmr'];
        $lifespan   = $_POST['lifespan'];
        $connection->exec("INSERT INTO unit (name, unitsize, line, mmr, lifespan) 
        VALUES ('$name', '$unitsize', '$line', '$mmr', '$lifespan')");

        $new_unit = "SELECT unit_id
                     FROM unit
                     ORDER BY unit_id DESC
                     LIMIT 1";
        foreach ($connection->query($new_unit) as $row) {
        $id = $row['unit_id'];
        };

    }
    catch(PDOException $error) 
    {
        echo $error->getMessage();
    }
}

当然我知道没有记录的SELECT无法正常工作......但是我的乞丐的直觉说,它也可能带来一个错误。

PS:我知道,代码可能有点乱......对不起你的眼睛出血:(

编辑: 我想要实现的目标

  1. 有一个包含现有表格的数据库tracker.db(由SQLite浏览器确认)
  2. 我想从form插入一些数据。
  3. 插入后我想将我的DB中注册的最后一个unit_id变为变量$id(unit_id是AUTOINCREMENT和PRIMARY KEY)
  4. 这就是全部

1 个答案:

答案 0 :(得分:1)

好吧,通过查看您的代码,我可以说错误(至少有一个)位于以下部分:

  • 创建连接。
  • SQL语句 - 叛逆者(')。
  • 未捕获,失败信号,返回PDO::exec()或/和PDO::query()的值。您正在以适当的方式使用这两个函数来定义它们,但也许它们在失败时返回FALSE。您根本没有处理的情况,以及在php.net上对应的docus的“返回值”部分中说明的情况。

所以,因为您的代码存在的问题是您不知道它为什么不起作用,例如你没有收到任何错误或标志,我想向你展示一个完整的方法来使用错误报告+准备好的语句+验证+异常处理。请注意,如果您想编写安全可靠的PDO解决方案,则所有这四个元素都是必需的。更多的是,当你以适当的方式应用它们时,你总会知道问题(或更多)的位置。而且你在代码编写方面会有更高的效率,因为你不会再浪费时间(有时是几小时!)来发现错误。

此外,您如何构建代码取决于您自己。我在这里向您介绍了一个程序表单,您可以轻松地按照步骤操作。更好的形式是以面向对象的方式实现的形式。

建议:

  • 始终准备sql语句(读取this)以避免错误的预期数据库注入。在您的情况下,这意味着您必须使用PDO::prepare() + PDOStatement::execute()代替PDO::exec(请阅读PDO::exec on php.net中的“说明”)。
  • PDO是一个非常强大的数据访问抽象系统。但是,为了以正确的方式使用它,您需要始终阅读您正在使用的每个函数的文档,并且特别是“返回值”部分。这将是一个“必须”,因为有些情况下,如果失败,可以以bool形式返回值FALSE OR 可以抛出异常。然后必须妥善处理这些案件。例如,如果是PDO::prepare()
  

如果数据库服务器无法成功准备语句,   PDO :: prepare()返回FALSE或发出PDOException(取决于错误   处理)。

如果你有不明智的话,请随时提出任何问题。

祝你好运。

<?php

/*
 * Try to include files using statements 
 * only on the top of the page.
 */
require "../config.php";
require "../common.php";

/*
 * Set error reporting level and display errors on screen.
 * 
 * =============================================================
 * Put these two lines in a file to be included when you need to
 * activate error reporting, e.g the display of potential errors 
 * on screen.
 * =============================================================
 * Use it ONLY ON A DEVELOPMENT SYSTEM, NEVER ON PRODUCTION !!!
 * If you activate it on a live system, then the users will see
 * all the errors of your system. And you don't want this !!!
 * =============================================================
 */
error_reporting(E_ALL);
ini_set('display_errors', 1);

/*
 * ===================================================
 * Two functions used for automatically binding of the
 * input parameters. They are of course not mandatory, 
 * e.g. you can also bind your input parameters one 
 * by one without using these functions. But then
 * you'd have to validate the binding of each input
 * parameter one by one as well.
 *  
 * Put these two functions in a file to be included,
 * if you wish.
 * ===================================================
 */

/**
 * Get the name of an input parameter by its key in the bindings array.
 *  
 * @param int|string $key The key of the input parameter in the bindings array.
 * @return int|string The name of the input parameter.
 */
function getInputParameterName($key) {
    return is_int($key) ? ($key + 1) : (':' . ltrim($key, ':'));
}

/**
 * Get the PDO::PARAM_* constant, e.g the data type of an input parameter, by its value.
 *  
 * @param mixed $value Value of the input parameter.
 * @return int The PDO::PARAM_* constant.
 */
function getInputParameterDataType($value) {
    if (is_int($value)) {
        $dataType = PDO::PARAM_INT;
    } elseif (is_bool($value)) {
        $dataType = PDO::PARAM_BOOL;
    } else {
        $dataType = PDO::PARAM_STR;
    }

    return $dataType;
}

/*
 * ======================
 * Hier begins your code.
 * ======================
 */
try {
    // Read from HTTP POST.
    $name = $_POST['name'];
    $unitsize = $_POST['unitsize'];
    $line = $_POST['line'];
    $mmr = $_POST['mmr'];
    $lifespan = $_POST['lifespan'];

    // Create a PDO instance as db connection to sqlite.
    $connection = new PDO('sqlite:../tracker.db');

    // The sql statement - it will be prepared.
    $sql = 'INSERT INTO unit (
                name,
                unitsize,
                line,
                mmr,
                lifespan
            ) VALUES (
                :name,
                :unitsize,
                :line,
                :mmr,
                :lifespan
            )';

    // The input parameters list for the prepared sql statement.
    $bindings = array(
        ':name' => $name,
        ':unitsize' => $unitsize,
        ':line' => $line,
        ':mmr' => $mmr,
        ':lifespan' => $lifespan,
    );

    // Prepare the sql statement.
    $statement = $connection->prepare($sql);

    // Validate the preparing of the sql statement.
    if (!$statement) {
        throw new UnexpectedValueException('The sql statement could not be prepared!');
    }

    /*
     * Bind the input parameters to the prepared statement 
     * and validate the binding of the input parameters.
     * 
     * =================================================================
     * This part calls the two small functions from the top of the page:
     *  - getInputParameterName()
     *  - getInputParameterDataType()
     * =================================================================
     */
    foreach ($bindings as $key => $value) {
        // Read the name of the input parameter.
        $inputParameterName = getInputParameterName($key);

        // Read the data type of the input parameter.
        $inputParameterDataType = getInputParameterDataType($value);

        // Bind the input parameter to the prepared statement.
        $bound = $statement->bindValue($inputParameterName, $value, $inputParameterDataType);

        // Validate the binding.
        if (!$bound) {
            throw new UnexpectedValueException('An input parameter could not be bound!');
        }
    }

    // Execute the prepared statement.
    $executed = $statement->execute();

    // Validate the prepared statement execution.
    if (!$executed) {
        throw new UnexpectedValueException('The prepared statement could not be executed!');
    }

    /*
     * Get the id of the last inserted row.
     * You don't need to call a SELECT statement for it.
     */
    $lastInsertId = $connection->lastInsertId();

    /*
     * Display results. Use it like this, instead of a simple "echo".
     * In this form you can also print result arrays in an elegant
     * manner (like a fetched records list).
     * 
     * Theoretically, this statement, e.g. the presentation of results 
     * on screen, should happen outside this try-catch block (maybe in
     * a HTML part). That way you achieve a relative "separation of 
     * concerns": separation of the fetching of results from the 
     * presentation of them on screen.
     */
    echo '<pre>' . print_r($lastInsertId, TRUE) . '</pre>';

    // Close the db connecion.
    $connection = NULL;
} catch (PDOException $exc) {
    echo '<pre>' . print_r($exc, TRUE) . '</pre>';
    // echo $exc->getMessage();
    // $logger->log($exc);
    exit();
} catch (Exception $exc) {
    echo '<pre>' . print_r($exc, TRUE) . '</pre>';
    // echo $exc->getMessage();
    // $logger->log($exc);
    exit();
}
?>
相关问题