Einführung
Lassen Sie uns über die mögliche Verwendung von Merkmalen zusammen mit polymorphen Beziehungen in Laravel sprechen.
Der Inhalt des Artikels:
- Domänenbeschreibung
- Anwendungserstellung
- Mögliche Datenbankstrukturen
- Entitätserstellung
- Verwendung von Merkmalen
- Tests schreiben
Domänenbeschreibung
Wir werden ein System entwickeln, in dem einige Mitarbeiter und bestimmte Teams an das Projekt angeschlossen werden können. Das Wesentliche des Themenbereichs sind Mitarbeiter, Teams und Projekte: Ein Team besteht aus Mitarbeitern, Mitarbeiter und Teams können einem Projekt zugeordnet werden. Zwischen einem Team und einem Mitarbeiter eine Viele-zu-Viele-Beziehung (sagen wir, ein Mitarbeiter kann an verschiedenen Teams teilnehmen), Viele-zu-Viele zwischen Projekten und Mitarbeitern, Viele-zu-Viele zwischen Teams und Projekten. Lassen Sie zur weiteren Überlegung die Implementierung der Kommunikation zwischen Team und Mitarbeitern weg und konzentrieren Sie sich auf die Einstellung von Teams und Mitarbeitern zum Projekt.
Anwendungserstellung
Laravel-Anwendungen lassen sich mit dem Application Maker-Paket sehr einfach erstellen . Nach der Installation passt das Erstellen einer neuen Anwendung in einen Befehl:
laravel new system
Mögliche Datenbankstrukturen
, : -, -, -.
, - - , (, 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.
Überprüfen Sie den Morph auf der Projektseite und die Eigenschaften des Teams und der Mitarbeiter
<?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);
}
}
Der Test ist bestanden!
Mit Merkmalen können Sie keine gängigen Methoden für polymorphe Beziehungen innerhalb von Modellklassen duplizieren. Sie können sie auch verwenden, wenn Sie in vielen Tabellen dieselben Felder haben (z. B. der Autor des Datensatzes). Hier können Sie auch ein Merkmal mit der Verbindungsmethode erstellen.
Ich werde mich freuen, Ihre Fälle von Merkmalen in Laravel und PHP zu hören.