Rumah >pembangunan bahagian belakang >tutorial php >Pengenalan semula hubungan polimorfik yang fasih ' s

Pengenalan semula hubungan polimorfik yang fasih ' s

Lisa Kudrow
Lisa Kudrowasal
2025-02-09 12:17:13590semak imbas

Re-Introducing Eloquent's Polymorphic Relationships

mata teras

    Persatuan Polymorphic Laravel membolehkan model menjadi milik pelbagai model lain pada satu persatuan. Ini memudahkan struktur pangkalan data, menjadikan kod lebih mudah untuk mengekalkan, dan membolehkan hubungan data yang lebih dinamik dan fleksibel.
  • Menyediakan persatuan polimorfik di Laravel melibatkan persatuan yang menentukan dalam model fasih. Kaedah
  • digunakan untuk menerima model yang berkaitan dengan polimorfik, manakala kaedah morphTo atau morphMany digunakan untuk model yang berkaitan dengan model lain. morphOne
  • Kaedah Laravel boleh digunakan untuk mengarahkan fasih menggunakan nama tersuai dan bukannya nama kelas untuk setiap model. Ini membantu dalam kes perubahan ruang nama model atau ruang nama yang terlalu panjang.
  • MorphMap Laravel menyokong banyak hubungan polimorfik, yang membolehkan model menjadi milik pelbagai model secara banyak. Ini amat berguna dalam aplikasi yang kompleks.
Artikel ini telah dikaji semula oleh Younes Rafie. Terima kasih kepada semua pengulas rakan sebaya SitePoint untuk membuat kandungan SitePoint Perfect!


Anda mungkin telah menggunakan pelbagai jenis hubungan antara model atau jadual pangkalan data, seperti biasa di Laravel: satu-satu, satu-ke-banyak, banyak-banyak, dan mempunyai banyak. Tetapi terdapat satu lagi jenis yang kurang biasa: persatuan polimorfik. Jadi apakah persatuan polimorfik? Re-Introducing Eloquent's Polymorphic Relationships

Persatuan Polymorphic merujuk kepada model yang boleh dimiliki oleh beberapa model lain dalam satu persatuan.

Untuk menggambarkan ini, mari kita buat adegan fiksyen di mana kita mempunyai topik dan model pos. Pengguna boleh meninggalkan komen dalam topik dan jawatan. Menggunakan hubungan polimorfik, kita boleh menggunakan jadual komen tunggal untuk kedua -dua kes. Menghairankan, bukan? Ini seolah -olah agak tidak praktikal kerana idealnya kita perlu membuat jadual Post_Comments dan jadual Topic_comments untuk membezakan komen. Menggunakan hubungan polimorfik, kami tidak memerlukan dua jadual. Mari memahami hubungan polimorfik melalui contoh praktikal.

apa yang akan kita bina

kami akan membuat aplikasi muzik demo yang mengandungi lagu dan album. Dalam aplikasi ini, kami boleh menyukai lagu dan album. Menggunakan hubungan polimorfik, kami akan menggunakan jadual Upvotes tunggal untuk kedua -dua kes. Pertama, mari kita periksa struktur jadual yang diperlukan untuk membina hubungan ini:

mari kita bincangkan lajur

dan
<code>albums
    id - integer
    name - string

songs
    id - integer
    title - string
    album_id - integer

upvotes
    id - integer
    upvoteable_id - integer
    upvoteable_type - string
</code>
, yang mungkin kelihatan sedikit pelik kepada mereka yang tidak menggunakan hubungan polimorfi sebelum ini. Lajur

akan mengandungi nilai ID album atau lagu, manakala lajur upvoteable_id akan mengandungi nama kelas yang memiliki model. Lajur upvoteable_type adalah bagaimana ORM menentukan "jenis" mana yang akan kembali memiliki model apabila mengakses hubungan upvoteable_id. upvoteable_type

menghasilkan model dan penghijrahan

Saya menganggap anda sudah mempunyai aplikasi Laravel yang sedang berjalan. Jika tidak, kursus permulaan cepat ini boleh membantu. Mari kita mulakan tiga model dan migrasi, dan kemudian mengedit migrasi untuk memenuhi keperluan kita.

<code>albums
    id - integer
    name - string

songs
    id - integer
    title - string
    album_id - integer

upvotes
    id - integer
    upvoteable_id - integer
    upvoteable_type - string
</code>

