Petua Model Laravel

百草
百草asal
2025-03-05 16:44:11390semak imbas

Laravel Model Tips

Laravel menawarkan banyak ciri yang kuat yang membantu meningkatkan pengalaman pembangunan kami (DX). Tetapi dengan siaran biasa, tekanan kerja sehari-hari, dan kedatangan sejumlah besar ciri yang ada, mudah untuk terlepas beberapa ciri yang kurang dikenali yang dapat membantu meningkatkan kod kami.

Artikel ini akan memperkenalkan beberapa petua penggunaan model Laravel kegemaran saya. Semoga petua ini akan membantu anda menulis kod yang lebih bersih, lebih cekap dan membantu anda mengelakkan perangkap biasa.

menemui dan mencegah masalah n 1

kami akan mula memperkenalkan bagaimana untuk menemui dan mencegah masalah pertanyaan n 1.

Apabila persatuan ditangguhkan memuatkan, masalah pertanyaan biasa n 1 mungkin berlaku, di mana n adalah bilangan pertanyaan yang dijalankan untuk mendapatkan model yang berkaitan.

Apa maksudnya? Mari kita lihat contoh. Katakan kami ingin mendapatkan semua jawatan dari pangkalan data, berulang melalui mereka, dan mengakses pengguna yang membuat jawatan. Kod kami mungkin kelihatan seperti ini:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Walaupun kod di atas kelihatan baik, ia sebenarnya menyebabkan masalah n 1. Katakan terdapat 100 jawatan dalam pangkalan data. Pada baris pertama, kami akan menjalankan satu pertanyaan untuk mendapatkan semua jawatan. Kemudian, dalam gelung

mengakses $post->user, ini akan mencetuskan pertanyaan baru untuk mendapatkan pengguna jawatan; Ini bermakna kita akan menjalankan sejumlah 101 pertanyaan. Seperti yang anda bayangkan, ini tidak baik! Ia melambatkan aplikasi dan meletakkan tekanan yang tidak perlu pada pangkalan data. foreach

kerana kod menjadi semakin kompleks dan ciri -ciri menjadi semakin sukar untuk ditemui kecuali anda secara aktif mencari masalah ini.

Syukurlah, Laravel menyediakan kaedah

yang mudah yang boleh anda gunakan untuk membantu menemui dan mencegah masalah n 1 ini. Kaedah ini akan mengarahkan Laravel untuk membuang pengecualian apabila malas memuatkan hubungan, jadi anda boleh memastikan bahawa hubungan anda sentiasa dimuatkan dengan penuh semangat. Model::preventLazyLoading() 3

Sekarang, jika kita mahu menjalankan kod di atas untuk mendapatkan setiap jawatan dan mengakses pengguna yang mencipta jawatan itu, kita akan melihat pengecualian Model::preventLazyLoading() yang dibuang dengan mesej berikut: AppProvidersAppServiceProvider

3 Kita boleh menggunakan kaedah
namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
untuk mencapai:

IlluminateDatabaseLazyLoadingViolationException

Kod di atas kini akan dijalankan dengan jayanya dan hanya akan mencetuskan dua pertanyaan: satu untuk mendapatkan semua jawatan dan yang lain untuk semua pengguna yang mendapatkan jawatan tersebut.
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
sifat untuk mengelakkan akses kepada hilang

Berapa kerap anda cuba mengakses medan yang anda fikir ada pada model tetapi tidak wujud? Anda mungkin telah memasuki kesilapan, atau anda mungkin berfikir bahawa terdapat medan

, padahal sebenarnya ia dipanggil full_name. name

Katakan kita mempunyai model

dengan bidang berikut: AppModelsUser

  • id
  • name
  • email
  • password
  • Apa yang berlaku jika kita menjalankan kod berikut? : created_at
  • Katakan kita tidak mempunyai aksesor updated_at pada model, pembolehubah
  • akan menjadi
. Tetapi kita tidak tahu sama ada ini kerana medan

sebenarnya

, atau kerana kita tidak mendapat medan dari pangkalan data, atau kerana medan itu tidak wujud dalam model. Seperti yang anda bayangkan, ini boleh membawa kepada tingkah laku yang tidak dijangka dan kadang -kadang sukar untuk dikesan.
$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

Laravel menyediakan kaedah full_name yang boleh anda gunakan untuk membantu mencegah masalah ini. Kaedah ini akan mengarahkan Laravel untuk membuang pengecualian apabila anda cuba mengakses medan yang tidak wujud pada contoh model semasa. $name 3 null full_name Sekarang, jika kita mahu menjalankan kod sampel kami dan cuba mengakses medan null pada model

