如何将PHP父对象转换/转换为子对象? [英] How can I transform / cast a PHP parent object to a child object?

查看:260
本文介绍了如何将PHP父对象转换/转换为子对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原因

我有一个遗留系统,该系统的表中包含子段.

I got a legacy system with a table containing slugs.

当这些记录匹配时,它表示某种具有布局ID的页面.

When those records match, it represents some kind of page with a layout ID.

由于这些页面可能具有不同的资源需求,因此取决于可以与哪些表连接的布局ID.

Because these pages can have different resource needs it depends on the layout ID which tables can be joined with.

我使用Laravel的口才模型.

I use Laravel's Eloquent models.

我想要的是一个拥有布局特定关系的子模型.

What I would like is to have a child model that holds the layout specific relations.

class Page extends Model {
    // relation 1, 2, 3 that are always present
}

class ArticlePage extends Page {
    // relation 4 and 5, that are only present on an ArticlePage
}

但是在我的控制器中,为了知道我需要哪种布局,我已经必须查询:

However in my controller, in order to know which layout I need, I already have to query:

url:/{slug}

$page = Slug::where('slug', $slug)->page;

if ($page->layout_id === 6) {
    //transform $page (Page) to an ArticlePage
}

因此,我得到了Page的实例,但是我想将其转换或转换为ArticlePage的实例,以加载它的其他关系.我该如何实现?

Because of this I get an instance of Page, but I would like to transform or cast it to an instance of ArticlePage to load it's additional relations. How can I achieve this?

推荐答案

您需要研究 Laravel中的多态关系以实现此目的.通过多态关系,您可以根据字段的类型检索不同的模型.在您的Slug模型中,您将需要以下内容:

You'll need to look into Polymorphic relations in Laravel to achieve this. A Polymorphic Relation would allow you to retrieve a different model based on the type of field it is. In your Slug model you would need something like this:

public function page()
{
    return $this->morphTo('page', 'layout_id', 'id');
}

在您的服务提供商之一中,例如AppServiceProvider,您需要提供一个 Morph Map ,以告诉Laravel将某些ID映射到某些模型类.例如:

In one of your service providers, e.g. AppServiceProvider you would need to provide a Morph Map to tell Laravel to map certain IDs to certain model classes. For example:

Relation::morphMap([
    1 => Page::class,
    // ...
    6 => ArticlePage::class,
]);

现在,无论何时使用page关系,Laravel都会检查类型并为您提供正确的模型.

Now, whenever you use the page relation, Laravel will check the type and give you the correct model back.

注意:我不确定100%的参数等,我还没有测试,但是您应该可以从文档中解决这个问题.

Note: I'm not 100% sure on the parameters etc. and I haven't tested but you should be able to work it out from the docs.

如果您的layout_idPage模型上,那么我看到的唯一解决方案是在您的Page模型中添加一种方法,该方法可以将现有页面转换ArticlePage或其他页面类型,基于其layout_id属性.您应该可以尝试这样的事情:

If your layout_id is on the Page model, the only solution I see is to add a method to your Page model that is able to convert your existing page into an ArticlePage, or other page type, based on its layout_id property. You should be able to try something like this:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Page extends Model
{
    const LAYOUT_ARTICLE = 6;

    protected $layoutMappings = [
        // Add your other mappings here
        self::LAYOUT_ARTICLE => ArticlePage::class
    ];

    public function toLayoutPage()
    {
        $class = $this->layoutMappings[$this->layout_id];

        if (class_exists($class)) {
            return (new $class())
                ->newInstance([], true)
                ->setRawAttributes($this->getAttributes());
        }

        throw new \Exception('Invalid layout.');
    }
}

这是根据您的layout_id属性寻找一个映射,然后它创建一个正确类型的新类,并用您从其创建的页面中的属性填充其属性.这应该是您所需要的,如果您查看Laravel创建新模型实例时调用的Laravel的Illuminate\Database\Eloquent::newFromBuilder()方法,您可以看到正在发生的事情以及如何获得上面的代码.您应该可以像这样使用它:

What this does is look for a mapping based on your layout_id property, and then it creates a new class of the correct type, filling its attributes with those from the page you're creating from. This should be all you need, if you take a look at Laravel's Illuminate\Database\Eloquent::newFromBuilder() method, which Laravel calls when it creates new model instances, you can see what's going on and how I've gotten the code above. You should be able to just use it like this:

$page = Slug::where('slug', $slug)
            ->first()
            ->page
            ->toLayoutPage();

这将为您提供ArticlePage

这篇关于如何将PHP父对象转换/转换为子对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