将 Laravel 查询结果投射到类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31873017/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cast Laravel query results to class
提问by OskarD90
When creating a query using the syntax DB::table('foo')
, it creates a generic class (stdClass). Is there any way to cast the resulting rows to a specific class?
使用语法创建查询时DB::table('foo')
,它会创建一个通用类 (stdClass)。有没有办法将结果行转换为特定的类?
Here is some example code that should explain what I want to do:
下面是一些示例代码,可以解释我想要做什么:
$result = DB::table('foo')->get();
$converted = (Foo) $result; // Not going to work
I want to cast all the (stdClass) objects of the array to the Foo class.
我想将数组的所有 (stdClass) 对象强制转换为 Foo 类。
采纳答案by Beefjeff
As of laravel 5.4
从 Laravel 5.4 开始
Eloquent models dont have the hydrate() method.
Eloquent 模型没有 hydr() 方法。
This has been moved to the Eloquent Builder class.
这已移至 Eloquent Builder 类。
https://laravel.com/api/5.4/search.html?search=hydrate
https://laravel.com/api/5.4/search.html?search=hydrate
The Eloquent Builder class requires a few things to get this working manually
Eloquent Builder 类需要一些东西来手动运行它
- A query builder to initialize
- A model to hydrate with.
- 要初始化的查询构建器
- 一个水合模型。
Here is my working example in some laravel 5.8 code:
这是我在一些 Laravel 5.8 代码中的工作示例:
$instance = new $class;
$table = $instance->getTable();
/** @var \Illuminate\Database\Eloquent\Builder $eloquent_builder*/
$eloquent_builder = new \Illuminate\Database\Eloquent\Builder(
// the Query Builder!
DB::connection($connection_name)
->table($table)
->select($columns)
->orderBy($order_by, $order)
);
// Tell Eloquent what you're using to hydrate the query
$eloquent_builder->setModel($instance);
return $eloquent_builder->get();
回答by dKen
Yes, you can hydrate the results into the classes you want. I found the answer buried deep in a mess of half-answers and confused questions that make up the terrible Laracasts.com forum. Thanks for asking the question here instead of there.
是的,您可以将结果混合到您想要的类中。我发现答案深深地埋在了组成糟糕的Laracasts.com 论坛的一堆半答案和混乱的问题中。感谢您在这里而不是在那里提问。
Once you get the results, hydrate them using your model class:
获得结果后,使用您的模型类对它们进行水合:
$result = DB::table('foo')->get();
$converted = Foo::hydrate($result);
Edit:Found some documentation on the hydrate
methodtoo, if that helps
编辑:也找到了一些关于该hydrate
方法的文档,如果有帮助的话
Edit 2:I found myself in a situation where I needed to cast results from either an array
or a collection
, depending on the results of a query. When a collection was returned, it was correctly hydrated, but when the result was an array, they were just stdClass
. I wrote a quick methodadded to my master model
that took a collection of arrays or objects, or a pagination object, and correctly cast it to the object I wanted.
编辑 2:我发现自己需要从 anarray
或 a 转换collection
结果,具体取决于查询的结果。当一个集合被返回时,它被正确地水合,但是当结果是一个数组时,它们只是stdClass
. 我写了一个添加到我的主人的快速方法model
,它获取一组数组或对象,或一个分页对象,并将其正确地转换为我想要的对象。
回答by Ben Swinburne
Typically you'd achieve this by setting the PDO Statement fetch_style to PDO::FETCH_CLASS as below
通常,您可以通过将 PDO 语句 fetch_style 设置为 PDO::FETCH_CLASS 来实现这一点,如下所示
$statement->fetchAll(PDO::FETCH_CLASS, "App\User");
$statement->fetchAll(PDO::FETCH_CLASS, "App\User");
If you look at the method Illuminate\Database\Connection::select
you'll see that whilst you can set the fetch_style/fetchMode, you can not the second argument.
如果您查看该方法,Illuminate\Database\Connection::select
您会发现虽然您可以设置 fetch_style/fetchMode,但您不能设置第二个参数。
public function select($query, $bindings = array(), $useReadPdo = true)
{
return $this->run($query, $bindings, function($me, $query, $bindings) use ($useReadPdo)
{
if ($me->pretending()) return array();
// For select statements, we'll simply execute the query and return an array
// of the database result set. Each element in the array will be a single
// row from the database table, and will either be an array or objects.
$statement = $this->getPdoForSelect($useReadPdo)->prepare($query);
$statement->execute($me->prepareBindings($bindings));
return $statement->fetchAll($me->getFetchMode());
});
}
Nor can you get access to the statement before fetchAll is called to call PDOStatement::setFetchMode
for example.
PDOStatement::setFetchMode
例如,在调用 fetchAll 之前,您也无法访问该语句。
You could perhaps attempt to extend Illuminate\Database\Connection
and utilise that throughout other Database related classes by extending and replacing where necessary but it seems like a hefty task to maintain.
您也许可以Illuminate\Database\Connection
通过在必要时扩展和替换来尝试在其他与数据库相关的类中扩展和利用它,但这似乎是一项艰巨的维护任务。
The other option is to use Eloquent which will give you classes back of a particular type but you get the slight additional overhead of hydrating the model objects.
另一种选择是使用 Eloquent,它会给你返回一个特定类型的类,但你会得到一些额外的模型对象水合开销。
class Foo extends Illuminate\Database\Eloquent\Model {
protected $table = 'foo';
}
Foo::all()
Foo::where('col', 1)->get()
回答by Robert Trzebiński
Laravel 5.8
Laravel 5.8
In the class you want to cast to (YourClass
in this example) to you'll need constructor like this:
在您想要转换为(YourClass
在本例中)的类中,您需要这样的构造函数:
/**
* Use to initialize fields from DB query like:
* $query->mapInto(YourClass::class)
*
* YourClass constructor.
* @param \stdClass $data
*/
public function __construct(\stdClass $data)
{
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
Then in your query:
然后在您的查询中:
$result = $query
->get()
->mapInto(YourClass::class);
$result will now contain a collection of YourClass
instances with fields loaded from the query.
$result 现在将包含具有YourClass
从查询加载的字段的实例集合。
回答by num8er
You cannot type cast it this way.
You can build change Your Foo class to get handle of object and work with it.
您不能以这种方式进行类型转换。
您可以构建更改您的 Foo 类以获取对象的句柄并使用它。
class Foo {
private $object = null;
public function __construct(stdClass $object) {
$this->object = $object;
}
public function __get($property) {
if (property_exists($this->object, $property)) {
return $this->object->$property;
}
}
public function __set($property, $value) {
if (property_exists($this->object, $property)) {
$this->object->$property = $value;
}
return $this;
}
public static function make(stdClass $object) {
return new self($object);
}
public static function makeCollection(array $collection) {
foreach($collection AS $key => $Item) {
$collection[$key] = self::make($Item);
}
return $collection;
}
}
$result = DB::table('foo')->get();
$converted = Foo::makeCollection($result);
回答by aldrin27
Yes. For example:
是的。例如:
$query = DB::table('example_tbl')->where('id', $id)->get();
$cast = (array)$query;
var_dump($cast);