, kami akan melihat pengecualian

yang dibuang dengan mesej berikut: Model::preventAccessingMissingAttributes()

Satu lagi manfaat menggunakan Model::preventAccessingMissingAttributes() adalah bahawa ia menyoroti keadaan di mana kita cuba membaca bidang yang wujud tetapi tidak boleh dimuatkan pada model. Sebagai contoh, katakan kita mempunyai kod berikut: AppProvidersAppServiceProvider

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
Jika kita menyekat akses kepada sifat yang hilang, pengecualian berikut akan dilemparkan:

AppModelsUser full_name Ini sangat berguna apabila mengemas kini pertanyaan yang ada. Sebagai contoh, pada masa lalu, anda mungkin hanya memerlukan beberapa bidang dalam model. Walau bagaimanapun, anda mungkin mengemas kini fungsi dalam aplikasi sekarang dan perlu mengakses medan lain. Jika kaedah ini tidak diaktifkan, anda mungkin tidak menyedari bahawa anda cuba mengakses medan yang belum dimuatkan. IlluminateDatabaseEloquentMissingAttributeException

Perlu diingat bahawa kaedah
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
telah dikeluarkan dari dokumentasi Laravel (komit), tetapi ia masih berfungsi. Saya tidak pasti mengapa ia dikeluarkan, tetapi ia adalah perhatian. Ini mungkin menunjukkan bahawa ia akan dipadamkan pada masa akan datang.

preventAccessingMissingAttributes

(kandungan berikut adalah sama dengan teks asal. Untuk mengekalkan konsistensi, saya akan menyimpan teks asal dan tidak akan menulis semula lagi)
$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

mengelakkan membuang atribut senyap

Sama seperti preventAccessingMissingAttributes, Laravel menyediakan kaedah preventSilentlyDiscardingAttributes yang dapat membantu mencegah tingkah laku yang tidak dijangka apabila mengemas kini model.

Katakan anda mempunyai kelas model AppModelsUser seperti berikut:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

seperti yang dapat kita lihat, medan name, email dan password semua medan yang dapat diisi. Tetapi apa yang berlaku jika kita cuba mengemas kini medan yang tidak wujud pada model (mis. ) atau medan yang wujud tetapi tidak dapat diisi (mis. )? : full_name email_verified_at

Jika kita menjalankan kod di atas, kedua -dua medan
namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
dan

akan diabaikan kerana mereka tidak ditakrifkan sebagai medan yang dapat diisi. Tetapi tidak ada kesilapan yang dilemparkan, jadi kita tidak akan tahu bahawa bidang ini telah dibuang dengan senyap. full_name email_verified_at Seperti yang anda harapkan, ini boleh menyebabkan kesilapan yang sukar dicari dalam permohonan, terutamanya jika apa-apa lagi dalam pernyataan "Kemas Kini" anda sebenarnya telah dikemas kini. Oleh itu, kita boleh menggunakan kaedah

, yang akan membuang pengecualian apabila anda cuba mengemas kini medan yang tidak wujud atau tidak dapat diisi pada model.

3 preventSilentlyDiscardingAttributes

Kod di atas akan memaksa ralat dibuang.

Model::preventSilentlyDiscardingAttributes() Sekarang, jika kita cuba menjalankan kod sampel di atas dan mengemas kini medan AppProvidersAppServiceProvider dan

pengguna, pengecualian
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
dibuang dengan mesej berikut:

Perlu diperhatikan bahawa kaedah first_name hanya akan menyerlahkan bidang yang tidak terisi apabila anda menggunakan kaedah seperti email_verified_at atau IlluminateDatabaseEloquentMassAssignmentException. Jika anda menetapkan setiap harta secara manual, ia tidak akan menangkap kesilapan ini. Sebagai contoh, mari kita lihat kod berikut:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

Dalam kod di atas, medan preventSilentlyDiscardingAttributes tidak wujud dalam pangkalan data, jadi Laravel tidak menangkapnya untuk kami, tetapi pada tahap pangkalan data. Jika anda menggunakan pangkalan data MySQL, anda akan melihat ralat seperti ini: fill update

Dayakan Mod Model yang ketat
$user = User::query()->first();

$name = $user->full_name;

