Php 修改的PDO&;lastInsertId()
这只是一种新的PDO形式,我并不完全理解。我知道类似的问题已经在这个网站上解决了。但是我被这个新的(对我来说是新的)基于类的PDO系统所吸引。它圆滑简洁。我把一切都弄清楚了,所有的动态用户数据都插入到数据库中了。但是,我不知道如何使用这种特殊样式包含lastInsertId()。用户没有输入post-id&我不能使用GET-request,这是我通常获取post-id的方式 在多次尝试失败后,我所拥有的是我所能做的最好的。很明显,它不起作用。如果您对我的代码有任何修改,我们将不胜感激 以下是数据库类: functions.phpPhp 修改的PDO&;lastInsertId(),php,database,class,pdo,last-insert-id,Php,Database,Class,Pdo,Last Insert Id,这只是一种新的PDO形式,我并不完全理解。我知道类似的问题已经在这个网站上解决了。但是我被这个新的(对我来说是新的)基于类的PDO系统所吸引。它圆滑简洁。我把一切都弄清楚了,所有的动态用户数据都插入到数据库中了。但是,我不知道如何使用这种特殊样式包含lastInsertId()。用户没有输入post-id&我不能使用GET-request,这是我通常获取post-id的方式 在多次尝试失败后,我所拥有的是我所能做的最好的。很明显,它不起作用。如果您对我的代码有任何修改,我们将不胜感激 以下是数据
class DB{
private static function connect(){
$pdo = new PDO('mysql:host=localhost;dbname=poetionpics;charset=utf8', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
public static function query($query, $params = array()){
$stmt = self::connect()->prepare($query);
$stmt->execute($params);
if(explode(' ', $query)[0] == 'SELECT'){
$data = $stmt->fetchALL();
return $data;
}
}
public function lastInsertId(){
$pdo = new PDO('mysql:host=localhost;dbname=poetionpics;charset=utf8', 'root', '');
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
return $pdo->lastInsertId();
}
}
这是我的插入代码:
action.php
for($count = 0; $count < count($_POST['hidden_post_title']); $count++){
$post_title = (isset($_POST['hidden_post_title'][$count])) ? strip_tags($_POST['hidden_post_title'][$count]) : NULL;
$post_desc = (isset($_POST['hidden_post_desc'][$count])) ? strip_tags($_POST['hidden_post_desc'][$count]) : NULL;
$newvidurl = (isset($_POST['hidden_vid_url'][$count])) ? strip_tags($_POST['hidden_vid_url'][$count]) : NULL;
$url_1 = (isset($_POST['url1_hidden_id'][$count])) ? strip_tags($_POST['url1_hidden_id'][$count]) : NULL;
$url_2 = (isset($_POST['url2_hidden_id'][$count])) ? strip_tags($_POST['url2_hidden_id'][$count]) : NULL;
DB::query('INSERT INTO cloudbook_posts VALUES (\'\', :post_title, :post_desc)',
array(':post_title'=>$post_title, ':post_desc'=>$post_desc));
//This is possibly problematic code or wrong location....
$postid = DB::lastInsertId('SELECT id FROM cloudbook_posts WHERE id=:id',
array(':id'=>$_POST['id']))[0]['id'];
//End problematic code
DB::query('INSERT INTO vid_info VALUES (\'\', :newvidurl, :postid)',
array(':newvidurl'=>$newvidurl, ':postid'=>$postid));
DB::query('INSERT INTO url_1 VALUES (\'\', :url_1, :postid)',
array(':url_1'=>$url_1, ':postid'=>$post_id));
}
echo str_replace(array('hidden_post_title', 'hidden_post_desc', 'url1_hidden_id', 'url2_hidden_id', '{', '}', '"', ',', ':'), '',
htmlspecialchars(json_encode($result), ENT_NOQUOTES));
?>
我想要的是:
vid_info table
id | newvidurl | postid
69 | some user data | $postid (see action.php for variable value)
这确实是一个有趣的案例
lastInsertId()
问题是设计不当(部分是cargo cult复制粘贴的代码)的直接后果
这种“PDO的新形式”只是一种展示(如此普遍,以至于我甚至写了一篇关于它的文章)。其中一个问题是:
您必须了解,每个PDO实例都会创建到DB服务器的不同连接。因此,永远不要在每个函数中打开和关闭新连接。因为它会大大降低您的PHP速度,并且不允许您使用某些只能在同一连接中使用的DB功能,即事务或获取插入id
因此,现在您可以看出问题来自于在lastInsertId()
方法中创建了一个新连接这一事实。解决方法是始终保持相同的连接
有两种方法可以解决这个问题:一种是目前更简单的方法,一种是将来更难实现的方法,另一种是更难实现的方法,但这会降低代码的耦合性,更容易维护。在我的另一篇文章中解释了这两个问题,这篇文章介绍了如何创建这样一个“圆滑而简洁的基于类的PDO系统”(但基于在堆栈溢出方面的大量经验和问题)
最合适的解决方案是在静态的东西产生的时候得到它。因此,最好的解决方案是创建一个常规类,然后将其传递给所有代码。在这种情况下,对$this->dbh
的所有调用都有意义,并指向同一个PDO实例。在这种情况下,您必须将DB:query()
符号更改为$DB->query()
然而,本文中的代码使用了不同的扩展PDO的方法。您的方法更好,所以让我们将代码重写为常规类
class DB{
public function __construct()
{
$host = '127.0.0.1';
$db = 'poetionpics';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
$options = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_EMULATE_PREPARES => false,
];
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
try {
$pdo = new \PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
}
public function query($query, $params = array())
{
$stmt = $this->pdo->prepare($query);
$stmt->execute($params);
return $stmt;
}
public function lastInsertId()
{
return $this->pdo->lastInsertId();
}
}
但请记住,由于您不是在扩展PDO,所以必须复制类中的所有PDO方法
如果当时放弃这种圆滑方法的想法让您无法忍受,那么您可以使用静态方法,但是可以为您保留一个PDO实例。在上面链接的文章中,同样有两种解释方法
在拥有适当的DB类之后,我们可以重写您的查询
$db = new DB();
$sql = 'INSERT INTO cloudbook_posts VALUES (null, :post_title, :post_desc)';
$db->query($sql, ['post_title'=>$post_title, 'post_desc'=>$post_desc]);
$postid = $db->lastInsertId();
$sql = 'INSERT INTO vid_info VALUES (null, :newvidurl, :postid)';
$db->query($sql, ['newvidurl'=>$newvidurl, 'postid'=>$postid]);
[0]['id']
的目的是什么?您使用的是lastInsertId
,但您不是在插入,而是在尝试选择。您似乎想得太多了。没有理由在sql查询中选择最后一个insert id——php会为您做这件事。您几乎只需要使用$postid=$db->lastInsertId()代码>或者您已经使用它>代码> $POSITD= PDO::LaSTReDistId()/<代码>这是一个很好的工作,但请考虑阅读我的文章。并且lastInsertId()方法名称是绝对不正确和误导的。至少调用它just insert()Dharman,[0]['id]的目的是从“cloudbook_posts”表中的MySql数据库中选择id字段。我没有显示cloudbook|u posts表b/c,这个问题没有必要,但是,按顺序,posts表是id | post|title | post|desc…..哦,谢谢,YCS!在没有意识到你给了我这个答案的情况下,我在阅读了你的文章后在文章的页面上问了一个问题。请忽略这个问题。这太完美了!!这是我问过的第一个问题,所以我还是习惯了一切。我现在就去批准你的回答,我的朋友。
$db = new DB();
$sql = 'INSERT INTO cloudbook_posts VALUES (null, :post_title, :post_desc)';
$db->query($sql, ['post_title'=>$post_title, 'post_desc'=>$post_desc]);
$postid = $db->lastInsertId();
$sql = 'INSERT INTO vid_info VALUES (null, :newvidurl, :postid)';
$db->query($sql, ['newvidurl'=>$newvidurl, 'postid'=>$postid]);