Perhatikan bahawa lulus bendera -m apabila membuat model juga akan menghasilkan migrasi yang berkaitan dengan model -model ini. Mari kita laraskan kaedah up dalam migrasi ini untuk mendapatkan struktur meja yang dikehendaki:

{some_timestamp}_create_albums_table.php

<code>php artisan make:model Album -m
php artisan make:model Song -m
php artisan make:model Upvote -m
</code>

{some_timestamp}_create_songs_table.php

<code class="language-php">public function up()
{
    Schema::create('albums', function (Blueprint $table) {
       $table->increments('id');
        $table->string('name');
        $table->timestamps();
    });
}</code>

{some_timestamp}_create_upvotes_table.php Sekarang, kita boleh menjalankan perintah migrasi tukang untuk membuat ketiga -tiga jadual ini:

<code class="language-php">public function up()
{
    Schema::create('songs', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->integer('album_id')->unsigned()->index();
        $table->timestamps();

        $table->foreign('album_id')->references('id')->on('albums')->onDelete('cascade');
    });
}</code>

mari kita konfigurasikan model kami untuk memberi perhatian kepada hubungan polimorfik antara album, lagu dan suka:

<code class="language-php">public function up()
{
    Schema::create('upvotes', function (Blueprint $table) {
        $table->increments('id');
        $table->morphs('upvoteable'); // 添加无符号整数 upvoteable_id 和字符串 upvoteable_type
        $table->timestamps();
    });
}</code>

app/Upvote.php

<code>php artisan migrate</code>

app/Album.php Kaedah

dalam model album dan lagu
<code class="language-php">[...]
class Upvote extends Model
{
    /**
     * 获取所有拥有模型。
     */
    public function upvoteable()
    {
        return $this->morphTo();
    }
}</code>
mentakrifkan hubungan one-to-banyak polimorfik antara model-model ini dan model upvote dan akan membantu kita mendapatkan semua contoh model tertentu.

app/Song.php Selepas menentukan hubungan, kita kini boleh mencuba permohonan untuk lebih memahami bagaimana hubungan polimorfik berfungsi. Kami tidak akan membuat sebarang pandangan untuk aplikasi ini, kami hanya akan mencuba aplikasi kami dari konsol.

<code class="language-php">class Album extends Model
{
    protected $fillable = ['name'];

    public function songs()
    {
        return $this->hasMany(Song::class);
    }

    public function upvotes()
    {
        return $this->morphMany(Upvote::class, 'upvoteable');
    }
}</code>
Jika anda menganggap pengawal dan di mana kita harus meletakkan kaedah seperti itu, saya cadangkan membuat albumupvotecontroller dan songupvotecontroller. Dengan cara ini, apabila kita berurusan dengan hubungan polimorfik, kita boleh menyambungkan perkara dengan ketat ke objek yang kita beroperasi. Dalam kes kami, kami boleh menyukai album dan lagu. Suka bukan album atau lagu. Juga, ia bukan seperti umum, yang bertentangan dengan bagaimana kita mempunyai UpvotesController dalam kebanyakan hubungan satu-ke-banyak. Semoga ini masuk akal.

upvotes mari kita mulakan konsol:

Hubungan pengambilan semula

Sekarang bahawa kami mempunyai beberapa data siap, kami dapat mengakses hubungan kami melalui model kami. Berikut adalah tangkapan skrin data dalam jadual upvotes:

<code class="language-php">class Song extends Model
{
    protected $fillable = ['title', 'album_id'];

    public function album()
    {
        return $this->belongsTo(Album::class);
    }

    public function upvotes()
    {
        return $this->morphMany(Upvote::class, 'upvoteable');
    }
}</code>

untuk mengakses semua album seperti ini, kita boleh menggunakan

atribut dinamik:

juga boleh mengambil pemilik hubungan polimorfik dari model polimorfik dengan mengakses nama kaedah yang melakukan panggilan ke Re-Introducing Eloquent's Polymorphic Relationships . Dalam kes kita, itu adalah kaedah

pada model upvote. Oleh itu, kami akan mengakses kaedah ini sebagai harta dinamik:

upvotes Hubungan

