How to create a relationship in laravel - php

Am new to laravel, I have issues trying to connect this tables: plans,users and loans even after reading the docs,
I have a plans tables that have all my plans, then I have a users table and loans table, my loans table has a user_id and a plan_id, all I want is to pull the records for plans and the users in the loan model.
Loanplan.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loanplan extends Model
{
//
protected $fillable = [
'title',
'amount',
'interest',
'repayment_month',
'status',
];
public function loan()
{
return $this->belongsTo('App\loan');
}
}
my loan model:
Loan.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $table = 'loans';
//
protected $fillable = [
'id',
'user_id',
'loanplan_id',
'payment_made',
'status',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function loanplan()
{
return $this->belongsTo('App\Loanplan');
}
}
I want get all the loan plans and users table records with plan_id and user_id as foreign respectively respectively in my LoanController.

I think the problem is with the customization of the loans table name in the Loanplan model.
According with your descriptions you need the followings setup:
A User can access to one or many Loans
users 1---m plans
A Loan belongs to a Loanplan // here I'm using Loanplan because that is your model name.
loans 1---m plans
So, this means:
User.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'users';
//
protected $fillable = [
'id',
//
];
public function loans()
{
return $this->hasMany(Loan::class);
}
//
}
Loan.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $table = 'loans';
//
protected $fillable = [
'id',
'user_id',
'loanplan_id',
//
];
public function user()
{
return $this->belongsTo(User::class);
}
public function plan()
{
// Notice that here I'm specifying the foreign key:
return $this->belongsTo(Loanplan::class);
}
//
}
Loanplan.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loanplan extends Model
{
protected $table = 'plans';
//
protected $fillable = [
'id',
//
];
public function loans()
{
return $this->hasMany(Loan::class);
}
//
}
So with this, you can access the information in your LoanController.php:
LoanController.php
public function myCoolMethod()
{
// get a user
$user = User::first();
// access his/her loans
$loans = user->loans;
//
// get a loan plan
$plan = Loanplan::first();
// access its loans
$loans = plan->loans;
//
}
I strongly suggest you to read the Laravel Documentation regarding relationships and also a course for database design. Have a good day mate.

Loanplan.php is missing the protected $table = "plans" variable
Same file,
public function loan()
{
return $this->belongsTo('App\loan');
}
the relationship should be hasOne or hasMany, not belongsTo.
Moreover, the name of the class should have Loan with capital L.
public function loan()
{
return $this->...('App\Loan');
}

First of all add protected $table = 'plans'; to your Loanplan model since the table name is 'plans'
Loanplan Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loanplan extends Model
{
protected $table = 'plans';
protected $fillable = [
'title',
'amount',
'interest',
'repayment_month',
'status',
];
public function loan()
{
return $this->hasOne('App\loan'); // or hasMany
}
}
?>
Loan Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $table = 'loans';
//
protected $fillable = [
'id',
'user_id',
'loanplan_id',
'payment_made',
'status',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function loanplan()
{
return $this->belongsTo('App\Loanplan');
}
}
?>
add this to the User Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function Loan()
{
return $this->hasOne('App\Loan'); // or hasMany
}
}
?>

First, you have to check if the model already querying from table that you created before. Laravel will automatically access table base on your class name.
Note that we did not tell Eloquent which table to use for our Flight model. By convention, the "snake case", plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the Flight model stores records in the flights table.
You can read it from this documentation
Second, make sure you call the right class. From Loanplan.php in the loan() method it's not using uppercase for the first letter.
Third, try to state the foreign key and primary key. You can also check how to do it in the documentation.

Related

Laravel hasOne() Function Using $this when not in object context

