如何解决既然不赞成使用fetchAll和FetchMode,如何将结果提取到自定义对象中?
在一些现有代码上,我有以下声明(经过相当长时间的查询构建练习):
return $statement->fetchAll(
DBAL\FetchMode::CUSTOM_OBJECT,PublishedLead::class
);
(到目前为止)这有效,但是我现在看到fetchAll()
和FetchMode
从DBAL 2.11开始都已弃用:
// ResultStatement::fetchAll()
/*
* @deprecated Use fetchAllNumeric(),fetchAllAssociative()
* or fetchFirstColumn() instead.
*/
// FetchMode
/*
* @deprecated Use one of the fetch- or iterate-related
* methods on the Statement
*/
为了使我的代码尽可能地向前兼容,如何编写此代码以将结果合并到自定义对象中?我必须根据结果编写自定义的补水逻辑,还是DBAL可以为我做这件事?
解决方法
据我通读DBAL源代码所知,不赞成使用一般的访存模式,而应使用提供的辅助方法代替,这将结果限制为数字数组或关联数组。
这意味着将结果编组到您自己的类中的过程现在应该应该在DBAL之外处理。这可能是促进使用Doctrine ORM的战术决定,或者他们只是想专注于名称中的内容(抽象数据库访问),而忽略与该任务无关的事情。无论哪种方式,编写自定义的混合逻辑实际上并没有那么复杂,您基本上可以编写一种提供静态方法fromArray($data)
的Trait,该方法迭代数组并设置所有对象属性,然后返回对象(请参阅{{ 3}})。在要从关联数组构建的所有类中使用此特征。
我假设您正在某个时刻循环遍历对象数组,因此您实际上可以将函数转换为生成器。如果最终使用foreach
遍历结果集,则甚至不需要使用结果对代码进行任何更改。这意味着用以下循环替换您的return语句:
foreach ($statement as $row) {
yield PublishedLead::fromArray($row);
}
如果您不熟悉生成器,这会将您的函数转换为返回\Generator
的函数,可以像在foreach中使用数组那样使用,但实际上并不会占用整个内存空间来保存所有数据。相反,只要需要下一个值,就会继续执行原始功能,直到到达下一个yield语句为止,此时将返回并立即使用产生的值。
此外,如果您想知道,该语句实际上确实实现了Traversable,因此您可以在从foreach
获得该语句之后直接execute
进行访问,而无需实际调用任何获取方法,这是我在上面的示例中所做的; $row
将是一个关联数组,或更准确地说,是从\PDO::FETCH_BOTH
默认提取模式获得的数组。
这是一个完整的原型:
<?php
// newly created
trait FromArrayTrait {
public static function fromArray(array $data = []): self {
foreach (get_object_vars($obj = new self) as $property => $default) {
$obj->$property = $data[$property] ?? $default;
}
return $obj;
}
}
class PublishedLead {
use FromArrayTrait; // add this line
// rest of your class
}
function getDatabaseResult(): iterable { // change return type hint,if applicable
// rest of your function/method
// the following 3 lines replace 'return $statement->fetchAll(...);'
foreach ($statement as $row) {
yield PublishedLead::fromArray($row);
}
}
// your actual main code,this is unchanged assuming you already use foreach
foreach (getDatabaseResult() as $lead) {
$lead->doSomething();
}
显然要考虑名称空间,并将这些部分放在代码中应放置的位置。顺便说一下,我稍微改变了fromArray
方法,以便在数组值为null的情况下使用默认值。如果您实际上希望能够将默认值替换为null,请还原为上面链接的原始版本。如果您要设置动态属性,即使它们未在您的类中明确声明,也请遍历$data
而不是get_object_vars()
:
public static function fromArrayDynamic(iterable $data = []): self {
$obj = new self;
foreach ($data as $property => $value) {
$obj->$property = $value;
}
return $obj;
}
当然,如果数组中包含空值,则此值将用空值覆盖默认值。另外,该版本与iterable
输入兼容,因此它不仅可以使用数组,还可以与Generators和Traversables一起使用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。