如何将 Laravel/Eloquent 结果映射到自定义类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21525250/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 08:57:49  来源:igfitidea点击:

How to map Laravel/Eloquent results to custom class

phpormlaravellaravel-4eloquent

提问by coatesap

I'm looking for a way to map the results of Laravel / Eloquent database queries to custom classes, rather than the default Eloquent class.

我正在寻找一种方法将 Laravel/Eloquent 数据库查询的结果映射到自定义类,而不是默认的 Eloquent 类。

Does Laravel / Eloquent include any built-in facility for doing this? If not, is there a suitable place to 'hook' into the result generation code and do the necessary mapping?

Laravel / Eloquent 是否包含用于执行此操作的任何内置工具?如果没有,是否有合适的地方可以“挂钩”到结果生成代码中并进行必要的映射?

As an example, this is roughly what I'd like to achieve:

例如,这大致是我想要实现的目标:

class User extends Eloquent {}

class MyUser
{
    protected $name;

    public function getName() {
        return $this->name;
    }

    public function setName($name) {
        $this->name = $name;
        return $this;
    }
}

$users = User::all();

// $users should now contain an array of MyUser instances

Motivation / Reason for question

动机/问题原因

The motivation behind this question is to find a way in which queries can produce objects or arrays of objects that are completely framework-independent. This is because the Laravel app in question needs to be able to pass its results to other non-Laravel systems, so hence Plain Old PHP Objects (such as MyUser) make the most sense.

这个问题背后的动机是找到一种方法,使查询可以生成完全独立于框架的对象或对象数组。这是因为有问题的 Laravel 应用程序需要能够将其结果传递给其他非 Laravel 系统,因此普通的旧 PHP 对象(例如 MyUser)最有意义。

回答by Antonio Carlos Ribeiro

Laravel will not give you something like that, but you can do with PHP. Inject your Eloquent User class into your custom class, Laravel will inject it for you automatically. Use the object inside your class as you wish and, if you need to call one or another Eloquent method, you can just provide fallbacks to the Eloquent User object.

Laravel 不会给你这样的东西,但你可以用 PHP 来做。将你的 Eloquent User 类注入到你的自定义类中,Laravel 会自动为你注入它。根据需要在您的类中使用该对象,如果您需要调用一个或另一个 Eloquent 方法,您可以只提供 Eloquent User 对象的回退。

A good option is to use the repository pattern, where your class will expect to receive an implementation of a repository interface, for that you have to:

一个不错的选择是使用存储库模式,您的类将期望接收存储库接口的实现,为此您必须:

Create the interface for your user repository, all repositories, including your Eloquent model, must implement this interface. This is a contract to let you switch the implementation of the repository whenever you want, without having to touch your class. It also will make your class framework agnostic.

为你的用户仓库创建接口,所有的仓库,包括你的 Eloquent 模型,都必须实现这个接口。这是一个契约,让您可以随时切换存储库的实现,而无需接触您的类。它也将使您的类框架不可知。

interface UserRepositoryInterface {

}

Your implementations of this repository could be:

您对此存储库的实现可能是:

class EloquentUser extends Eloquent implements UserRepositoryInterface {

}

class DoctrineUser extends DoctrineWhatever implements UserRepositoryInterface {

}

Create your class

创建你的班级

class User extends Eloquent {}

class MyUser
{
    protected $name;

    public function __construct(UserRepositoryInterface $user)
    {
        $this->userRepository = $user;
    }

    public function __call($name, $arguments)
    {
        return call_user_func_array(array($this->userRepository,$name), $arguments);
    }

    public static function __callStatic($name, $arguments)
    {
        return call_user_func_array(array('User',$name), $arguments);
    }

    public function getName() {
        return $this->userRepository->name;
    }

    public function setName($name) {
        $this->name = $name;
        return $this;
    }
}

Now in Laravel to select the implementation you just have to

现在在 Laravel 中选择你只需要的实现

App::bind('UserRepositoryInterface', 'EloquentUser');

To switch to doctrine, you just have to

要切换到教义,你只需要

App::bind('UserRepositoryInterface', 'DoctrineUser');

And if you need to use this class outside Laravel, you just have to instantiate it, passing whatever implementation of the repository you want:

如果你需要在 Laravel 之外使用这个类,你只需要实例化它,传递你想要的存储库的任何实现:

$user = new MyUser(new DoctrineUser);

No more ties to Laravel.

不再与 Laravel 建立联系。

回答by bubjavier

for Eloquent models, you might want to take advantage of ->toArray()method then typecast it using (object)to get POPO.

对于 Eloquent 模型,您可能希望利用->toArray()方法,然后使用它进行类型转换(object)以获取 POPO。

e.g.

例如

$user = (object) User::find(1)->toArray();

print_r($user);

you should get:

你应该得到:

stdClass Object
(
    [id] => 1
    [name] => John Doe
    [email] => [email protected]
    [active] => 1
    ...
    [created_at] => 2017-10-26 17:45:53
    [updated_at] => 2017-10-26 17:45:53
    [deleted_at] => 
)

回答by kororo

I also wanted to have custom class for this pre-defined class "User".

我还想为这个预定义的类“用户”提供自定义类。

class User extends Model implements UserInterface, RemindableInterface {

to UserModel class:

到 UserModel 类:

class UserModel extends Model implements UserInterface, RemindableInterface {

So rather than hacking through the codes and classes, actually there is config for it.

因此,不是通过代码和类进行黑客攻击,实际上有它的配置。

Open app/config/auth.php

打开 app/config/auth.php

Make sure you change:

确保你改变:

'model' => 'UserModel', // change to UserModel or your custom named class
'table' => 'User', // change if your table is non default "User"

It should be good to go.

去应该不错。

:)

:)