المقدمة
لنتحدث عن الاستخدام المحتمل للسمات جنبًا إلى جنب مع العلاقات متعددة الأشكال في Laravel.
محتوى المقالة:
- وصف المجال
- إنشاء التطبيق
- هياكل قاعدة البيانات الممكنة
- إنشاء الكيان
- استخدام السمات
- اختبارات الكتابة
وصف المجال
سنضع نظامًا يمكن فيه إلحاق بعض الموظفين وفرق معينة بالمشروع. سيكون جوهر الموضوع هو الموظفين والفرق والمشاريع: يتكون الفريق من الموظفين والموظفين والفرق ويمكن إرفاقه بالمشروع. بين فريق وموظف ، علاقة أطراف بأطراف (دعنا نقول أنه يمكن لموظف المشاركة في فرق مختلفة) ، بين أطراف وأخرى بين المشاريع والموظفين ، والعديد من بين الفرق والمشاريع. لمزيد من الدراسة ، دعنا نحذف تنفيذ التواصل بين الفريق والموظفين ، ونركز على موقف الفرق والموظفين تجاه المشروع.
إنشاء التطبيق
من السهل جدًا إنشاء تطبيقات Laravel باستخدام حزمة صانع التطبيقات . بعد تثبيته ، يتناسب إنشاء تطبيق جديد مع أمر واحد:
laravel new system
هياكل قاعدة البيانات الممكنة
, : -, -, -.
, - - , (, 1 — , 2 — ).
- , — , .
, , , . :
php artisan make:model Employee -f //    
php artisan make:model Team -f //    
php artisan make:model Project -f //    
php artisan make:migration CreateEntitiesTables //     
php artisan make:model Attach -m //    
App/, database/migrations/ database/factories/.
. , : , . — .
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateEntitesTables extends Migration
{
    
    public function up()
    {
        Schema::create('employees', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
        Schema::create('teams', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
        Schema::create('projects', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }
    
    public function down()
    {
        Schema::dropIfExists('employees');
        Schema::dropIfExists('teams');
        Schema::dropIfExists('projects');
    }
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAttachesTable extends Migration
{
    
    public function up()
    {
        Schema::create('attachments', function (Blueprint $table) {
            $table->id();
            $table->morphs('attachable');
            $table->unsignedInteger('project_id');
            $table->timestamps();
            $table->foreign('project_id')->references('id')->on('projects')
                ->onDelete('cascade');
        });
    }
    
    public function down()
    {
        Schema::dropIfExists('attachments');
    }
}
, morphs().
:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
    protected $fillable = ['name'];
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
    protected $fillable = ['name'];
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
class Project extends Model
{
    protected $fillable = ['name'];
    
    public function attachments()
    {
        return $this->hasMany(Attach::class);
    }
    
    public function employees()
    {
        return $this->morphedByMany(Employee::class, 'attachable', 'attachments');
    }
    
    public function teams()
    {
        return $this->morphedByMany(Team::class, 'attachable', 'attachments');
    }    
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Attach extends Model
{
    protected $table = 'attachments';
    protected $fillable = ['attachable_id', 'attachable_type', 'project_id'];
}
<?php
use Faker\Generator as Faker;
$factory->define(, function (Faker $faker) {
    return [
        'name' => $faker->colorName
    ];
});
, .
Laravel — morphedByMany(), — morphToMany(). , .
app/Traits : Attachable.php
<?php
namespace App\Traits;
use App\Project;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
trait Attachable
{
    
    public function attachments()
    {
        return $this->morphToMany(Project::class, 'attachable', 'attachments');
    }
}
use.
...
    use Attachable;
...
.
, Laravel PHPUnit . :
php artisan make:test AttachableTest
tests/Feature/. RefreshDatabase.
تحقق من الشكل على جانب المشروع والسمات من جانب الفريق والموظفين
<?php
namespace Tests\Feature;
use App\Team;
use App\Employee;
use App\Project;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class OrderTest extends TestCase
{
    use RefreshDatabase;
    
    public function polymorphic_relations_scheme(): void
    {
        
        $project = factory(Project::class)->create();
        
        $team = factory(Team::class)->create();
        
        $employee = factory(Employee::class)->create();
        
        $project->teams()->save($team);
        $project->employees()->save($employee);
        
        $this->assertCount(2, $project->attachments);
        $this->assertCount(1, $project->teams);
        $this->assertCount(1, $project->employees);
        $this->assertEquals($team->id, $project->teams->first()->id);
        $this->assertEquals($employee->id, $project->employees->first()->id);
        
        $this->assertCount(1, $team->attachments);
        $this->assertCount(1, $employee->attachments);
        $this->assertEquals($project->id, $team->attachments->first()->id);
        $this->assertEquals($project->id, $employee->attachments->first()->id);
    }
}
لقد مر الاختبار!
تسمح لك السمات بعدم تكرار الطرق الشائعة للعلاقات متعددة الأشكال داخل فئات النموذج ، يمكنك أيضًا استخدامها إذا كان لديك نفس الحقول في العديد من الجداول (على سبيل المثال ، مؤلف السجل) - هنا يمكنك أيضًا إنشاء سمة باستخدام طريقة الاتصال.
سأكون سعيدًا لسماع حالاتك المتعلقة باستخدام السمات في Laravel و PHP.