我从phpdelusions借用了以下包装类:
class DB
{
protected static $instance = null;
public static function instance() {
if (self::$instance === null) {
$opt = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_CLASS,
PDO::ATTR_EMULATE_PREPARES => FALSE,
);
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR;
self::$instance = new PDO($dsn, DB_USER, DB_PASS, $opt);
}
return self::$instance;
}
public static function __callStatic($method, $args) {
return call_user_func_array(array(self::instance(), $method), $args);
}
public static function run($sql, $args = []) {
$stmt = self::instance()->prepare($sql);
$stmt->execute($args);
return $stmt;
}
}
我还设置了users
表格id
,name
和password
。现在,我正在尝试将表中的第一个行作为类User
的对象(假设某个地方有一个require_once 'User.php'
,加载模型类):
$stmt = DB::run('SELECT * FROM users LIMIT 1');
$user = $stmt->fetchAll(PDO::FETCH_CLASS, 'User'); // Array ( [0] => User Object ( ... ) )
它有效,但
fetchAll
总是返回一个数组,如果上面的查询以某种方式被破坏,结果可能是User
个可变对象,而目标是始终获得一个,即第一个对象,即使查询返回多行。PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_CLASS
instance()
方法中的DB
将默认提取样式设置为CLASS,但我始终必须在{{1}中指定PDO::FETCH_CLASS
我认为这是多余的。fetchAll
,因为您永远不知道$first = (is_array($user)) ? $user[0] : null;
是否为空。只获取第一个对象并获得合法的行($user
对象)或仅为null将更容易。如果您的目标是获得一个对象,那么返回阵列是没有意义的吗?所以我尝试将User
改为fetchAll
,但有多种变体,这就是我所得到的:
fetch
是否可以仅使用$user = $stmt->fetch('User'); // # 1, FETCH_MODE is already CLASS, but no...
// Warning: PDOStatement::fetch() expects parameter 1 to be integer, string given
$user = $stmt->fetch(PDO::FETCH_CLASS, 'User'); // # 2
// Warning: PDOStatement::fetch() expects parameter 2 to be integer, string given
$user = $stmt->fetch(); // #3
// Uncaught PDOException: SQLSTATE[HY000]: General error: No fetch class specified
// so how do you specify it then with fetch() ???
将第一行作为给定类的对象获取?或者我别无选择,只能写fetch
,然后运行$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');
?
答案 0 :(得分:2)
由于您只想要一个对象,我完全理解您不想使用fetchAll()
的原因。但既然你想要一个,为什么不使用fetchObject()
?
因为它完全能够在while循环中使用。它就像对象的fetch()
一样。
返回所需类的实例,其属性名称对应于列名称,如果失败则返回FALSE。
public mixed PDOStatement::fetchObject ([ string $class_name = "stdClass" [, array $ctor_args ]] )
示例:
class User{
protected $data = [];
public function __get(string $key){
return $this->data[$key];
}
public function __set(string $key, $value){
$this->data[$key] = $value;
}
public function __construct($a, $b, $c){
echo $a, $b, $c;
print_r($this->data);
}
}
$stmt = DB::run('SELECT id, name FROM users LIMIT 1');
if($user = $stmt->fetchObject('User', [1, 2, 3])){
echo $user->id;
}
答案 1 :(得分:2)
如我所见,您正在使用我的PDO包装器。所以你只需点击一下右边的答案,因为有一篇姊妹文章Fetching objects with PDO:)
因此,要使用fetch(),您需要额外的函数调用
$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');
$user = $stmt->fetch();
但是,正如在另一个答案中正确地说的那样,fetchObject()
在任何一种情况下都更好:
$user = DB::run('SELECT * FROM users LIMIT 1')->fetchObject('User');