pada model
<code>php artisan tinker
>>> $album = App\Album::create(['name' => 'More Life']);
>>> $song = App\Song::create(['title' => 'Free smoke', 'album_id' => 1]);
>>> $upvote1 = new App\Upvote;
>>> $upvote2 = new App\Upvote;
>>> $upvote3 = new App\Upvote;
>>> $album->upvotes()->save($upvote1);
>>> $song->upvotes()->save($upvote2);
>>> $album->upvotes()->save($upvote3);</code>
upvote akan mengembalikan contoh album, kerana ini seperti yang dimiliki oleh contoh contoh album.

Kerana kita boleh mendapatkan bilangan suka untuk lagu atau album, kita boleh menyusun lagu atau album berdasarkan The Likes on the View. Begitulah carta muzik berfungsi.

untuk lagu, kita akan suka seperti ini:

<code>albums
    id - integer
    name - string

songs
    id - integer
    title - string
    album_id - integer

upvotes
    id - integer
    upvoteable_id - integer
    upvoteable_type - string
</code>

Jenis polimorfik adat

Secara lalai, Laravel akan menggunakan nama kelas yang berkelayakan sepenuhnya untuk menyimpan jenis model yang berkaitan. Sebagai contoh, dalam contoh di atas, Upvote mungkin tergolong dalam album atau lagu, dan lalai upvoteable_type adalah App\Album atau App\Song masing -masing.

Walau bagaimanapun, ini mempunyai kelemahan yang besar. Bagaimana jika ruang nama model album berubah? Kita perlu melakukan beberapa jenis penghijrahan untuk menamakan semula semua kejadian dalam jadual Upvotes. Ini agak rumit! Apa yang berlaku jika ruang nama panjang (mis.

)? Ini bermakna kita perlu menetapkan panjang maksimum yang sangat panjang pada lajur. Di sinilah kaedah App\Models\Data\Topics\Something\SomethingElse dapat membantu kami. MorphMap

kaedah "morphmap" akan mengarahkan fasih untuk menggunakan nama tersuai untuk setiap model, bukan nama kelas:

<code>php artisan make:model Album -m
php artisan make:model Song -m
php artisan make:model Upvote -m
</code>
kita boleh mendaftarkan morphMap dalam fungsi boot AppServiceProvider, atau membuat pembekal perkhidmatan yang berasingan. Agar perubahan baru berkuat kuasa, kita mesti menjalankan perintah dump-autoload komposer. Jadi sekarang kita boleh menambah rekod seperti ini:

<code class="language-php">public function up()
{
    Schema::create('albums', function (Blueprint $table) {
       $table->increments('id');
        $table->string('name');
        $table->timestamps();
    });
}</code>
Ia berkelakuan sama seperti contoh sebelumnya.

Kesimpulan

Walaupun anda mungkin tidak pernah menghadapi situasi di mana anda perlu menggunakan hubungan polimorfik, hari itu akhirnya akan datang. Kelebihan menggunakan Laravel adalah bahawa pengendalian keadaan ini sangat mudah dan tidak perlu melakukan apa -apa trik persatuan model untuk mendapatkan sesuatu yang berfungsi. Laravel juga menyokong banyak hubungan polimorfik. Anda boleh membaca lebih lanjut mengenainya di sini.

Saya harap anda kini memahami hubungan polimorfik dan apa yang mungkin diperlukan untuk jenis hubungan ini. Satu lagi contoh hubungan polimorfik yang lebih maju ada di sini. Jika anda mendapati ini membantu, sila kongsi dengan rakan anda dan jangan lupa untuk klik butang seperti itu. Jangan ragu untuk meninggalkan pemikiran anda di bahagian komen di bawah!

Soalan Lazim Mengenai Hubungan Polymorphic Eloquent

Apakah faedah menggunakan hubungan polimorfik di Laravel?

Hubungan polimorfik di Laravel menyediakan cara yang fleksibel dan cekap untuk memproses data yang berkaitan antara model yang berbeza. Mereka membenarkan model tergolong dalam pelbagai jenis model lain dalam satu persatuan. Ini bermakna anda boleh mempunyai satu senarai pengecam unik semua data yang berkaitan tanpa mengira jenis mereka. Ini dapat memudahkan struktur pangkalan data anda dan menjadikan kod anda lebih mudah untuk dijaga. Ia juga membolehkan hubungan data yang lebih dinamik dan fleksibel, yang amat berguna dalam aplikasi kompleks.

Bagaimana untuk menetapkan hubungan polimorfik di Laravel?

