Laravel One to One Relationship get object result is null - php

Migration persons Table:
Schema::create('persons', function (Blueprint $table) {
$table->id();
$table->string("firstname");
$table->string("lastname");
$table->timestamps();
});
Migration passports Table:
Schema::create('passports', function (Blueprint $table) {
$table->id();
$table->string("identifystring")->unique();
$table->unsignedBigInteger("person_id");
$table->timestamps();
$table->foreign("person_id")->references("id")->on("persons")->onDelete("cascade");
});
Person model:
class Person extends Model
{
use HasFactory;
protected $table ="persons";
protected $fillable = [
"firstname",
"lastname"
];
public function passport() {
$this->hasOne(\App\Models\Passport::class, "passports.person_id","persons.id");
}
}
Passport Model:
class Passport extends Model
{
use HasFactory;
protected $table = "passports";
protected $fillable = [
"identifystring",
"person_id"
];
}
execute Code:
$person = \App\Models\Person::findOrFail(2);
dd($person->passport());
Result is: null

class Person extends Model
{
use HasFactory;
protected $table ="persons";
protected $fillable = [
"firstname",
"lastname"
];
public function passport() {
$this->hasOne(\App\Models\Passport::class, "person_id", "id");
}
}

You did not return the relation. just return it:
public function passport() {
return $this->hasOne(\App\Models\Passport::class, "passports.person_id","persons.id");
}

As per the migrations written. In the Person model write
public function passport() {
return $this->hasOne(\App\Models\Passport::class, "person_id","id");
}
and in the Passport model write
public function person() {
return $this->belongsTo(\App\Models\Person::class, 'id', 'person_id');
}
Execute the code
$person = \App\Models\Person::findOrFail(2)->passport;
dd($person);

Use this code.
In your Person Model
public function passport() {
return $this->hasOne(\App\Models\Passport::class);
}
In your passport model
public function person() {
return $this->belongsTo(\App\Models\Person::class, 'person_id');
}
Then try to pass the relation again by doing the same thing
$person = \App\Models\Person::findOrFail(2);
dd($person->passport());

Related

How to restrict delete / destroy method when model has association with another model / id?

I have model called GroupService and it has association with Service. I want to prevent or restrict when deleting GroupService, if GroupService has association with Service. And if GroupService has no association then users can delete it. I've been following these guides but it's not working for me :
[1] Laravel - How to prevent delete when there is dependent field
[2] https://laracasts.com/discuss/channels/laravel/how-to-prevent-the-delete-of-table-row-that-has-its-id-in-another-table
Here's my code :
Model GroupService:
class GroupService extends Model
{
use HasFactory;
protected $table = 't_grup_layanan';
protected $guarded = ['id'];
// protected $fillable = [
// 'bisnis_id',
// 'deskripsi'
// ];
protected $with = ['business'];
public function service(){
return $this->hasMany(Service::class);
}
public function business(){
return $this->belongsTo(Business::class, 'bisnis_id');
}
// protected static function boot(){
// parent::boot();
// static::deleting(function($groupservice) {
// $relationMethods = ['service'];
// foreach ($relationMethods as $relationMethod) {
// if ($groupservice->$relationMethod()->count() > 0) {
// return false;
// }
// }
// });
// }
}
Model Service:
class Service extends Model
{
use HasFactory;
protected $table = 't_layanan';
protected $guarded = ['id'];
// protected $fillable = [
// 'gruplayanan_id',
// 'nama',
// 'deskripsi'
// ];
protected $with = ['groupservice'];
public function groupservice(){
return $this->belongsTo(GroupService::class, 'gruplayanan_id');
}
}
Controller GroupService:
public function destroy(GroupService $groupservice, $id)
{
$groupService = GroupService::find(Crypt::decrypt($id));
if ($groupService->service()->exists())
{
abort('Resource cannot be deleted due to existence of related resources.');
}
$groupService->delete();
return redirect('/dashboard/gruplayanan/')->with('danger', 'Data dihapus !');
}
Migration GroupService:
public function up()
{
Schema::create('t_grup_layanan', function (Blueprint $table) {
$table->id();
$table->foreignId('bisnis_id')->nullable()->index('fk_bisnis_to_group');
$table->text('deskripsi');
$table->timestamps();
});
}
Migration Service:
public function up()
{
Schema::create('t_layanan', function (Blueprint $table) {
$table->id();
$table->foreignId('gruplayanan_id')->index('fk_grup_to_layanan');
$table->text('nama');
$table->text('deskripsi');
$table->timestamps();
});
}
public function up()
{
Schema::table('t_layanan', function (Blueprint $table) {
$table->foreign('gruplayanan_id', 'fk_grup_to_layanan')->references('id')->on('t_grup_layanan')->onUpdate('CASCADE')->onDelete('CASCADE');
});
}
I think problem is here on your relationship function:
public function service(){
return $this->hasMany(Service::class);
}
By Laravel convention, Eloquent will take the table name parent model and suffix it with _id.
So it look for t_grup_layanan_id field in the t_layanan table which currently does not exist.
So if you want to override the default convention, you have to specify it on the 2nd parameter like this.
public function service(){
return $this->hasMany(Service::class, 'gruplayanan_id');
}