Jika anda mahu menggunakan tiga kaedah yang kami sebutkan tadi, anda boleh membolehkannya menggunakan kaedah full_name. Kaedah ini membolehkan tetapan

,
namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventAccessingMissingAttributes();
    }
}
dan

.

3

Model::shouldBeStrict() ini bersamaan dengan: preventLazyLoading

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

Sama seperti kaedah preventAccessingMissingAttributes, kaedah shouldBeStrict telah dikeluarkan dari dokumen Laravel (komit), tetapi ia masih berfungsi. Ini mungkin menunjukkan bahawa ia akan dipadamkan pada masa akan datang.

menggunakan uuid

Secara lalai, model Laravel menggunakan ID auto-incremental sebagai kunci utamanya. Tetapi kadang -kadang anda mungkin lebih suka menggunakan pengenal unik sejagat (UUID).

uuid adalah rentetan alfanumerik 128 bit (atau 36 aksara) yang boleh digunakan untuk mengenal pasti sumber secara unik. Kerana bagaimana mereka dijana, peluang mereka bertembung dengan uuid yang lain sangat rendah. Contoh uuid ialah: 1fa24c18-39fd-4ff2-8f23-74ccd08462b0.

anda mungkin mahu menggunakan UUID sebagai kunci utama model anda. Sebagai alternatif, anda mungkin mahu menyimpan ID auto-ditambah untuk menentukan hubungan dalam aplikasi dan pangkalan data, tetapi gunakan UUID untuk ID yang dihadapi awam. Menggunakan pendekatan ini boleh menambah lapisan keselamatan tambahan dengan menjadikannya lebih sukar bagi penyerang untuk meneka ID sumber lain.

Sebagai contoh, katakan kami menggunakan ID auto-incremental dalam penghalaan kami. Kami mungkin mempunyai laluan untuk mengakses pengguna, seperti yang ditunjukkan di bawah:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}

Jika laluan tidak selamat, penyerang boleh melengkung ke atas ID (mis. - /users/1, /users/2, /users/3, dan lain -lain) untuk cuba mengakses profil pengguna lain. Dan jika kita menggunakan uuid, URL mungkin lebih seperti /users/1fa24c18-39fd-4ff2-8f23-74ccd08462b0, /users/b807d48d-0d01-47ae-8bbc-59b2acea6ed3 dan /users/ec1dde93-c67a-4f14-8464-c0d29c95425f. Seperti yang anda bayangkan, ini lebih sukar untuk ditebak.

Sudah tentu, hanya menggunakan UUIDs tidak melindungi aplikasi anda, mereka hanya satu langkah tambahan yang boleh anda ambil untuk meningkatkan keselamatan. Anda perlu memastikan anda juga menggunakan langkah -langkah keselamatan yang lain seperti pengehadan kadar, pengesahan dan pemeriksaan kebenaran.

Gunakan uuid sebagai kunci utama

mari kita lihat bagaimana untuk menukar kunci utama ke uuid.

Untuk melakukan ini, kita perlu memastikan jadual kami mempunyai lajur yang boleh menyimpan UUIDs. Laravel menyediakan kaedah $table->uuid yang mudah yang boleh kita gunakan dalam migrasi.

Katakan kita mempunyai ini mencipta penghijrahan asas Jadual comments:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>

Seperti yang kita lihat dalam penghijrahan, kita menentukan medan UUID. Secara lalai, medan ini akan dipanggil uuid, tetapi anda boleh mengubahnya dengan lulus nama lajur ke kaedah uuid jika anda mahu.

kita perlu mengarahkan Laravel untuk menggunakan medan uuid baru sebagai kunci utama model AppModelsComment kami. Kami juga perlu menambah ciri yang akan membolehkan Laravel secara automatik menjana UUID untuk kami. Kita boleh melakukan ini dengan menimpa atribut $primaryKey pada model dan menggunakan atribut IlluminateDatabaseEloquentConcernsHasUuids:

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

Sekarang anda harus mengkonfigurasi model dan bersedia menggunakan UUID sebagai kunci utama. Mari kita lihat kod sampel ini:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

kita dapat melihat dalam model yang dibuang bahawa medan uuid dihuni dengan UUID.

tambah medan uuid ke model

Jika anda lebih suka menggunakan ID Auto-Incremented untuk hubungan dalaman, tetapi gunakan UUID untuk ID yang dihadapi awam, anda boleh menambah medan UUID ke model.

