好的,我刚刚开始了解 MySQLi 准备好的语句。这对我来说是一大步,因为我对 MySQL 和 PHP 还是很陌生,所以我对这个概念的理解非常脆弱(可能需要一个小时左右),所以你的答案必须用类似的措辞表达,对此感到抱歉.
我想知道的是我是否正确地编写了准备好的语句。没有什么比学习一种不正确的方法并习惯它,从而导致整个项目的编码效率低下更糟糕的了。
要点:我有一个注册用户的函数,然后返回插入的 ID,因此它是用户的引用 ID。
之前,我只是简单地查询数据库,尽管使用了 mysql_real_escape_string() 和类似的安全措施,但我被告知存在安全风险。
现在,它看起来像这样:(为了这个问题,假设所有引用的变量都已定义,绑定(bind)参数是字符串,并且所有被调用的函数都存在并且正在工作)。
function registerUser($username, $fname, $email, $password, $region, $activation) {
$uniqueSalt = uniqueSalt();
$password = sha1($uniqueSalt . $password);
$mysqli = mysqli_connect('localhost', 'root', '', 'database');
if ($stmt = $mysqli->prepare("INSERT INTO `users` VALUES('', ?, ?, ?, ?, '$password', '$uniqueSalt', '$activation')") ) {
$stmt->bind_param("ssss", $username, $fname, $email, $region);
$stmt->execute();
$stmt->close();
} else {
echo 'error preparing statement';
}
return mysqli_insert_id($mysqli);
}
这似乎有效,但是:
1) 这是执行准备好的语句的正确语法吗?
2) 我将这个函数所在的文件(称为 function.php)与另一个名为 init.php 的文件包含在一起,该文件之前定义了变量 $mysqli。我发现如果我不包括
$mysqli = mysqli_connect('localhost', 'root', '', 'database');
我会收到一个错误。为什么我必须在函数内部重新定义它?
3) 当我之前在使用准备语句之前结束函数时,使用 return mysql_insert_id() 效果很好,现在我发现我必须使用 mysqli_insert_id($mysqli) 。
如果我不在括号内包含 $mysqli,我会得到错误 mysqli_insert_id() expects exactly 1 parameter, 0 given。为什么会这样,为什么与我之前的不同?
干杯, 卢克。
最佳答案
您的用法没有多大意义。来自PHP Manual Example :
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
将此与您的使用情况进行比较:
$stmt = $mysqli->prepare("INSERT INTO `users` VALUES('', ?, ?, ?, ?, '$password', '$uniqueSalt', '$activation')");
$stmt->bind_param("ssss", $username, $fname, $email, $region);
注意到什么奇怪的事了吗?手册示例使用 ? 作为占位符,然后您可以在其中使用 ->bind_param() 创建替换集。所以我相信你的例子应该是:
$stmt = $mysqli->prepare("INSERT INTO `users` VALUES('', ?, ?, ?, ?, ?, ?, ?)");
$stmt->bind_param("sssssss", $username, $fname, $email, $region, $password, $uniqueSalt, $activation);
不知道 $activation 是数字还是字符串值。 (另外,我建议在 INSERT 查询中使用列名而不是省略它们。)
现在,在许多情况下,您所做的应该有效,因为您正在创建单个 use 语句并使用变量扩展来插入 $pass、$uniqueSalt、$activation 到正在准备的查询字符串中。如果您在查询中放入一个或多个变量时不小心有一个 ',则不会出现这种情况,这些变量应该被参数化(使用 ->bind_param()),或者使用 mysqli_real_escape_string()。然而,混合使用这些方法是一种糟糕的做法,并且违背了使用准备好的语句的目的。没有理由做前几个,但不做后几个。
您的$mysqli 变量是"out of scope"当你在函数中调用它时,如果它是全局定义的,因此当它不可用时,你不能使用它,除非你导入它或在本地(在函数中)创建另一个。您可以在函数内使用 global $mysqli; 语法导入它(只要它是全局创建的,而不是在另一个函数中本地创建的)。
这与 #2 是同一个问题。请参阅:http://php.net/manual/en/mysqli.insert-id.php
我的建议是使用 PDO而不是 mysql_/mysqli_ 函数。
关于php - 在函数中编写 MySQLi 准备语句的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8639760/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun