рд▓рд╛рд░рд╡реЗрд▓ рдореЗрдВ рдмрд╣реБрд░реВрдкреА рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рдХреНрд╖рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛

рдкрд░рд┐рдЪрдп


рдЪрд▓реЛ рд▓рд╛рд░рд╡реЗрд▓ рдореЗрдВ рдмрд╣реБрд░реВрдкреА рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд╕рд╛рде рд▓рдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВред


рд▓реЗрдЦ рдХреА рд╕рд╛рдордЧреНрд░реА:


  1. рдбреЛрдореЗрди рд╡рд┐рд╡рд░рдг
  2. рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд┐рд░реНрдорд╛рдг
  3. рд╕рдВрднрд╡ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдВрд░рдЪрдирд╛рдПрдБ
  4. рдЗрдХрд╛рдИ рдирд┐рд░реНрдорд╛рдг
  5. рд▓рдХреНрд╖рдг рдЙрдкрдпреЛрдЧ
  6. рд▓реЗрдЦрди рдкрд░реАрдХреНрд╖рдг

рдбреЛрдореЗрди рд╡рд┐рд╡рд░рдг


рд╣рдо рдПрдХ рдкреНрд░рдгрд╛рд▓реА рд╡рд┐рдХрд╕рд┐рдд рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рдХреБрдЫ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдФрд░ рдХреБрдЫ рдЯреАрдореЛрдВ рдХреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░ рдХрд╛ рд╕рд╛рд░ рдХрд░реНрдордЪрд╛рд░реА, рдЯреАрдо рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ рд╣реЛрдЧрд╛: рдПрдХ рдЯреАрдо рдореЗрдВ рдХрд░реНрдордЪрд╛рд░реА рд╣реЛрддреЗ рд╣реИрдВ, рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдФрд░ рдЯреАрдореЛрдВ рдХреЛ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рдЯреАрдо рдФрд░ рдПрдХ рдХрд░реНрдордЪрд╛рд░реА рдХреЗ рдмреАрдЪ, рдХрдИ-рд╕реЗ-рдХрдИ рд╕рдВрдмрдВрдз (рдЪрд▓реЛ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдХрд░реНрдордЪрд╛рд░реА рд╡рд┐рднрд┐рдиреНрди рдЯреАрдореЛрдВ рдореЗрдВ рднрд╛рдЧ рд▓реЗ рд╕рдХрддрд╛ рд╣реИ), рдХрдИ-рд╕реЗ-рдХрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдФрд░ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ, рдХрдИ-рд╕реЗ-рдХрдИ рдЯреАрдореЛрдВ рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдмреАрдЪред рдЖрдЧреЗ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП, рдЯреАрдо рдФрд░ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдЯреАрдореЛрдВ рдФрд░ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред


рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд┐рд░реНрдорд╛рдг


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
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    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();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    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
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    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');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    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'];

    /**
     * Relation for project attachments
     * @return HasMany
     */
    public function attachments()
    {
        return $this->hasMany(Attach::class);
    }

    /**
     * Relation for project employees
     * @return MorphToMany
     */
    public function employees()
    {
        return $this->morphedByMany(Employee::class, 'attachable', 'attachments');
    }

    /**
     * Relation for project teams
     * @return MorphToMany
     */
    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

/** @var \Illuminate\Database\Eloquent\Factory $factory */

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
{
    /**
     * Relation for entity attachments
     * @return MorphToMany
     */
    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;

    /** @test */
    public function polymorphic_relations_scheme(): void
    {
        // Given project
        $project = factory(Project::class)->create();
        // Given team
        $team = factory(Team::class)->create();
        // Given employee
        $employee = factory(Employee::class)->create();

        // When we add team and employee to project
        $project->teams()->save($team);
        $project->employees()->save($employee);

        // Then project should have two attachments
        $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);
        // Team and employee should have attachment to project
        $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);
    }
}

рдЗрдореНрддрд┐рд╣рд╛рди рдкрд╛рд╕ рд╣реЛ рдЧрдпрд╛!


рд▓рдХреНрд╖рдг рдЖрдкрдХреЛ рдореЙрдбрд▓ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рднреАрддрд░ рдмрд╣реБрд░реВрдкреА рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЛрдВ рдХреА рдирдХрд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЖрдк рдЙрдиреНрд╣реЗрдВ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХрдИ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рд╕рдорд╛рди рдлрд╝реАрд▓реНрдб рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд▓реЗрдЦрдХ) - рдпрд╣рд╛рдВ рдЖрдк рдХрдиреЗрдХреНрд╢рди рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рднреА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред


рд▓рд╛рд░рд╡реЗрд▓ рдФрд░ рдкреАрдПрдЪрдкреА рдореЗрдВ рд▓рдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЖрдкрдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕реБрдирдХрд░ рдореБрдЭреЗ рдЦреБрд╢реА рд╣реЛрдЧреАред


All Articles