Get all the genres that a movie belongs to in the Laravel REST API

Asside from the $movie data I want to also get all the genres that a movie belongs to following this path: 127.0.0.1:8000/api/movies/{id}. My foreign keys are in the separate table so how exactly I can achieve that? My migrations:
public function up()
{
Schema::create('genres', function (Blueprint $table) {
$table->id();
$table->string('name');
});
}
public function up()
{
Schema::create('movies', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('status')->nullable()->default(0);
$table->string('image_path')->default('default.png');
});
}
public function up()
{
Schema::create('genre_movie', function (Blueprint $table) {
$table->foreignId('genre_id')->constrained()->cascadeOnDelete();
$table->foreignId('movie_id')->constrained()->cascadeOnDelete();
});
}
Movie model:
class Movie extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name', 'status', 'image_path'];
public function genres()
{
return $this->belongsToMany(Genre::class, 'genre_movie');
}
}
Genre model:
class Genre extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['name'];
public function movies()
{
return $this->belongsToMany(Movie::class, 'genre_movie');
}
}
Movie Resource:
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'status' => $this->status,
'image_path' => url()->to('/images/' .$this->image_path),
];
}
Genre Resource:
public function toArray($request){
return [
'id' => $this->id,
'name' => $this->name,
];
}
Function in the controller which only returns $movie data:
public function show(Movie $movie)
{
return new MovieResource($movie);
}
I thought this would work:
public function show(Movie $movie)
{
return new MovieResource($movie->with('genres'));
}
But I receive this error: "message": "Property [id] does not exist on the Eloquent builder instance."
You can return JSON with a small change too.
public function showMovieAndGenre(Movie $movie)
{
$fullData = Movie::join('genres', 'genres.id', '=', 'movies.id')
->select([
'movies.id AS mid',
'genres.id AS gid',
'movies.name AS mname',
'genres.name AS gname',
'movies.status AS status',
'movies.image_path AS image_path'
])
->get();
return $fullData;
}
return $this->belongsToMany(Genre::class, 'genre_movie');
Consider using hasManyThrough https://laravel.com/docs/9.x/eloquent-relationships#has-many-through

laravel 9.0 Eloquent all() method doesn't return relationship

I have two tables Department and InspectionSite.
Department Migration
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->string('department_name', 100);
});
}
InspectionSite Migration:
public function up()
{
Schema::create('inspection_sites', function (Blueprint $table) {
$table->id();
$table->string('site_title');
$table->foreignIdFor(\App\Models\Department::class);
$table->timestamps();
});
}
Department Model:
class Department extends Model
{
use HasFactory;
protected $fillable = ['depatment_name'];
public function sites() {
return $this->hasMany(InspectionSite::class);
}
}
InspectionSite Model
class InspectionSite extends Model
{
use HasFactory;
protected $guarded = [];
public function department() {
return $this->belongsTo(Department::class, 'department_id');
}
}
getting data from controller
public function get() {
$selector = ['site_title AS title', 'site_type' ];
$sites = InspectionSite::all();
return response()->json($sites->department, 200);
}
when I call find() method it returns relationship data but not in all() method?
public function get() {
$departments = Department::all();
return response()->json($departments->sites, 200);
}
Error details
all() method returns Collection of models and each model should have department relation.
When you are trying to return this:
return response()->json($sites->department, 200);
You are accessing department property on Collection instance.
Instead you should call it on each model of that collection.
Here you can try solutions, depending what you want to achieve
Solution 1: (recomended)
$sites = InspectionSite::with('department')->get();
return response()->json($sites, 200);
// result
[
{
...
department: ...
}
...
]
Solution 2: (Returns only depertments, not InspectionSite properties)
$sites = InspectionSite::with('department')->get()
->map(function($s) {
return $s->department;
});
return response()->json($sites, 200);
// result
[
{
[department]
}
{
[department]
}
]

How to get data using relationship