I have 2 models named AdminContent, AdminCategory. I have content_category_id in my admin_contents table. I have category_id and category_name in my admin_categories table. I linked category_id with content_category_id foreign.
I am using the hasOne() function in my Admin Content model. But I get the error Using $this when not in object context!
My main goal is to get content_category_id value from admin_categories table name column
Migrations
// Admin Categories Migration
Schema::create( 'admin_categories', function(Blueprint $table) {
$table->bigIncrements('ctgry_id')->unique();
$table->string('category_name', 50)->unique();
$table->timestamps();
});
// Admin Contents Migration
Schema::create('admin_contents', function (Blueprint $table) {
$table->bigIncrements('cntnt_id')->unique();
$table->string('content_title');
$table->text('content_content');
$table->string('content_slug');
$table->bigInteger('content_category_id');
$table->foreign('content_category_id')->references('ctgry_id')->on('admin_categories');
$table->string('content_status');
$table->string('create_user');
$table->string('content_tags');
$table->string('content_excerpt');
$table->dateTime('posted_at');
$table->timestamps();
});
Models
// AdminContent Model
protected $table = "admin_contents";
protected $fillable = [
'content_title', 'content_content',
'content_category_id', 'content_status', 'create_user','content_tags',
'content_excerpt',
'created_at', 'updated_at'
];
protected $guards = [
'cntnt_id',
];
public function setCategoryName()
{
return $this->hasOne(AdminCategory::class);
}
When I want to access with $this->hasOne(AdminCategory::class) I get this error!
First: relationships in Laravel are based in standardize models, using 'id' as column name for ids. If you are using another name for firstKey, you should add it to relationship definition, as stated in documentation. I mean, your relationship should not work because Eloquent doesn't know which are your tables first keys.
Second: when you define a relationship you should call id from your model. So how are you accessing to $this->hasOne(AdminCategory::class)?
It should be something like AdminContent::with('setCategoryName')
Maybe showing some code from your controller we can give you a more accurate reply.
What I want is this,
I get the blog content with query and print it. But I am printing the content_category_id value as the id value in category table. What I need to do is get the content_category_id and the id value in the category table, the category name linked to that id. Thanks in advance for your help.
Admin Content Model
namespace App\Models\Admin;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class AdminContent extends Model
{
use HasFactory;
protected $table = "admin_contents";
protected $primaryKey = 'cntnt_id';
protected $fillable = [
'content_title', 'content_content',
'content_category_id', 'content_status', 'create_user','content_tags',
'content_excerpt',
'created_at', 'updated_at'
];
protected $guards = [
'cntnt_id',
];
public function _all()
{
return self::all();
}
public static function setCategoryName()
{
return $this->hasOne(AdminCategory::class, 'content_category_id', 'ctgry_id');
}
}
Admin Category Model
namespace App\Models\Admin;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AdminCategory extends Model
{
use HasFactory;
protected $table = 'admin_categories';
protected $primaryKey = 'ctgry_id';
protected $fillable = [
'category_name', 'updated_at'
];
protected $quards = [
'ctgry_id', 'created_at'
];
}
Post Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Admin\AdminContent;
class PostController extends Controller
{
public function index()
{
return view('frontend.blog');
}
public function getCategoryName()
{
return AdminContent::find(1)->setCategoryName;
}
}
MySQL Tables
https://www.hizliresim.com/2z0337a

How to obtain three level model data laravel

Updated
User model
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens, HasRoles;
const MALE = 'male';
const FEMALE = 'female';
protected $guard_name = 'sanctum';
public function educationalBackgrounds()
{
return $this->hasMany("App\Models\Users\EducationalBackground", "user_id");
}
public function seminars()
{
return $this->hasMany("App\Models\Users\Seminar", "user_id");
}
}
I have child table EducationalBackground which is related to User table
class EducationalBackground extends Model
{
use HasFactory;
protected $table = 'users.educational_backgrounds';
protected $fillable = [
'user_id',
'studies_type',
'year',
'course',
];
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
public function educationalAwards()
{
return $this->hasMany("App\Models\Users\EducationalAward", "educational_background_id");
}
}
And a third table that i want to access the award field
class EducationalAward extends Model
{
use HasFactory;
protected $table = 'users.educational_awards';
protected $fillable = [
'educational_background_id',
'award',
'photo',
];
public function educationalBackground()
{
return $this->belongsTo('App\Models\Users\EducationalBackground', 'educational_background_id');
}
}
I have api get route here
Route::get('/educational-background/{id}', [UserProfileController::class, 'getEducationalBackground']);
Here is my api method it works fine. But i want to go deeper and access the data of third table.
public function getEducationalBackground($id)
{
$educationalBackground = EducationalBackground::with('user')->where('user_id', $id)->get();
return response()->json($educationalBackground, 200);
}
It looks like you're not really grasping the concept of relations yet. Also, I'd advise you to look into route model binding :) What you basically want to be doing is:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds()->with('educationalAwards')->get();
}
Also, when you're pretty sure that whenever you want to use backgrounds, you also want to use the awards, you can add the with(...) to the model definition like so:
class EducationalBackground extends Model
{
...
protected $with = ['educationalAwards'];
}
That way, you can simplify your controller method to:
public function getEducationalBackground($id)
{
$user = User::find($id);
return $user->educationalBackgrounds;
}

