Relationship 1:1 Laravel
Following the documentation and comments, the models
and migrations
need to be changed to fit the relationship 1:1 proposed by eloquent.
Relação
Migrations
Usuario (Users)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class Users extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 150);
$table->string('username', 20)->unique();
$table->string('email', 100)->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
}
Teachers (Teacher)
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class Teacher extends Migration
{
public function up()
{
Schema::create('teachers', function (Blueprint $table) {
$table->integer('userid')
->unsigned();
$table->primary('userid');
$table->date('birth');
$table->string('about');
$table->foreign('userid')
->references('id')
->on('users');
$table->timestamps();
});
}
public function down()
{
Schema::drop('teachers');
}
}
The great change in migration
is in regards Teacher
, the key to the relationship cannot be self-improvement, because it receives the key value of the relationship with User
and is the primary key table teachers
. Summarizing the table/field users.id
relates to teachers.userid
, thus generating a relationship 1:1.
Models
User
<?php namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
//configurações a serem observadas
protected $primaryKey = "id";
protected $table = "users";
public $incrementing = true;
protected $fillable = [
'username', 'email', 'password', 'name', 'remember_token',
];
protected $hidden = ['password', 'remember_token'];
public function teacher()
{
return $this->hasOne(Teacher::class, 'userid','id');
}
}
Teacher
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Teacher extends Model
{
//configurações a serem observadas
protected $primaryKey = "userid";
protected $table = "teachers";
public $incrementing = false;
protected $fillable = ['userid', 'birth', 'about'];
public function user()
{
return $this->belongsTo(User::class, 'userid', 'id');
}
}
As already said the change is also in the model Teacher
, where it is to be indicated:
- Primary key
- Disable auto-incrementing of this field which by default is true;
and is on the model in that part:
//configurações a serem observadas
protected $primaryKey = "userid"; //setando a chave primária
protected $table = "teachers"; //nome da tabela na base de dados
public $incrementing = false; //desabilitando auto-incremento
that is, who generates the identification of the relationship of the tables is the model User
and who gets this key is the model Teacher
. User
has a hasOne
with Teacher
, while Teacher
has a belongsTo
with User
.
Create a record:
//primeiro cria user
$data0['name'] = 'Usuario 1';
$data0['username'] = 'usuario1';
$data0['email'] = '[email protected]';
$data0['password'] = bcrypt('usuario1');
$user = new App\Models\User($data0);
$user->save(); // salva
//depois cria teacher para esse user.
$data1['birth'] = date('Y-m-d');
$data1['about'] = 'Sobre usuario1';
$user->teacher()->create($data1);
//exibindo informações.
var_dump($user->with('teacher')->where('id', $user->id)->first());
Seeking registration:
>>> $c->with('teacher')->find(6);
=> App\Models\User {#731
id: 6,
name: "Usuario 1",
username: "usuario1",
email: "[email protected]",
created_at: "2017-01-07 12:23:39",
updated_at: "2017-01-07 12:23:39",
teacher: App\Models\Teacher {#738
userid: 6,
birth: "2017-01-07",
about: "Sobre usuario1",
created_at: "2017-01-07 12:23:39",
updated_at: "2017-01-07 12:23:39",
},
}
>>>
Deleting this record and relation:
>>> $d = $c->find(6); //busca
=> App\Models\User {#711
id: 6,
name: "Usuario 1",
username: "usuario1",
email: "[email protected]",
created_at: "2017-01-07 12:23:39",
updated_at: "2017-01-07 12:23:39",
}
>>> $d->teacher()->delete(); //excluindo teacher
=> 1
>>> $d->delete(); //excluindo user
=> true
>>>
References:
That code of
insert
is that right? There are two commas then creating a space where the user. I have seen other examples where the answers ask you to pay attention to the dates. You have a model that creates timestamps, but the database does not have the appropriate field for the dates.– Not The Real Hemingway
@Nottherealhemingway already checked the
timestamps
, this is precisely the problem, which I quoted in the last paragraph of the question, in fact the tableusers
nor has the columnuser
, this column belongs to tableteachers
, but Laravel is reversing the relationship I created. I created something similar to:Teacher hasOne User
but he’s interpreting it asUser hasOne User
– Leonardo
Ah, damn it, I’m sorry! I should have read it carefully. Back to the lab
– Not The Real Hemingway
1 user can be a teacher is that it? If it is different the Migration and the models to work.
– novic
@Virgilionovic basically yes, because I’m going to have two types of users, corporations and teachers, so I unified the access table, with the attributes that they both have in common. So in my view, a teacher has a user, just as a corporation will have a user.
– Leonardo
A user can be both teacher and corporation?
– novic
@Virgilionovic, no, will always be one for one, user would only function as a extends for teacher and corporation, only to reuse fields that the two have in common, not to have to have the attributes email, password.
– Leonardo
@Ivcs I made a catch I changed some points of Teacher (both Migration and model) and created a record for you to understand.
– novic