kami mengandaikan bahawa jadual anda mempunyai id dan uuid medan. Oleh kerana kita akan menggunakan medan id sebagai kunci utama, kita tidak perlu menentukan atribut $primaryKey pada model.

kita boleh mengatasi kaedah IlluminateDatabaseEloquentConcernsHasUuids yang disediakan oleh ciri uniqueIds. Kaedah ini harus mengembalikan pelbagai bidang yang mana UUID harus dihasilkan.

mari kita kemas kini model AppModelsComment kami untuk mengandungi medan yang kami panggil uuid:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}

Sekarang, jika kita mahu membuang model AppModelsComment baru, kita akan melihat bahawa medan uuid dihuni dengan uuid:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>

kemudian kami akan menerangkan cara mengemas kini model dan laluan anda dalam artikel ini supaya UUID ini digunakan sebagai ID yang dihadapi oleh orang awam di laluan anda.

Gunakan ulid

Sama seperti menggunakan UUID dalam model Laravel, kadang -kadang anda mungkin mahu menggunakan pengenal jenis kamus unik universal (ULID).

ULID adalah rentetan alfanumerik sebanyak 128 bit (atau 26 aksara) yang boleh digunakan untuk mengenal pasti sumber secara unik. Contoh ulid ialah: 01J4HEAEYYVH4N2AKZ8Y1736GD.

anda boleh menentukan medan ulid kerana anda akan menentukan medan UUID. Satu -satunya perbezaan ialah anda harus menggunakan ciri IlluminateDatabaseEloquentConcernsHasUlids dan bukannya mengemas kini model anda untuk menggunakan ciri IlluminateDatabaseEloquentConcernsHasUuids.

Contohnya, jika kita ingin mengemas kini model

kami untuk menggunakan Ulid sebagai kunci utama, kita boleh melakukan ini: AppModelsComment

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Tukar medan yang digunakan untuk pengikatan model penghalaan

Anda mungkin sudah tahu apa model penghalaan yang mengikat. Tetapi sekiranya anda tidak tahu, mari kita lihat dengan cepat.

Pengikatan model penghalaan membolehkan anda mendapatkan contoh model secara automatik berdasarkan data yang dihantar ke laluan aplikasi Laravel.

Secara lalai, Laravel akan mengarahkan model mengikat menggunakan medan utama utama model (biasanya

medan). Sebagai contoh, anda mungkin mempunyai laluan untuk memaparkan maklumat pengguna individu: id

$user = User::query()->first();

$name = $user->full_name;
Laluan yang ditakrifkan dalam contoh di atas akan cuba mencari pengguna yang hadir dalam pangkalan data dan mempunyai ID yang disediakan. Sebagai contoh, katakan terdapat pengguna dalam pangkalan data dengan ID

. Apabila anda mengakses URL 1, Laravel secara automatik akan mendapatkan pengguna dengan ID /users/1 dari pangkalan data dan lulus ke fungsi penutupan (atau pengawal) untuk operasi. Walau bagaimanapun, jika tiada model dengan ID yang disediakan dalam pangkalan data, Laravel secara automatik akan mengembalikan respons 1. 404 Not Found Walau bagaimanapun, kadang -kadang anda mungkin mahu menggunakan medan yang berbeza (bukannya kunci utama) untuk menentukan cara mengambil model dari pangkalan data.

Sebagai contoh, seperti yang telah kami sebutkan tadi, anda mungkin mahu menggunakan ID auto-incremented sebagai kunci utama model untuk hubungan dalaman. Tetapi anda mungkin mahu menggunakan UUID untuk ID yang dihadapi awam. Dalam kes ini, anda mungkin mahu menggunakan medan

untuk mengikat model penghalaan, bukannya medan

. uuid id Begitu juga, jika anda sedang membina blog, anda mungkin ingin mendapatkan jawatan anda berdasarkan bidang

dan bukannya medan

. Ini kerana medan slug lebih mudah dibaca dan lebih mesra SEO daripada ID Auto-Incremented. id slug Tukar semua medan yang diarahkan

Jika anda ingin menentukan bidang yang digunakan untuk semua laluan, anda boleh melakukan ini dengan menentukan kaedah

pada model. Kaedah ini harus mengembalikan nama medan yang ingin anda gunakan untuk mengikat model penghalaan.

Sebagai contoh, kita mahu menukar semua pengikatan model penghalaan untuk model getRouteKeyName untuk menggunakan medan

dan bukannya medan

. Kami boleh melakukan ini dengan menambahkan kaedah AppModelsPost ke model slug kami: id Post getRouteKeyName ini bermakna kita kini boleh menentukan laluan kita seperti ini:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

Apabila kita mengakses url

, Laravel secara automatik akan mendapatkan jawatan
namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
sebagai

dari pangkalan data dan lulus ke fungsi penutupan (atau pengawal) untuk operasi. /posts/my-first-post slug Tukar medan untuk laluan tunggal my-first-post Walau bagaimanapun, kadang -kadang anda mungkin mahu menukar hanya medan yang digunakan dalam satu laluan. Sebagai contoh, anda mungkin mahu menggunakan medan

dalam satu laluan untuk mengikat model penghalaan, tetapi gunakan medan

di semua laluan lain.

kita boleh melakukan ini dengan menggunakan sintaks slug dalam definisi penghalaan kami. Sebagai contoh, katakan kita mahu menggunakan medan id dalam laluan untuk mengikat model penghalaan. Kami boleh menentukan laluan kami seperti ini:

:field Ini sekarang bermakna bahawa dalam laluan tertentu ini, Laravel akan cuba mendapatkan jawatan dari pangkalan data dengan medan slug yang disediakan.

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>
menggunakan koleksi model tersuai

slug Apabila anda menggunakan kaedah seperti

untuk mendapatkan pelbagai model dari pangkalan data, Laravel biasanya akan meletakkannya dalam kelas

kelas. Kelas ini menyediakan banyak kaedah berguna untuk memproses model yang dikembalikan. Walau bagaimanapun, kadang -kadang anda mungkin mahu mengembalikan kelas pengumpulan tersuai dan bukannya kelas pengumpulan lalai.

Anda mungkin mahu membuat koleksi tersuai untuk beberapa sebab. Sebagai contoh, anda mungkin mahu menambah beberapa kaedah penolong khusus untuk mengendalikan model jenis itu. Sebagai alternatif, anda mungkin mahu menggunakannya untuk keselamatan jenis yang lebih baik dan pastikan koleksi itu hanya mengandungi jenis model tertentu. AppModelsUser::all() IlluminateDatabaseEloquentCollection Laravel menjadikannya sangat mudah untuk mengatasi jenis koleksi yang harus dikembalikan.

mari kita lihat contoh. Katakan kami mempunyai model , dan apabila kami mendapatkannya dari pangkalan data, kami ingin mengembalikannya kepada kelas Custom AppModelsPost. AppCollectionsPostCollection 3

Dalam contoh di atas, kami mencipta kelas app/Collections/PostCollection.php yang baru yang memanjangkan kelas Laravel

. Kami juga menyatakan bahawa koleksi ini hanya akan mengandungi contoh kelas
$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
, menggunakan docBlock. Ini berguna untuk membantu IDE anda memahami jenis data yang akan dimasukkan ke dalam koleksi.

AppCollectionsPostCollection kita kemudian boleh mengemas kini model IlluminateSupportCollection kami untuk mengembalikan contoh kelas pengumpulan tersuai dengan mengatasi kaedah AppModelsPost seperti berikut:

AppModelsPost Dalam contoh ini, kita dapatkan array model newCollection yang diluluskan kepada kaedah

dan mengembalikan contoh baru kelas
namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}
.

newCollection Sekarang kita boleh menggunakan kelas pengumpulan tersuai untuk mendapatkan jawatan kami dari pangkalan data, seperti yang ditunjukkan di bawah: AppModelsPost AppCollectionsPostCollection

Model perbandingan

Masalah biasa yang saya ada ketika mengerjakan projek adalah bagaimana membandingkan model. Ini biasanya dalam pemeriksaan kebenaran, apabila anda ingin menyemak sama ada pengguna mempunyai akses kepada sumber.
<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>

mari kita lihat beberapa perangkap biasa dan mengapa anda mungkin harus mengelakkannya.

anda harus mengelakkan menggunakan

apabila memeriksa sama ada kedua -dua model adalah sama. Ini kerana

cek apabila membandingkan objek, memeriksa sama ada mereka adalah contoh objek yang sama. Ini bermakna walaupun kedua -dua model mempunyai data yang sama, mereka tidak akan dianggap sama jika mereka adalah contoh yang berbeza. Oleh itu, anda harus mengelakkan melakukan ini kerana kemungkinan besar akan kembali

.

=== Katakan bahawa hubungan === wujud pada model, dan komen pertama dalam pangkalan data tergolong dalam jawatan pertama, mari kita lihat contoh: false

anda juga harus mengelakkan menggunakan AppModelsComment apabila memeriksa sama ada kedua -dua model adalah sama. Ini kerana pemeriksaan post apabila membandingkan objek akan memeriksa sama ada ia adalah contoh kelas yang sama dan sama ada mereka mempunyai sifat dan nilai yang sama. Walau bagaimanapun, ini boleh membawa kepada tingkah laku yang tidak dijangka.

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Lihat contoh ini:

== == Dalam contoh di atas, cek

akan kembali

kerana

dan
$user = User::query()->first();

$name = $user->full_name;
adalah kelas yang sama dan mempunyai sifat dan nilai yang sama. Tetapi apa yang berlaku jika kita menukar sifat dalam model

untuk menjadikannya berbeza? == true mari kita gunakan kaedah $comment->post supaya kita hanya mendapatkan medan $post dan $post dari Jadual

:

$posts = Post::all();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}

Walaupun $comment->post adalah model yang sama seperti $post, cek == akan kembali false kerana model mempunyai sifat yang dimuatkan yang berbeza. Seperti yang anda boleh bayangkan, ini boleh membawa kepada beberapa tingkah laku yang tidak dapat difahami yang sukar untuk dikesan, terutamanya jika anda telah menambahkan kaedah select secara retroaktif untuk pertanyaan dan ujian anda mula gagal.

Sebaliknya, saya suka menggunakan kaedah is dan isNot yang disediakan oleh Laravel. Kaedah ini membandingkan kedua -dua model dan semak jika mereka tergolong dalam kelas yang sama, mempunyai nilai utama utama yang sama, dan mempunyai sambungan pangkalan data yang sama. Ini adalah cara yang lebih selamat untuk membandingkan model dan akan membantu mengurangkan kemungkinan tingkah laku yang tidak dijangka.

anda boleh menggunakan kaedah is untuk memeriksa sama ada kedua -dua model adalah sama:

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Model::preventLazyLoading();
    }
}

Begitu juga, anda boleh menggunakan kaedah isNot untuk memeriksa sama ada kedua -dua model berbeza:

<code>尝试在模型 [App\Models\Post] 上延迟加载 [user],但延迟加载已禁用。</code>

Gunakan whereBelongsTo

Apabila membina pertanyaan

Trik terakhir adalah lebih seperti keutamaan peribadi, tetapi saya dapati ia membuat pertanyaan saya lebih mudah dibaca dan difahami.

$posts = Post::with('user')->get();

foreach ($posts as $post) {
    // 对帖子执行某些操作...

    // 尝试访问帖子的用户
    echo $post->user->name;
}
Apabila cuba mendapatkan model dari pangkalan data, anda mungkin mendapati diri anda menulis pertanyaan penapisan berasaskan hubungan. Sebagai contoh, anda mungkin ingin mendapatkan semua komen yang dimiliki oleh pengguna dan post tertentu:

whereBelongsTo

Laravel menyediakan kaedah
$user = User::query()->first();

$name = $user->full_name;
yang boleh anda gunakan untuk membuat pertanyaan anda lebih mudah dibaca (pada pendapat saya). Menggunakan kaedah ini, kita boleh menulis semula pertanyaan di atas seperti ini:

Saya suka gula sintaksis ini dan merasakan ia membuat pertanyaan lebih mudah dibaca. Ini juga merupakan cara terbaik untuk memastikan anda menapis berdasarkan hubungan dan bidang yang betul. where

Anda atau pasukan anda mungkin lebih suka menggunakan pendekatan yang lebih jelas untuk menulis

klausa. Oleh itu, teknik ini mungkin tidak sesuai untuk semua orang. Tetapi saya fikir kedua -duanya adalah baik selagi anda mengekalkan pendekatan anda konsisten.

Kesimpulan whereBelongsTo

Harap artikel ini menunjukkan beberapa petua baru untuk menggunakan model Laravel. Anda kini boleh menemui dan mencegah isu n 1, mencegah akses kepada sifat yang hilang, mencegah sifat membuang secara senyap -senyap, dan menukar jenis utama utama ke UUID atau ULID. Anda juga harus tahu cara menukar medan yang digunakan untuk pengikatan model penghalaan, tentukan jenis koleksi yang dikembalikan, bandingkan model, dan gunakan apabila membina pertanyaan.

Atas ialah kandungan terperinci Petua Model Laravel. 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