Problem with Laravel Eloquent - relation not working

I'am beginner in Laravel. I have project in Laravel 5.8.
I have User model:
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable;
use psCMS\Presenters\UserPresenter;
use scopeActiveTrait;
public static $roles = [];
public $dates = ['last_activity'];
// ...
public function scopeHistory()
{
return $this->hasMany('App\UserLoginHistory');
}
// ...
}
and UserLoginHistory:
class UserLoginHistory extends Model
{
protected $quarded = ['id'];
public $timestamps = false;
protected $fillable = ['user_id', 'date_time', 'ip'];
public function user()
{
return $this->belongsTo('App\User');
}
}
I want show user login history by this code:
User::history()->where('id', $idAdmin)->orderBy('id', 'desc')->paginate(25);
but it's not working.
This function not working - I haven't got results.
How can I fixed it?
First of all, you are defining your relationship as a scope (prefixing the relationship with the scope keyword). Try updating your model relationship to this:
public function history()
{
return $this->hasMany('App\UserLoginHistory');
}
Then, given your query, it seems that you want to get all the UserLoginHistory
records for a given User. You could accomplish this in two ways (at least).
From the UserLoginHistory model itself, constraining the query by the foreign key value:
$userId = auth()->id(); // get the user ID here.
$results = UserLoginHistory::where('user_id', $userId)->paginate(15);
// ^^^^^^^ your FK column name
From the User model using your defined relationship:
$userId = auth()->id(); // get the user ID here.
$results = User::find($userId)->history;
The downside of the second approach is that you'll need to paginate the results manually.
in your User model you should define your relation by this way :
public function history()
{
return $this->hasMany('App\UserLoginHistory');
}
then if you would like to select with history model you can do that with WhereHas() method :
User::whereHas(['history'=>function($q) use ($idAdmin) {
$q->where('id',$idAdmin)
}])->orderBy('id', 'desc')->paginate(25);
You must be do this changes
public function history()
{
return $this->hasMany('App\UserLoginHistory');
}
usage
$user = User::find($idAdmin);
$userHistories = $user->history()->latest()->paginate(25);
or get user with all history
User::with('history')->find($idAdmin);
// Post model
namespace App;
use App\User;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function categories()
{
return $this->belongsToMany('App\Category')->withTimestamps();
}
}
// Category model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
public function posts()
{
return $this->belongsToMany('App\Post')->withTimestamps();
}
}

Laravel Eloquent: 3 table relationship

