How can I create a dual has_many relationship in Laravel? - database

I have a database with a Employee table and a Customer table. The Employee table has 2 one_to_many relationships with the Customer table; the foreign keys in the Customer table are 'primary_sales_contact_id' and 'primary_service_contact_id'. Both obviously refer to the id field on the Employee table.
How do I set up a migration for this, and how would I subsequently create a model for it? I'm a newbie in Laravel, so apologies if its blindingly obvious, and thanks for your time.

Employee migration
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEmpoyeeTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('employee', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('employee');
}
}
Customer migration
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCustomerTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('customer', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->integer('primary_sales_contact_id')->unsigned();
$table->integer('primary_service_contact_id')->unsigned();
$table->foreign('primary_sales_contact_id')->references('id')->on('employee');
$table->foreign('primary_service_contact_id')->references('id')->on('employee');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('customer');
}
}
Employee model
class Employee extends Eloquent
{
protected $table = 'employee';
public $timestamps = false;
public function customersService() {
return $this->hasMany('Customer', 'primary_service_contact_id');
}
public function customersSale() {
return $this->hasMany('Customer', 'primary_sales_contact_id');
}
}
Customer model
class Customer extends Eloquent
{
protected $table = 'customer';
public $timestamps = false;
public function primarySalesContact() {
return $this->belongsTo('Employee', 'primary_sales_contact_id');
}
public function primaryServiceContact() {
return $this->belongsTo('Employee', 'primary_service_contact_id');
}
}
All stuff use like:
$customer = Customer::find(1);
echo $customer->primaryServiceContact;
$employee = Employee::find(1);
echo $employee->customersSale;

Related

Laravel Virgin: Access inverse model relationship in a model's mutator that participate in the relationship

In my logic I have these tables:
Table Grid:
id PK
width INT
height INT
Table Rover:
id pk
grid_pos_x UNSIGNED INT
grid_pos_y UNSIGNED INT
grid_id UNSINGED BIGINT
NOTE: I kept minimal in order to be more explanatory, for full table specs look on migration scripts below.
And I use the following migration script to create the schemas:
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateGridTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('grid', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('width');
$table->unsignedInteger('height');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('grid');
}
}
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRoverTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('rover', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('grid_id')->unsigned();
$table->string('command');
$table->foreign('grid_id')->references('id')->on('grid');
$table->smallInteger('last_commandPos')->unsigned()->default(0);
$table->smallInteger('grid_pos_x')->unsigned();
$table->smallInteger('grid_pos_y')->unsigned();
$table->enum('rotation', App\Constants\RoverConstants::ORIENTATIONS);
$table->string('last_command');
Schema::enableForeignKeyConstraints();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('rover');
}
}
And I try to model the table rover with the following model:
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use App\Model\Grid;
class Rover extends Model
{
/**
* Table Name
*/
protected $table='rover';
public function grid()
{
return $this->belongsTo(Grid::class);
}
public function setGridPosXValue($value)
{
}
public function setGridPosYValue($value)
{
}
}
And in a similar fashion the Grid model as well:
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use App\Model\Rover;
class Grid extends Model
{
/**
* Table Name
*/
protected $table='grid';
public function rovers()
{
return $this->hasMany(Rover::class);
}
}
What I want to achieve is to access the width and height attributes from the Grid in order to check whether the grid_pos_x and grid_pos_y are smaller from the width and height using the methods setGridPosXValue and the setGridPosYValue respectively.
Do you know how to do that?
Looks like you have a one to many relationship setup here: https://laravel.com/docs/5.8/eloquent-relationships#one-to-many
To get the grid for a rover you can access it in multiple ways:
Directly:
$width = $Rover->grid->width;
$height = $Rover->grid->height;
With the builder methods:
$Grid = $Rover->grid()->first();
$width = $Grid->width;
$height = $Grid->height;

Why there is 2 primary keys in table (Sentinel framework database)?

i included SENTINEL framework with implemented Sentinel migration into my LARAVEL project. Lot of things are clear to me but i can't understand why there is 2 primary keys in Role_users table, because i learned that for connection between 2 tables we need primary key and foreign key which is not a case here (role_users table). If someone knows explanation It would mean a lot to me.
my Database Scheme
Php my admin scheme
migration_cartalyst_sentinel
<?php
/**
* Part of the Sentinel package.
*
* NOTICE OF LICENSE
*
* Licensed under the 3-clause BSD License.
*
* This source file is subject to the 3-clause BSD License that is
* bundled with this package in the LICENSE file.
*
* #package Sentinel
* #version 2.0.17
* #author Cartalyst LLC
* #license BSD License (3-clause)
* #copyright (c) 2011-2017, Cartalyst LLC
* #link http://cartalyst.com
*/
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class MigrationCartalystSentinel extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('activations', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('code');
$table->boolean('completed')->default(0);
$table->timestamp('completed_at')->nullable();
$table->timestamps();
$table->engine = 'InnoDB';
});
Schema::create('persistences', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('code');
$table->timestamps();
$table->engine = 'InnoDB';
$table->unique('code');
});
Schema::create('reminders', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('code');
$table->boolean('completed')->default(0);
$table->timestamp('completed_at')->nullable();
$table->timestamps();
$table->engine = 'InnoDB';
});
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('slug');
$table->string('name');
$table->text('permissions')->nullable();
$table->timestamps();
$table->engine = 'InnoDB';
$table->unique('slug');
});
Schema::create('role_users', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->nullableTimestamps();
$table->engine = 'InnoDB';
$table->primary(['user_id', 'role_id']);
});
Schema::create('throttle', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->string('type');
$table->string('ip')->nullable();
$table->timestamps();
$table->engine = 'InnoDB';
$table->index('user_id');
});
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email');
$table->string('password');
$table->text('permissions')->nullable();
$table->timestamp('last_login')->nullable();
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->timestamps();
$table->engine = 'InnoDB';
$table->unique('email');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('activations');
Schema::drop('persistences');
Schema::drop('reminders');
Schema::drop('roles');
Schema::drop('role_users');
Schema::drop('throttle');
Schema::drop('users');
}
}
EloquentUser
<?php
/**
* Part of the Sentinel package.
*
* NOTICE OF LICENSE
*
* Licensed under the 3-clause BSD License.
*
* This source file is subject to the 3-clause BSD License that is
* bundled with this package in the LICENSE file.
*
* #package Sentinel
* #version 2.0.17
* #author Cartalyst LLC
* #license BSD License (3-clause)
* #copyright (c) 2011-2017, Cartalyst LLC
* #link http://cartalyst.com
*/
namespace Cartalyst\Sentinel\Users;
use Cartalyst\Sentinel\Permissions\PermissibleInterface;
use Cartalyst\Sentinel\Permissions\PermissibleTrait;
use Cartalyst\Sentinel\Persistences\PersistableInterface;
use Cartalyst\Sentinel\Roles\RoleableInterface;
use Cartalyst\Sentinel\Roles\RoleInterface;
use Illuminate\Database\Eloquent\Model;
class EloquentUser extends Model implements RoleableInterface, PermissibleInterface, PersistableInterface, UserInterface
{
use PermissibleTrait;
/**
* {#inheritDoc}
*/
protected $table = 'users';
/**
* {#inheritDoc}
*/
protected $fillable = [
'email',
'password',
'last_name',
'first_name',
'permissions',
];
/**
* {#inheritDoc}
*/
protected $hidden = [
'password',
];
/**
* {#inheritDoc}
*/
protected $persistableKey = 'user_id';
/**
* {#inheritDoc}
*/
protected $persistableRelationship = 'persistences';
/**
* Array of login column names.
*
* #var array
*/
protected $loginNames = ['email'];
/**
* The Eloquent roles model name.
*
* #var string
*/
protected static $rolesModel = 'Cartalyst\Sentinel\Roles\EloquentRole';
/**
* The Eloquent persistences model name.
*
* #var string
*/
protected static $persistencesModel = 'Cartalyst\Sentinel\Persistences\EloquentPersistence';
/**
* The Eloquent activations model name.
*
* #var string
*/
protected static $activationsModel = 'Cartalyst\Sentinel\Activations\EloquentActivation';
/**
* The Eloquent reminders model name.
*
* #var string
*/
protected static $remindersModel = 'Cartalyst\Sentinel\Reminders\EloquentReminder';
/**
* The Eloquent throttling model name.
*
* #var string
*/
protected static $throttlingModel = 'Cartalyst\Sentinel\Throttling\EloquentThrottle';
/**
* Returns an array of login column names.
*
* #return array
*/
public function getLoginNames()
{
return $this->loginNames;
}
/**
* Returns the roles relationship.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function roles()
{
return $this->belongsToMany(static::$rolesModel, 'role_users', 'user_id', 'role_id')->withTimestamps();
}
/**
* Returns the persistences relationship.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function persistences()
{
return $this->hasMany(static::$persistencesModel, 'user_id');
}
/**
* Returns the activations relationship.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function activations()
{
return $this->hasMany(static::$activationsModel, 'user_id');
}
/**
* Returns the reminders relationship.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function reminders()
{
return $this->hasMany(static::$remindersModel, 'user_id');
}
/**
* Returns the throttle relationship.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function throttle()
{
return $this->hasMany(static::$throttlingModel, 'user_id');
}
/**
* Get mutator for the "permissions" attribute.
*
* #param mixed $permissions
* #return array
*/
public function getPermissionsAttribute($permissions)
{
return $permissions ? json_decode($permissions, true) : [];
}
/**
* Set mutator for the "permissions" attribute.
*
* #param mixed $permissions
* #return void
*/
public function setPermissionsAttribute(array $permissions)
{
$this->attributes['permissions'] = $permissions ? json_encode($permissions) : '';
}
/**
* {#inheritDoc}
*/
public function getRoles()
{
return $this->roles;
}
/**
* {#inheritDoc}
*/
public function inRole($role)
{
if ($role instanceof RoleInterface) {
$roleId = $role->getRoleId();
}
foreach ($this->roles as $instance) {
if ($role instanceof RoleInterface) {
if ($instance->getRoleId() === $roleId) {
return true;
}
} else {
if ($instance->getRoleId() == $role || $instance->getRoleSlug() == $role) {
return true;
}
}
}
return false;
}
/**
* {#inheritDoc}
*/
public function generatePersistenceCode()
{
return str_random(32);
}
/**
* {#inheritDoc}
*/
public function getUserId()
{
return $this->getKey();
}
/**
* {#inheritDoc}
*/
public function getPersistableId()
{
return $this->getKey();
}
/**
* {#inheritDoc}
*/
public function getPersistableKey()
{
return $this->persistableKey;
}
/**
* {#inheritDoc}
*/
public function setPersistableKey($key)
{
$this->persistableKey = $key;
}
/**
* {#inheritDoc}
*/
public function setPersistableRelationship($persistableRelationship)
{
$this->persistableRelationship = $persistableRelationship;
}
/**
* {#inheritDoc}
*/
public function getPersistableRelationship()
{
return $this->persistableRelationship;
}
/**
* {#inheritDoc}
*/
public function getUserLogin()
{
return $this->getAttribute($this->getUserLoginName());
}
/**
* {#inheritDoc}
*/
public function getUserLoginName()
{
return reset($this->loginNames);
}
/**
* {#inheritDoc}
*/
public function getUserPassword()
{
return $this->password;
}
/**
* Returns the roles model.
*
* #return string
*/
public static function getRolesModel()
{
return static::$rolesModel;
}
/**
* Sets the roles model.
*
* #param string $rolesModel
* #return void
*/
public static function setRolesModel($rolesModel)
{
static::$rolesModel = $rolesModel;
}
/**
* Returns the persistences model.
*
* #return string
*/
public static function getPersistencesModel()
{
return static::$persistencesModel;
}
/**
* Sets the persistences model.
*
* #param string $persistencesModel
* #return void
*/
public static function setPersistencesModel($persistencesModel)
{
static::$persistencesModel = $persistencesModel;
}
/**
* Returns the activations model.
*
* #return string
*/
public static function getActivationsModel()
{
return static::$activationsModel;
}
/**
* Sets the activations model.
*
* #param string $activationsModel
* #return void
*/
public static function setActivationsModel($activationsModel)
{
static::$activationsModel = $activationsModel;
}
/**
* Returns the reminders model.
*
* #return string
*/
public static function getRemindersModel()
{
return static::$remindersModel;
}
/**
* Sets the reminders model.
*
* #param string $remindersModel
* #return void
*/
public static function setRemindersModel($remindersModel)
{
static::$remindersModel = $remindersModel;
}
/**
* Returns the throttling model.
*
* #return string
*/
public static function getThrottlingModel()
{
return static::$throttlingModel;
}
/**
* Sets the throttling model.
*
* #param string $throttlingModel
* #return void
*/
public static function setThrottlingModel($throttlingModel)
{
static::$throttlingModel = $throttlingModel;
}
/**
* {#inheritDoc}
*/
public function delete()
{
$isSoftDeleted = array_key_exists('Illuminate\Database\Eloquent\SoftDeletes', class_uses($this));
if ($this->exists && ! $isSoftDeleted) {
$this->activations()->delete();
$this->persistences()->delete();
$this->reminders()->delete();
$this->roles()->detach();
$this->throttle()->delete();
}
return parent::delete();
}
/**
* Dynamically pass missing methods to the user.
*
* #param string $method
* #param array $parameters
* #return mixed
*/
public function __call($method, $parameters)
{
$methods = ['hasAccess', 'hasAnyAccess'];
if (in_array($method, $methods)) {
$permissions = $this->getPermissionsInstance();
return call_user_func_array([$permissions, $method], $parameters);
}
return parent::__call($method, $parameters);
}
/**
* Creates a permissions object.
*
* #return \Cartalyst\Sentinel\Permissions\PermissionsInterface
*/
protected function createPermissions()
{
$userPermissions = $this->permissions;
$rolePermissions = [];
foreach ($this->roles as $role) {
$rolePermissions[] = $role->permissions;
}
return new static::$permissionsClass($userPermissions, $rolePermissions);
}
}
Role_users is used as a pivot table in this case; it's the intermediate table in the many-to-many relationship between Users and Roles. A User can belong to many Roles, and a Role can belong to many Users.
The composite primary key on Role_users ensures that no User will have the same Role twice, and vice versa. The primary key is a unique combination of the user_id and role_id.

