简体   繁体   中英

Polymorphic Eloquent relationships with namespaces

I've tried to implement polymorphic relationships. They work perfectly... However, I'm trying to reduce my database size as much as possible so... I've this

Table action
|  id  |  realatable_type  |  relatable_id
|  1   |  Lion\People      |  65
|  2   |  Lion\Company     |  13

Obviously I've this

<?php namespace Lion;

class Company extends \Eloquent { ... }
class People extends \Eloquent { ... }

Is there any way to store only "People" or "Company" assuming that the namespace is always going to be "Lion"?

Since Laravel 4.1, inside your model (in this case Company and People ) you can set the protected property $morphClass to whatever you want.

<?php namespace Lion;

class Company extends \Eloquent { 

    protected $morphClass = 'Company';
}

Now in your table you can store the type without the namespace:

 |  id  |  realatable_type  |  relatable_id
 |  2   |  Company          |  13

I believe the best solution here (for database size at least) would be to simply change readable_type to ENUM('Lion\\Company', 'Lion\\People') .


That being said, if you really want to handle this on Laravel side, you'll have to create new classes extending from Illuminate\\Database\\Eloquent\\Relations\\Morph* ¹ and overwrite their constructors ² as to get only the last value after a dash, on $morphClass . Something like this:

<?php

use \Illuminate\Database\Eloquent\Model;
use \Illuminate\Database\Eloquent\Builder;

class MyMorphOne extends \Illuminate\Database\Eloquent\Relations\MorphOne {
    public function __construct(Builder $query, Model $parent, $type, $id) {
        parent::__construct($query, $parent, $type, $id);

        $this->morphClass = substr($this->morphClass, strrpos($this->morphClass, '\\') + 1);
    }
}

Then, extend your own model or base model, to overwrite morphOne , morphMany and morphToMany methods as to make use of your new extended classes. Something like this:

<?php

class People extends Eloquent {

    // ...

    public function morphOne($related, $name, $type = null, $id = null) {
        $instance = new $related;

        list($type, $id) = $this->getMorphs($name, $type, $id);

        $table = $instance->getTable();

        return new MyMorphOne($instance->newQuery(), $this, $table.'.'.$type, $table.'.'.$id);
    }

}
  1. * = One , Many and ToMany
  2. Which are actually inherited from MorphOneOrMany on MorphOne and MorphMany .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM