Laravel Polymorphic Relations

Justas Maziliauskas, maziliauskas.lt

Klaidos.

Images

Skirtingos lentelės: profile_images, blog_posts_images, uploaded_images, email_attachment_images...

 

Atskiras laukas prie  įrašo: profile_photo, main_img...

Images

Identifikatorius: type

SELECT * FROM images WHERE type = 1; // profile pictures
SELECT * FROM images WHERE type = 2; // blog post featured image
SELECT * FROM images WHERE type = 3; // thumbnails

Eloquent

Polymorphic Relations

Polimorfizmas – objektiniame programavime naudojama sąvoka, kai metodas gali būti vykdomas skirtingai, priklausomai nuo konkrečios klasės ar duomenų tipo realizacijos, metodo kvietėjui nieko nežinant apie tokius skirtumus.

Nueik ir nupirk man maisto.

Ka galima nuveikti?

// load user
$user = User::find(1);

// create photo
$photo = new Photo;
$photo->path = 'foo/bar/baz';

// save photo to the loaded model
$user->photos()->save($photo);
$user = User::find(1);

foreach ($user->photos as $photo) {
    //
}
$post = Post::find(1);

foreach ($post->photos as $photo) {
    //
}
// load blog post
$post = Post::find(1);

// save photo to the loaded model
$post->photos()
     ->create(array(
        'path' => 'foo/bar/baz'
       ));

images table

$photo = Photo::find(1);

$photo->imageable; -> App\User {...}

Many To Many

// load photo
$photo = Photo::find(1);

// attach tag
$photo->attach(5); 

$photo = Photo::find(1);

foreach ($photo->tags as $tag) {
    //
}
$video = Video::find(1);

foreach ($video->tags as $tag) {
    //
}
// load video
$video = Video::find(1);

// attach tag
$video->attach(5); 

tags table

save(), saveMany(), attach(), sync()... also works
$tag = Tag::find(1);

foreach ($tag->videos as $video) {
    //
}

foreach ($tag->photos as $photo) {
    //
}

HOW IT'S MADE?

users
    id - integer
    name - string

posts
    id - integer
    title - integer

photos
    id - integer
    path - string
    imageable_id - integer
    imageable_type - string
pa make:migration create_photos_table --create=photos
public function up()
    {
        Schema::create('photos', function (Blueprint $table) {
            $table->increments('id');
            $table->string('path');
            $table->morphs('imageable');
        });
    }
class Photo extends Model
{
    public function imageable()
    {
        return $this->morphTo();
    }
}

class User extends Model
{
    public function photos()
    {
        return $this->morphMany(Photo::class, 'imageable');
    }
}

class Post extends Model
{
    public function photos()
    {
        return $this->morphMany(Photo::class, 'imageable');
    }
}
// load user
$user = User::find(1);

// create photo
$photo = new Photo;
$photo->path = 'foo/bar/baz';

// save photo to the loaded model
$user->photos()->save($photo);
$user = User::find(1);

foreach ($user->photos as $photo) {
    //
}
$post = Post::find(1);

foreach ($post->photos as $photo) {
    //
}
// load blog post
$post = Post::find(1);

// save photo to the loaded model
$post->photos()
      ->create(array(
         'path' => 'foo/bar/baz'
      ));

images table

photos
    id - integer
    path - string

videos
    id - integer
    name - string

tags
    id - integer
    name - string

taggables
    tag_id - integer
    taggable_id - integer
    taggable_type - string
pa make:migration create_taggables_table --create=taggables
public function up()
    {
        Schema::create('taggables', function (Blueprint $table) {
            $table->integer('tag_id')->unsigned();
            $table->foreign('tag_id')->references('id')->on('tags');
            $table->morphs('taggable');
        });
    }

Many To Many

class Photo extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

class Video extends Model
{
    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable');
    }
}

class Tag extends Model
{
    public function photos()
    {
        return $this->morphedByMany(Photo::class, 'taggable');
    }

    public function videos()
    {
        return $this->morphedByMany(Video::class, 'taggable');
    }
}
// load photo
$photo = Photo::find(1);

// attach tag
$photo->attach($tag_id); 

$photo = Photo::find(1);

foreach ($photo->tags as $tag) {
    //
}
$video = Video::find(1);

foreach ($video->tags as $tag) {
    //
}
// load video
$video = Video::find(1);

// attach tag
$video->attach($tag_id); 

tags table

Įdomu?

photos table

$user = User::find(1);

foreach ($user->photos as $photo) {
    //
}

SELECT * FROM `photos` 
WHERE `photos`.`imageable_id` = '1' 
AND `photos`.`imageable_type` = 'App\User'

Klausimai?

Gal kas susidūręs plačiau?

1st Laravel Meetup Vilnius

By Justas Maziliauskas