рдкрд░рд┐рдЪрдп
рдЪрд▓реЛ рд▓рд╛рд░рд╡реЗрд▓ рдореЗрдВ рдмрд╣реБрд░реВрдкреА рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд╕рд╛рде рд▓рдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВред
рд▓реЗрдЦ рдХреА рд╕рд╛рдордЧреНрд░реА:
- рдбреЛрдореЗрди рд╡рд┐рд╡рд░рдг
- рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд┐рд░реНрдорд╛рдг
- рд╕рдВрднрд╡ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рдВрд░рдЪрдирд╛рдПрдБ
- рдЗрдХрд╛рдИ рдирд┐рд░реНрдорд╛рдг
- рд▓рдХреНрд╖рдг рдЙрдкрдпреЛрдЧ
- рд▓реЗрдЦрди рдкрд░реАрдХреНрд╖рдг
рдбреЛрдореЗрди рд╡рд┐рд╡рд░рдг
рд╣рдо рдПрдХ рдкреНрд░рдгрд╛рд▓реА рд╡рд┐рдХрд╕рд┐рдд рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рдХреБрдЫ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдФрд░ рдХреБрдЫ рдЯреАрдореЛрдВ рдХреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░ рдХрд╛ рд╕рд╛рд░ рдХрд░реНрдордЪрд╛рд░реА, рдЯреАрдо рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдПрдВ рд╣реЛрдЧрд╛: рдПрдХ рдЯреАрдо рдореЗрдВ рдХрд░реНрдордЪрд╛рд░реА рд╣реЛрддреЗ рд╣реИрдВ, рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдФрд░ рдЯреАрдореЛрдВ рдХреЛ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдПрдХ рдЯреАрдо рдФрд░ рдПрдХ рдХрд░реНрдордЪрд╛рд░реА рдХреЗ рдмреАрдЪ, рдХрдИ-рд╕реЗ-рдХрдИ рд╕рдВрдмрдВрдз (рдЪрд▓реЛ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдХрд░реНрдордЪрд╛рд░реА рд╡рд┐рднрд┐рдиреНрди рдЯреАрдореЛрдВ рдореЗрдВ рднрд╛рдЧ рд▓реЗ рд╕рдХрддрд╛ рд╣реИ), рдХрдИ-рд╕реЗ-рдХрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдФрд░ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ, рдХрдИ-рд╕реЗ-рдХрдИ рдЯреАрдореЛрдВ рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдмреАрдЪред рдЖрдЧреЗ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП, рдЯреАрдо рдФрд░ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВ, рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдЯреАрдореЛрдВ рдФрд░ рдХрд░реНрдордЪрд╛рд░рд┐рдпреЛрдВ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред
рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдирд┐рд░реНрдорд╛рдг
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);
}
}
рдЗрдореНрддрд┐рд╣рд╛рди рдкрд╛рд╕ рд╣реЛ рдЧрдпрд╛!
рд▓рдХреНрд╖рдг рдЖрдкрдХреЛ рдореЙрдбрд▓ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рднреАрддрд░ рдмрд╣реБрд░реВрдкреА рд╕рдВрдмрдВрдзреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЛрдВ рдХреА рдирдХрд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЖрдк рдЙрдиреНрд╣реЗрдВ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХрдИ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдореЗрдВ рд╕рдорд╛рди рдлрд╝реАрд▓реНрдб рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░рд┐рдХреЙрд░реНрдб рдХреЗ рд▓реЗрдЦрдХ) - рдпрд╣рд╛рдВ рдЖрдк рдХрдиреЗрдХреНрд╢рди рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рднреА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рд▓рд╛рд░рд╡реЗрд▓ рдФрд░ рдкреАрдПрдЪрдкреА рдореЗрдВ рд▓рдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЖрдкрдХреЗ рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕реБрдирдХрд░ рдореБрдЭреЗ рдЦреБрд╢реА рд╣реЛрдЧреАред