Eloquent hasOne relationship return null - laravel

I have 2 models Admin and Subscription
Model Admin.php
public function subscription() {
return $this->hasOne('App\Subscription','admin_id','id');
}
Model Subscription.php
public function payer() {
return $this->belongsTo('App\Admin','admin_id','id');
}
When i try to get payer of the subscription it returns null.
I am getting a payer like this.
In Controller.php
$subscriptions=Subscription::all();
foreach ($subscriptions as $subscription) {
dd($subscription->payer);
}
Please give me a solution. I tried and change everything it's still not working.
This is my migrations
Subscription Table
id int(10) unsigned Auto Increment
subscription_type varchar(191) NULL
expiry_date timestamp NULL
status varchar(191) [required]
admin_id varchar(191)
created_at timestamp NULL
updated_at timestamp NULL
Admin Table
id int(10) unsigned Auto Increment
name varchar(191)
email varchar(191)
password varchar(191)
remember_token varchar(100) NULL
created_at timestamp NULL
updated_at timestamp NULL

Im not sure since you haven't showed your migration files but I think you might be setting the relation wrongly, you are specifying the same foreign. Also if primary key is named 'id' you don't need to specify it. So maybe this works out:
Model Admin
public function subscription()
{
// asumes foreign key is called admin_id
return $this->hasOne('App\Subscription');
}
Model Subscription
public function payer()
{
// asumes foreign key is called subscription_id
return $this->belongsTo('App\Admin');
}
Update, if you have your tables named as you are suggesting you won't need to specify any key because you are following laravel default naming conventions.

Laravel pitches a fit if you don't use a number as an id. You have to tell it if you use a string.
protected $keyType = 'string';

the method name you write for hasOne must have more than 3 chars.

Related

Laravel Polymorphic Relationship - Many to Many issue

Have students, that can have documents.
Documents can either be 'just documents' that belong to students (normal one to many relationship)
However, Students can also have 'passports' and 'visas' (amongst others). Each passport and visa can have a document too. A single document can belong to many things (eg, one document can be associated with a passport and a visa). For the purpose of this troubleshooting, lets keep it simple and between Student / Passport (I've also left out other class stuff like fillable just to keep this brief).
Student Model:
class Student extends Model
{
public function documents() {
return $this->hasMany('App\StudentDocument');
}
public function visas() {
return $this->hasMany('App\StudentVisa');
}
public function passports() {
return $this->hasMany('App\StudentPassport');
}
}
Student Passport Class
class StudentPassport extends Model
{
public function student_documents()
{
return $this->morphToMany(StudentDocument::class, 'student_documentable');
}
}
Student Passport Store:
public function store(StudentPassportRequest $request, $student_id)
{
$student = Student::findOrFail($student_id);
$passport = $student->passports()->create($request->all());
if ($request->file('student_document_file')->isValid()) {
$uploaded_file = $request->file('student_document_file');
$filename = time().'-'.$uploaded_file->getClientOriginalName();
Storage::disk('local')->putFileAs(
'student_document_files/'. \Auth::user()->userable_id .'/'. $student_id .'/',
$uploaded_file,
$filename
);
$student_document = new StudentDocument;
$student_document->filename = $filename;
$student_document->student_document_type_id = StudentDocumentType::where('student_document_type','Passport')->first()->id;
$student_document->original_filename = $uploaded_file->getClientOriginalName();
$student_document->mime = $uploaded_file->getMimeType();
$student_document->student_id=$student_id;
$passport->student_documents()->save($student_document);
}
return redirect('/baadmin/students/'. $student_id .'#kt_tabs-passports')->with('flash_message', ['success','Created Successfully','Student Passport "'. $request->input('passport_number') .'" created successfully!']);
}
Error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'student_documentables' doesn't exist
INSERT INTO `student_documentables` (
`student_document_id`,
`student_documentable_id`,
`student_documentable_type`
)
VALUES
(5, 503, App \ StudentPassport)
I took the example as found in the Laravel Documentation here and just renamed 'tag' to student_documents' essentially. The student_documentable table doesnt exist of course, as it should be plugging it into the student_documents table.
Schema:
CREATE TABLE `student_documents` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`student_id` bigint(20) unsigned NOT NULL,
`student_document_type_id` bigint(20) unsigned NOT NULL,
`filename` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`mime` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`original_filename` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
`primary_date` datetime NOT NULL DEFAULT current_timestamp(),
`secondary_date` datetime DEFAULT NULL,
`student_documentable_id` bigint(20) DEFAULT NULL,
`student_documentable_type` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `student_id_index` (`student_id`),
KEY `student_document_type_id_index` (`student_document_type_id`),
KEY `student_documentable_id_index` (`student_documentable_id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
What am I doing wrong or is Laravel just not understanding 'student_documents'?
I can of course change the Student Passport Class to not plug into 'student_documentable' and use 'student_document' then it would try put in the data to the correct table, but I dont know if this is right since all documentation refers to adding an 'able' at the end...
You should first create a pivot table for that MorphMany relation,
Schema::create('student_documentables', function (Blueprint $table)
{
// optional depends if you want an id or not
$table->id();
// here singular is used, to generate student_documentable_type and student_documentable_id fields
$table->morphs('student_documentable');
// the foreign key to student_document
$table->unsignedInteger('student_document_id');
$table->foreign('student_document_id')->on('student_documents')->references('id')->onUpdate('cascade')->onDelete('cascade');
});
In your StudentDocument :
// we define a relation to retrieve all documentables like passport that are linked to that document
public function student_documentables()
{
return $this->morphTo('student_documentables');
}
In your StudentPassport :
// we define a relation to retrieve all documents linked to that passport
public function student_documents()
{
return $this->morphMany(StudentDocument::class, 'student_documentables');
}

Laravel paginate with only first result

i'm kinda new to Laravel so I hope the question is clear enough.
I have a table with Users and another table with Tasks.
In my User model I have the following :
public function tasks() {
return $this->hasMany('App\User' , 'id');
}
I can do the following to retrieve a single user from the DB
$users = \App\User::find(1)->tasks()->paginate();
but i get
{"current_page":1,"data":[{"id":1,"name":"Ed","email":"mail#weqweqeq.com","email_verified_at":null,"created_at":null,"updated_at":null,"tasks":[{"id":1,"name":"Ed","email":"mail#weqweqeq.com","email_verified_at":null,"created_at":null,"updated_at":null}]},{"id":2,"name":"Alyse","email":"mail#rxygewe.com","email_verified_at":null,"created_at":null,"updated_at":null,"tasks":[]}],"first_page_url":"http:\/\/127.0.0.1:8000?page=1","from":1,"last_page":1,"last_page_url":"http:\/\/127.0.0.1:8000?page=1","next_page_url":null,"path":"http:\/\/127.0.0.1:8000","per_page":15,"prev_page_url":null,"to":2,"total":2}
I've also tried :
$users = \App\User::with(['tasks' => function($q) {
$q->first();
}])->paginate();
but the tasks property is empty
My question is how I can get all the users but only with first task and paginate to work?
Tasks table
1 id(Primary) bigint(20) UNSIGNED No None AUTO_INCREMENT
2 created_at timestamp Yes NULL
3 updated_at timestamp Yes NULL
4 task_name varchar(255) utf8mb4_unicode_ci No None
5 user_id(Index) bigint(20) UNSIGNED No None
Your model relationship is defined incorrectly. You have associated a User with many Users.
https://laravel.com/docs/master/eloquent-relationships#one-to-many
public function tasks() {
// a User ($this) has many Tasks
return $this->hasMany('App\Task');
}
Also, be careful when using ->first() as the order is not guaranteed unless specified.
$users = \App\User::with(['tasks' => function($q) {
// get the most recently created task
$q->latest()->first();
}])->paginate();
for another example
$getData = $User::where('code_transaction',$code)->first();
$pag = $getData->paginate(10);

Laravel 5.4 Model Relationship

I have created three tables users, courses and user_courses as shown below
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`address` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`status` enum('0','1') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE TABLE `courses` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` text,
`description` text,
`price` varchar(255) DEFAULT NULL,
`schedule` varchar(255) DEFAULT NULL,
`duration` varchar(255) DEFAULT NULL,
`summary` text,
`skills` text,
`mode` enum('0','1') DEFAULT NULL COMMENT '0-Online 1 -Instructor',
`random_token` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
CREATE TABLE `user_courses` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) DEFAULT NULL,
`course_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1
Now with these tables, I want to bind relationship such as when I fetch Users I'm able to get courses for a user and when I get to courses I want users associated with the course.
Please help how I can achieve it.
I have got my answer so posting it here if it can help anyone.
The main thing here is to assign a many-to-many relationship. In my user model I have defined
public function courses()
{
return $this->belongsToMany('App\Course');
}
In course model
public function users()
{
return $this->belongsToMany('App\User');
}
Actually, it depends on how you want to use the relationship.In some parts of the code you will need $user->courses or more likely to query $course->users or both.
Now here user_course table will be assumed as a pivot table. So in model, you can write it as
public function courses()
{
return $this->belongsToMany('App\Course', 'user_courses');
}
Here you can also specify the actual names of the fields of that particular pivot table i.e user_courses table.Then, what all we have to do is just add two more parameters first is the current model field and then add the field of the model being joined like
public function courses()
{
return $this->belongsToMany('App\Course', 'user_courses','user_id', 'course_id');
}
So using the above model relationship you can easily fetch users with all the respective courses by
User::->with('courses')->get();
First Fix
First, fix the user_course table structure the users table has id as integer while it's being referenced in user_course in user_id as bigint.
Solution
The first thing to do is to create models in the application. Then create relationships within models and finally use those relationships.
Create models
By using command line
php artisan make:model Course
php artisan make:model UserCourse
You can create them manually if you like. By default, they will be created in app folder with namespace App. For example, the user model will be App/User and so on.
The user model will already exists as its shipped with laravel default installation.
Create relationships
In user model add the following function
public function courses()
{
$this->belongsToMany(Course::class, 'user_course');
}
You can leave the Course Model empty if you are not planning to make a reverese relation from course to user. The one above defines relation from user to courses
Usage
Say in a controller you can use this as
public function someFunctionInController()
{
$usersWithCourses = \App\User::with('courses')->get()->toArray();
//result of a single user record will look something like this
/**
[
'id' => 1,
'name' => 'some name'
... //other users table columns
//the courses will be an array of array content and will be automatically injected
'courses' => [[
'id' => 1 //the course id
... //course table columns,
'pivot' => [
'user_id' => 1,
'course_id' => 1
]
],[
'id' => 3 //the course id
... //course table columns,
'pivot' => [
'user_id' => 1,
'course_id' => 3
]
]]
]
**/
}

relationship one to many only working one side

i have a relationship one to many not working in one side.
My tables
`seguro_carro` (
`id_seguro` INT NOT NULL AUTO_INCREMENT,
`matricula` VARCHAR(8) NOT NULL,
`validade` DATE NOT NULL,
`preco` DECIMAL(12,3) NOT NULL,
`tipo_seguro` INT NOT NULL,
`cliente` INT NOT NULL
)
`tipo_seguro_carro` (
`id_tipo_seguro` INT NOT NULL AUTO_INCREMENT,
`descricao` VARCHAR(50) NOT NULL
)
Models:
SeguroCarro.php
public function tipoSeguro()
{
return $this->belongsTo('App\TipoSeguroCarro', 'id_tipo_seguro');
}
TipoSeguroCarro.php
public function seguros()
{
return $this->hasMany('App\SeguroCarro','tipo_seguro');
}
i can do TipoSeguroCarro::find(x)->seguros but not the other side like SeguroCarro::find(x)->tipoSeguro
and i can't understand why this is happening..
someone ?
thanks
You should pass tipo_seguro attribute instead of id_tipo_seguro, because Your foreign key is tipo_seguro in both relationships.
Some explanation due to request:
https://laravel.com/api/5.2/Illuminate/Database/Eloquent/Model.html#method_belongsTo
BelongsTo belongsTo( string $related, string $foreignKey = null, string $otherKey = null, string $relation = null)
https://laravel.com/api/5.2/Illuminate/Database/Eloquent/Model.html#method_hasMany
HasMany hasMany( string $related, string $foreignKey = null, string $localKey = null)
Both belongsTo and hasMany accepts second parameter as foreign key. So basicly, You have two fields involved - first is Your primary key (id_tipo_seguro) and second is foreign key (tipo_seguro). As mentioned before, both methods accept foreign key as second parameter.

Laravel hasOne does not trigger any sql request

I have a little issue with Laravel. I'm totally new with it, and am trying to create a multilang model for some content I have.
This is my configuration :
Database :
Table appartements :
1 id int(10)
2 address varchar(255)
3 postcode int(11)
4 city varchar(255)
5 country varchar(255)
6 created_at timestamp
7 updated_at timestamp
Table appartement_langs
1 id int(10)
2 language_id int(11)
3 appartement_id int(11)
4 title varchar(255)
5 subtitle varchar(255)
6 description text
7 created_at timestamp
8 updated_at timestamp
Table languages
1 id int(10)
2 locale varchar(255)
3 created_at timestamp
4 updated_at timestamp
So basically I have the language_id and the appartement_id.
In my Appartement model I have the following :
<?php
class Appartement extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function gallery()
{
return $this->hasMany('Gallery');
}
public function languages()
{
return $this->hasMany('AppartementLang', 'language_id');
}
public function lang()
{
return $this->hasOne('AppartementLang');
}
}
When I try to get the field $appartement->lang()->title I get nothing.
Can you give me a hint ? Because I really don't know how to handle this :).
Thanks a lot.
When you use lang() you are actually returning the query partially built (so you can add on other conditions, etc..)
If you want to retrieve the language model you only have to use lang.
So:
$appartement->lang->title
If you var_dump() the lang() you will see for yourself.
In the Laravel documentation you will see their relationship example calls:
$phone = User::find(1)->phone;

Resources