I'm new to Laravel-eloquent, I would like to translate this SQL to Eloquent mode:
select
fl.id, fut.id, fut.firebase_topic_id, ft.id, fl.created_at
from
firebase_logs fl,
firebase_user_topics fut,
firebase_topics ft
where
fl.id = fut.firebase_log_id
and
fut.firebase_topic_id = ft.id
and
fl.created_at between '2019-01-09 16:33:39' and '2019-01-09 16:33:41'
and
ft.id = 1
order by fl.created_at asc
Where:
Firebase_logs.id (1) -> Firebase_user_topics.firebase_log_id (N)
and
Firenase_user_topics.firebase_topic_id (N) -> Firebase_topics.id (1)
FirebaseLog.php:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class FirebaseLog extends Model
{
public $incrementing = false;
protected $primaryKey = 'id';
public function user_topics() {
//return $this->hasManyThrough(FirebaseTopics::class, FirebaseUserTopics::class);
return $this->hasMany(FirebaseUserTopics::class);
}
}
FirebaseUserTopics.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class FirebaseUserTopics extends Model
{
protected $table = 'firebase_user_topics';
public function log()
{
return $this->belongsTo(FirebaseLog::class);
}
public function topic()
{
return $this->belongsTo(FirebaseTopics::class);
}
}
FirebaseTopics.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class FirebaseTopics extends Model
{
protected $table = 'firebase_topics';
public function user_topics()
{
return $this->hasMany(FirebaseUserTopics, 'firebase_user_topics');
}
}
My Controller, works fine with this:
$a = FirebaseLog::with('user_topics')->whereBetween('created_at', array('2019-01-09 16:33:39', '2019-01-09 16:33:41'))->get();
return $a;
But I don't know how to connect to FirebaseTopics to continue building the code, some help will be appreciated.
EDITED ANSWER!
The solution of your problem is use the hasOne relation instead of belongsTo in your FirebaseUserTopics model. It must be following;
public function topic()
{
return $this->hasOne(FirebaseTopics::class, 'id', 'firebase_topic_id');
}
Because your FirebaseTopics model has not a relation with FirebaseUserTopics model. The "belongsTo" (that uses to make reverse a relation) search firebase_topic_id field in the firebase_topics table but this field has no in the firebase_topics table. That's why, you must be make to relation directly, not reverse.

Accessing Pivot table "3rd Model relationship" in Laravel Eloquent

I have this Many-to-Many relation Laravel Eloquent relationship
The Models are:
class Email extends Model //actually represent the email account
{
protected $table = 'emails';
protected $fillable = [
'user_id',
'name',
];
public function messages() {
return $this->belongsToMany(Message::class)->withPivot('email_subtype_id');
}
}
class Message extends Model //actually represent the email message
{
protected $table = 'messages';
protected $fillable = [
'subject',
'body ',
];
public function emails() {
return $this->belongsToMany(Email::class)->withPivot('email_subtype_id');
}
}
class EmailMessage extends Pivot //actually represent the pivot table
{
protected $table = 'email_message';
protected $fillable = [
'email_id',
'message_id',
'email_subtype_id',
];
public function email() {
return $this->belongsTo(Email::class);
}
public function message() {
return $this->belongsTo(Message::class);
}
//this is the relation to a third model called EmailSubtype
//I want to include this relation to the Pivot when using it
public function subtype() {
return $this->belongsTo(EmailSubtype::class, 'email_subtype_id');
}
}
class EmailSubtype extends Model //3rd Model need to be included with Pivot
{
protected $table = 'email_subtypes';
protected $fillable = [
'name'
];
public function pivotEmailSubtype(){
return $this->hasMany(Pivot::class, 'email_subtype_id');
}
}
I am able to do this in the Controller:
$email = Email::find(1);
foreach($email->messages as $message) {
$subtype_id = $message->pivot->email_subtype_id;
dd($subtype_id); //1 that relates to subtype: CC Email Account
//also I can get the name indirectly away from the relation as follows:
$subtypeName = EmailSubtype::find($subtype_id)->first()->name;
dd($subtypeName);
}
Here I am getting the email_subtype_id only by direct pivot relation but have to do extra work to get the related email sub-type name.
I need to get the email sub-type name [Directly] from the 3rd Model EmailSubtype relationship oneToMany [hasMany and belongsTo] that relates to Pivot model with EmailSubtype model using something like:
$message->pivot->subtypeName;
Any help please!
Use this:
public function messages() {
return $this->belongsToMany(Message::class)->withPivot('email_subtype_id')
->using(EmailMessage::class);
}
$message->pivot->subtype->name

Categories