Please I want to make link using id (Semesters)
this how is my DB :
Courses: id , title , pdf_file , extension , description , matieres_id and timetables
Matieres: id , matiere , semester_id and timetables
Semesters: id , semester, matieres_id and timetables
route/web.php
Route::get('/lms/semestre', 'HomeController#semestres');
Route::get('/lms/', 'HomeController#lms');
Route::get('/lms/matieres/{id}', 'HomeController#matieres');
Route::get('/lms/course/{id}', 'HomeController#course');
Route::get('/lms/courses', 'HomeController#courses');
Course.php (model)
class Course extends Model
{
use SoftDeletes;
protected $table = 'courses';
protected $fillable = ['id'];
public function matiere()
{
return $this->belongsTo(\App\Matiere::class);
}
}
Matiere.php (Model)
class Matiere extends Model
{
protected $table = 'matieres';
protected $fillable = ['id'];
public function semestre()
{
return $this->belongsTo(\App\Semestre::class);
}
}
Semestre.php (Model)
class Semestre extends Model
{
protected $table = 'semestres';
protected $fillable = ['id'];
public function matiere()
{
return $this->belongsTo(\App\Matiere::class);
}
}
My issue is how to make url /lms/courses/{semester_id} and display a page where is courses list using course->matiere_id->semesters.
It's very complicated for me and I don't want to create column semester_id in course table.
Try this one.
Note: Make sure CourseDB is created first before SemesterDB
database:
course_db:
Schema::create('courses', function (Blueprint $table) {
...
});
semester_db:
Schema::create('semesters', function (Blueprint $table) {
...
$table->unsignedBigInteger('course_id');
...
$table->foreign('course_id')->references('id')->on('courses')->onDelete('cascade');
})
Model:
course_model:
protected $guarded = [];
public function semester() {
return $this->hasOne(Semester::class);
}
semester_mode:
protected $guarded = [];
public function course() {
return $this->belongsTo(Course::class);
}
controller:
App\Course;
public function index() {
$courses = Course::all();
dd($courses->semester);
}

Laravel Eloquent after save id becomes 0

It's a table migrated from https://github.com/lucadegasperi/oauth2-server-laravel
In the table oauth_clients, the field data type of id is varchar(40), not int.
$name = Input::get('name');
$id = str_random(40);
$secret = str_random(40);
$client = new oauthClient;
$client->name = $name;
$client->id = $id;
$client->secret = $secret;
$client->save();
After save(); the $client->id become '0', not the string I assigned.
That makes the following relation table save fail.
$endpoint = new OauthClientEndpoint(array('redirect_uri' => Input::get('redirect_uri));
$client->OauthClientEndpoint()->save($endpoint);
I checked the $client->id: after save, it becomes 0 and I get an error including this one:
(SQL: insert into `oauth_client_endpoints` (`redirect_uri`, `client_id`, `updated_at`, `created_at`) values (http://www.xxxxx.com, 0, 2014-09-01 11:10:16, 2014-09-01 11:10:16))
I manually saved an endpoint to prevent this error for now. But how do I resolve this issue?
Here's my model:
class OauthClient extends Eloquent {
protected $table = 'oauth_clients';
public function OauthClientEndpoint(){
return $this->hasOne('OauthClientEndpoint', 'client_id', 'id');
}
}
class OauthClientEndpoint extends Eloquent {
protected $table = 'oauth_client_endpoints';
protected $fillable = array('redirect_uri');
public function OauthClient(){
return $this->belongsTo('OauthClient', 'client_id', 'id');
}
}
class CreateOauthClientsTable extends Migration {
public function up() {
Schema::create('oauth_clients', function (Blueprint $table) {
$table->string('id', 40);
$table->string('secret', 40);
$table->string('name');
$table->timestamps();
$table->unique('id');
$table->unique(array('id', 'secret'));
});
}
public function down() {
Schema::drop('oauth_clients');
}
}
class CreateOauthClientEndpointsTable extends Migration {
public function up() {
Schema::create('oauth_client_endpoints', function (Blueprint $table) {
$table->increments('id');
$table->string('client_id', 40);
$table->string('redirect_uri');
$table->timestamps();
$table->foreign('client_id')
->references('id')->on('oauth_clients')
->onDelete('cascade')
->onUpdate('cascade');
});
}
public function down() {
Schema::table('oauth_client_endpoints', function ($table) {
$table->dropForeign('oauth_client_endpoints_client_id_foreign');
});
Schema::drop('oauth_client_endpoints');
}
}
When you are setting your own ID and not using auto_increment be sure to add public $incrementing = false; to that model. In your case you want:
class OauthClient extends Eloquent {
public $incrementing = false;
protected $table = 'oauth_clients';
public function OauthClientEndpoint(){
return $this->hasOne('OauthClientEndpoint', 'client_id', 'id');
}
}
This is a tiny red block in the huge Laravel documentation:
Note: Typically, your Eloquent models will have auto-incrementing keys. However, if you wish to specify your own keys, set the incrementing property on your model to false.

Categories