Laravel 5 - Blob doesn't retrive an image right

I'm using Laravel to store an image (generated from a canvas) but when I retrieve the value from the column and I pass it to the "src" attribute of an block it doesn't load and into the browser console I see the error
"Failed to load resource: net::ERR_INVALID_URL"
migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTblTaccuinoTable extends Migration
{
/**
* Schema table name to migrate
* #var string
*/
public $set_schema_table = 'tbl_taccuino';
/**
* Run the migrations.
* #table tbl_taccuino
*
* #return void
*/
public function up()
{
if (Schema::hasTable($this->set_schema_table)) return;
Schema::create($this->set_schema_table, function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id_taccuino');
$table->integer('id_paziente')->unsigned();
$table->string('taccuino_descrizione', 45);
$table->date('taccuino_data');
$table->binary('taccuino_report_anteriore');
$table->binary('taccuino_report_posteriore');
$table->index(["id_paziente"], 'fk_tbl_taccuino_tbl_pazienti1_idx');
$table->foreign('id_paziente', 'fk_tbl_taccuino_tbl_pazienti1_idx')
->references('id_paziente')->on('tbl_pazienti')
->onDelete('no action')
->onUpdate('no action');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists($this->set_schema_table);
}
}
Model
<?php
/**
* Created by Reliese Model.
* Date: Mon, 25 Dec 2017 12:47:05 +0000.
*/
namespace App\Models\Patient;
use Reliese\Database\Eloquent\Model as Eloquent;
/**
* Class Taccuino
*
* #property int $id_taccuino
* #property int $id_paziente
* #property string $taccuino_descrizione
* #property \Carbon\Carbon $taccuino_data
* #property boolean $taccuino_report_anteriore
* #property boolean $taccuino_report_posteriore
*
* #property \App\Models\Pazienti $tbl_pazienti
*
* #package App\Models
*/
class Taccuino extends Eloquent
{
protected $table = 'tbl_taccuino';
protected $primaryKey = 'id_taccuino';
public $incrementing = false;
public $timestamps = false;
protected $casts = [
'id_taccuino' => 'int',
'id_paziente' => 'int',
];
protected $dates = [
'taccuino_data'
];
protected $fillable = [
'id_paziente',
'taccuino_descrizione',
'taccuino_data',
'taccuino_report_anteriore',
'taccuino_report_posteriore'
];
public function tbl_pazienti()
{
return $this->belongsTo(\App\Models\Patient\Pazienti::class, 'id_paziente');
}
}
Inside my blade view
<img id="canvas_dolore" class="M" src="{{$record->taccuino_report_anteriore }}"></img>
PS: The blob string value starts with
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA..."
You might try outputting unescaped src values for the image:
<img src="{!! ... !!}">

Does Sonata admin work with self generated entity ids?

Does Sonata admin work self generated entity ids? I have the following entity which uses the Uuid library to generate its own id but when I try to create a new Group using Sonata admin it gets confused and thinks I am editing an existing entity and not creating a new one.
<?php declare(strict_types=1);
namespace App\Entity;
use App\Value\StartEndTime;
use App\Exception\GroupInactiveException;
use Ramsey\Uuid\Uuid;
use Assert\Assertion;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
class Group
{
/** #var string */
private $id;
/** #var string */
private $title;
/** #var string */
private $description;
/** #var User */
private $admin;
/** #var Collection */
private $members;
/** #var Collection */
private $invites;
/** #var StartEndTime */
private $startEndTime;
/** #var StartEndTime */
private $eventStartEndTime;
public function __construct()
{
$this->id = Uuid::uuid4()->toString();
$this->members = new ArrayCollection();
$this->invites = new ArrayCollection();
}
public function getId(): string
{
return $this->id;
}
public function getTitle()
{
return $this->title;
}
public function setTitle(string $title)
{
Assertion::notEmpty($title, 'Title is not specified');
$this->title = $title;
return $this;
}
public function getDescription()
{
return $this->description;
}
public function setDescription(string $description)
{
Assertion::notEmpty($description, 'Description is not specified');
$this->description = $description;
return $this;
}
public function getStartEndTime()
{
return $this->startEndTime;
}
public function setStartEndTime(StartEndTime $startEndTime)
{
$this->startEndTime = $startEndTime;
return $this;
}
public function getEventStartEndTime()
{
return $this->eventStartEndTime;
}
public function setEventStartEndTime(StartEndTime $startEndTime)
{
$this->eventStartEndTime = $startEndTime;
return $this;
}
}

Symfony entity set array as single entity elements

i have problem, i would to add prototype array to database but this show me this error:
Expected argument of type "AppBundle\Entity\Tag", "array" given
...
Post ->setTag (array(array('value' => 'test'), array('value' => 'tess')))
here is my setter for tag:
public function setTag(\AppBundle\Entity\Tag $tag = null)
{
$this->tag = $tag;
return $this;
}
I Have two entities with relation, here relation:
class Post
{
/**
* #ORM\ManyToMany(targetEntity="Tag", inversedBy="post")
* #ORM\JoinColumn(name="tag_id", referencedColumnName="id")
*/
private $tag;
public function setTag(\AppBundle\Entity\Tag $tag = null)
{
$this->tag = $tag;
return $this;
}
}
and tag:
class Tag
{
/**
* #ORM\ManyToMany(targetEntity="Post", mappedBy="tag")
*/
private $post;
}
Source:
http://snipet.co.uk/kR
http://snipet.co.uk/gcf
http://snipet.co.uk/0VI
You're trying to model a bidirectional many-to-many relation between Post and Tag.
So, first of all, your getters need to return a collection of objects, and your setters need to accept a collection of objects - not only one single object as in your code (your setTag method accepts a parameter of type Tag - but you need an array-like parameter).
Secondly, the Doctrine framework does not work with simple PHP arrays, but with implementations of \Doctrine\Common\Collections\Collection.
Next, you need to initialize your collection fields in the constructors of your entity classes with an implementation of the Collection class - you can use \Doctrine\Common\Collections\ArrayCollection.
So your entity classes should look rather like this:
/**
* #ORM\Entity
*/
class Post
{
/**
* #ORM\ManyToMany(targetEntity="Tag", inversedBy="posts")
* #ORM\JoinTable(name="posts_tags")
*/
private $tags;
public function __construct()
{
$this->tags = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getTags()
{
return $this->tags;
}
public function setTags(\Doctrine\Common\Collections\Collection $tags)
{
$this->tags = $tags;
}
}
/**
* #ORM\Entity
*/
class Tag
{
/**
* #ORM\ManyToMany(targetEntity="Post", mappedBy="tags")
*/
private $posts;
public function __construct()
{
$this->posts = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getPosts()
{
return $this->posts;
}
public function setPosts(\Doctrine\Common\Collections\Collection $posts)
{
$this->posts = $posts;
}
}
I strongly advise you to read once again the documentation of the Doctrine framework, how to annotate your entities, and how to model relations: http://doctrine-orm.readthedocs.io/projects/doctrine-orm/en/latest/reference/association-mapping.html

Resources