好吧,通过查看您的代码,我可以说错误(至少一个)在于以下部分:
- 连接创建。
- SQL 语句 - 撇号 (')。
- 未捕获,故障信号,返回值
PDO::exec() 或/和PDO::query()。关于它们的定义,您正在以正确的方式使用这两个函数,但它们可能在失败时返回 FALSE。您根本没有处理的情况,并且在 php.net 上相应文档的“返回值”部分中进行了说明。
所以,因为您的代码的问题是您不知道它为什么不起作用,例如您没有收到任何错误或迹象,我想向您展示使用错误报告 + 准备好的语句 + 验证 + 异常处理的完整方法。请注意,如果您想编写安全可靠的 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();
}
?>