Menubuhkan hubungan polimorfik di Laravel melibatkan hubungan yang menentukan dalam model fasih. Pertama, anda perlu menentukan hubungan pada model yang akan menerima hubungan polimorfik. Ini dilakukan menggunakan kaedah morphTo. Kemudian, pada model yang akan dikaitkan dengan model lain, gunakan kaedah morphMany atau morphOne mengikut sama ada hubungan itu adalah satu-ke-banyak atau satu.

Bolehkah anda memberikan contoh hubungan polimorfik di Laravel?

Sudah tentu, mari kita pertimbangkan platform blog di mana kedua -dua jawatan dan pengguna boleh mempunyai komen. Dalam kes ini, model komen akan mempunyai hubungan polimorfik dengan model pos dan pengguna. Inilah cara untuk menentukan hubungan ini:

<code>albums
    id - integer
    name - string

songs
    id - integer
    title - string
    album_id - integer

upvotes
    id - integer
    upvoteable_id - integer
    upvoteable_type - string
</code>

Bagaimana menggunakan hubungan polimorfik untuk mendapatkan rekod yang berkaitan?

Anda boleh mendapatkan rekod yang relevan dalam hubungan polimorfik seperti yang anda lakukan dengan hubungan fasih yang lain. Sebagai contoh, jika anda ingin mengambil semua komen dari siaran, anda boleh melakukan ini:

<code>php artisan make:model Album -m
php artisan make:model Song -m
php artisan make:model Upvote -m
</code>

Bagaimana untuk menyelamatkan rekod yang berkaitan menggunakan hubungan polimorfik?

Simpan rekod yang berkaitan dalam hubungan polimorfik juga serupa dengan hubungan fasih yang lain. Anda boleh mengaitkan model menggunakan kaedah associate dan menyimpan model. Berikut adalah contoh:

<code class="language-php">public function up()
{
    Schema::create('albums', function (Blueprint $table) {
       $table->increments('id');
        $table->string('name');
        $table->timestamps();
    });
}</code>

Apakah beberapa kes penggunaan biasa untuk hubungan polimorfik?

Hubungan polimorfik amat berguna dalam situasi di mana model boleh tergolong dalam pelbagai jenis model lain. Sesetengah kes penggunaan biasa termasuk komen yang boleh dimiliki oleh jawatan dan pengguna, tag yang boleh digunakan untuk pelbagai jenis kandungan, dan imej atau fail yang boleh dilampirkan kepada pelbagai jenis entiti.

Apakah batasan atau kelemahan menggunakan hubungan polimorfik?

Walaupun hubungan polimorfik memberikan banyak fleksibiliti, mereka juga mungkin lebih kompleks dan lebih sukar untuk ditubuhkan dan dikendalikan daripada hubungan fasih standard. Mereka juga menyokong semua ciri hubungan standard, seperti keinginan untuk memuatkan kekangan.

Bagaimana untuk memadam rekod yang relevan dalam hubungan polimorfik?

anda boleh menggunakan kaedah delete pada hubungan untuk memadam rekod yang relevan dalam hubungan polimorfik. Sebagai contoh, untuk memadam semua komen dari siaran, anda boleh melakukan ini:

<code class="language-php">public function up()
{
    Schema::create('songs', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->integer('album_id')->unsigned()->index();
        $table->timestamps();

        $table->foreign('album_id')->references('id')->on('albums')->onDelete('cascade');
    });
}</code>

Bolehkah saya menggunakan hubungan polimorfik dengan banyak hubungan?

Ya, Laravel menyokong banyak hubungan polimorfik melalui kaedah morphToMany dan morphedByMany. Ini membolehkan model menjadi milik pelbagai model secara banyak.

Bagaimana menangani hubungan polimorfik dalam penghijrahan pangkalan data?

Dalam penghijrahan pangkalan data, anda biasanya menambah dua lajur ke jadual yang akan menerima hubungan polimorfik: satu untuk ID model yang berkaitan dan yang lain untuk jenis model yang berkaitan. Laravel menyediakan kaedah morphs yang mudah untuk menambah lajur ini:

<code class="language-php">public function up()
{
    Schema::create('upvotes', function (Blueprint $table) {
        $table->increments('id');
        $table->morphs('upvoteable'); // 添加无符号整数 upvoteable_id 和字符串 upvoteable_type
        $table->timestamps();
    });
}</code>

Ini menambah commentable_id dan commentable_type lajur ke meja.

Atas ialah kandungan terperinci Pengenalan semula hubungan polimorfik yang fasih ' s. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn