Laravel belongsTo relationship not working - php

I have three models that I have created Post and Comment and User. I am trying to create a relationship in between. Comment and Post they both have a field "user_id" that matches the id on the User table. Below are the relationships that I am trying to set:
Comment.php:
<?php
namespace App;
class Comment extends Model
{
//
public function post(){
return $this->belongsTo(Post::class);
}
public function user(){
return $this->belongsTo(User::class);
}
}
Post.php:
<?php
namespace App;
class Post extends Model
{
public function comments(){
return $this->hasMany(Comment::class);
}
public function addComment($body, $name, $email){
$this->comments()->create(compact('body','name','email'));
}
public function user(){ // $comment->user->name
return $this->belongsTo(User::class);
}
}
User.php
<?php
namespace App;
use App\Post;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function post(){
return $this->hasMany(Post::class);
}
}
Now as you can see a Comment belongsTo a user and a post belongsTo a user.
However when I try to create a new post via tinker (with no user created on database or logged in user) I can create a post with no problem;
That tells me that the relationship that a post must have a user and a comment must have a user as well its not working! Any idea how to fix this ?
Migrations:
create_posts_migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePostsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->string('title');
$table->text('body');
$table->string('image');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
}
create_comment_migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCommentsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->integer('post_id');
$table->integer('user_id');
$table->string('email');
$table->string('name');
$table->string('body');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('comments');
}
}

Add the foreign key constraints in your migration to check for valid user when creating a post and to check for valid user and post when creating comments. This should solve your issue.
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('title');
$table->text('body');
$table->string('image');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('post_id');
$table->unsignedInteger('user_id');
$table->string('email');
$table->string('name');
$table->string('body');
$table->timestamps();
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Change the onDelete option based on your needs. The cascade will delete the child relationships when a parent is deleted.

Related

Why am i getting this error when i try to add foreign keys on Invoice table?

I have two tables users and invoices. This is the up function for the users migration:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('email')->unique();
$table->string('phone')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('comentarii');
$table->rememberToken();
$table->timestamps();
});
}
This is the up function for the invoices migration:
public function up()
{
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->unsignedInteger('user_id');
$table->foreign('user_id')->refferences('id')->on('users');
$table->integer('InvoiceNumber');
$table->dateTime('date');
$table->string('serviceInvoiced');
$table->timestamps();
});
}
All I am trying to do is to make a one to many relationship as in a user can have multiple invoices.
Here is the User model:
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $guarded = [];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function getInvoices()
{
return $this->hasMany(Invoice::class);
}
}
Here is the Invoice model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
use HasFactory;
protected $guarded=[];
public function getUsers()
{
return $this->belongsTo(User::class);
}
}
What am I doing wrong? I watched multiple tutorials already. Here are the errors that im getting:
The columns need to be of the same type. id() is an alias of bigIncrements(), so
$table->unsignedInteger('user_id');
should be
$table->unsignedBigInteger('user_id');
Also note: it's ->references('id'), not ->refferences('id')
More on Available Column Types
You have two issues:
You have a typo in your migration statement
$this->id() make unsignedBigInteger so user_id should be unsignedBigInteger
Alter you migration lines to this:
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users'); //references not refferences

Property [firstName] does not exist on this collection instance

My User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'firstName', 'secondName', 'email', 'city', 'phoneNumber', 'password', 'profilePicture'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function ratings()
{
return $this->belongsToMany(Ratings::class, 'ratings_has_users', 'users_id', 'ratings_id')->withTimestamps();
}
}
My Ratings Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Ratings extends Model
{
public function user(){
return $this->belongsToMany(User::class, 'ratings_has_users', 'users_id', 'ratings_id')->withTimestamps();
}
}
MIgration to create table 'ratings_has_users'
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRatingsHasUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('ratings_has_users', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('users_id');
$table->unsignedBigInteger('ratings_id');
$table->timestamps();
});
Schema::table('ratings_has_users', function (Blueprint $table) {
$table->foreign('users_id')
->references('id')
->on('users');
});
Schema::table('ratings_has_users', function (Blueprint $table) {
$table->foreign('ratings_id')
->references('id')
->on('ratings');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('ratings_has_users');
}
}
Migration to create 'users' table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('firstName',55);
$table->string('secondName',55);
$table->string('email',55)->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('city',55);
$table->text('description')->nullable();
$table->string('phoneNumber',11);
$table->string('profilePicture',255)->default('profile.jpg');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Migration to create 'ratings' table:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRatingsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('ratings', function (Blueprint $table) {
$table->id();
$table->integer('stars');
$table->mediumText('note');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('ratings');
}
}
And code in my blade:
#foreach($ratings as $rating)
{{ dd($rating->user->firstName) }}
#endforeach
I don't know why I see this error message: Property [firstName] does not exist on this collection instance. (View: /data/www/twoj-trener/resources/views/trainer_page/reviews.blade.php)
When I change code on this:
#foreach($ratings as $rating)
{{ dd($rating->user) }}
#endforeach
I got this:
Illuminate\Database\Eloquent\Collection {#1291 ▼
#items: []
}
The relation between rating and user should be users() (with an S for plural) since it's a belongToMany one with a pivot table.
If you want ratings to be unique per user, consider changing your migration of ratings table
public function up()
{
Schema::create('ratings', function (Blueprint $table) {
$table->id();
$table->integer('stars');
$table->mediumText('note');
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
and change the relation to belongsTo
if your structure is correct as it is, you will need to get the user before accessing its attribute
#foreach($ratings as $rating)
{{ dd($rating->users->first() ?? $rating->users->first()->firstName) }}
#endforeach
Ratings has user(better name users, because belongsToMany) relation method. If belongsToMany relation that relation method(in this case user) will give the Collection (list related records).
You can do something like below
$rating->user->first()->firstName

Trying to get property 'id' of non-object Laravel 7.X

Now I have two Models: user.php and Trx.php. I have created a one to many relationships as below:
User Model:
public function transactions()
{
return $this->hasMany('App\Trx');
}
Trx Model:
public function user()
{
return $this->belongsTo('App\User');
}
And this is the controller method for process data from Trx.php model and sending data to the views:
public function purchasedPlan()
{
$page_title = 'Purchased Plan';
$transactions = Trx::where('type', 7)->orderBy('id', 'DESC')->paginate(config('constants.table.default'));
$empty_message = 'No data found.';
// dd($transactions);
return view('admin.reports.transactions', compact('page_title', 'transactions', 'empty_message'));
}
Now the problem is that when I try accessing the data from the model, that's the $transactions, everything is working well except when I try getting the user in the relationship established like this in the blade template:
transactions.blade.php
<td> {{ $trx->user->username }}</td>
With that, I get this error:
Error:
[2020-05-24 05:35:40] production.ERROR: Trying to get property 'id' of non-object (View: /home/icashers/public_html/acc/core/resources/views/admin/reports/transactions.blade.php) {"exception":"[object] (ErrorException(code: 0): Trying to get property 'id' of non-object (View: /home/icashers/public_html/acc/core/resources/views/admin/reports/transactions.blade.php)
What am I doing wrong please? Anyone who's seeing what I am not please help. Thank you in advance😂
Trx.php Migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTrxesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('trxes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id')->nullable();
$table->string('amount',50)->nullable();
$table->string('main_amo',50)->nullable();
$table->string('charge',50)->nullable();
$table->string('type',50)->nullable();
$table->string('title')->nullable();
$table->string('trx')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('trxes');
}
}
User.php Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('firstname');
$table->string('lastname');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('mobile')->unique();
$table->decimal('balance', 11, 2)->default(0);
$table->string('password');
$table->string('image')->nullable();
$table->text('address')->nullable()->comment('contains full address');
$table->tinyInteger('status')->default(1)->comment('0: banned, 1: active');
$table->tinyInteger('ev')->default(0)->comment('0: email unverified, 1: email verified');
$table->tinyInteger('sv')->default(0)->comment('0: sms unverified, 1: sms verified');
$table->string('ver_code')->nullable()->comment('stores verification code');
$table->dateTime('ver_code_send_at')->nullable()->comment('verification send time');
$table->tinyInteger('ts')->default(0)->comment('0: 2fa off, 1: 2fa on');
$table->tinyInteger('tv')->default(1)->comment('0: 2fa unverified, 1: 2fa verified');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
Your migration has an error.... no foreign key defined>
public function up()
{
Schema::create('trxes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->string('amount',50)->nullable();
$table->string('main_amo',50)->nullable();
$table->string('charge',50)->nullable();
$table->string('type',50)->nullable();
$table->string('title')->nullable();
$table->string('trx')->nullable();
$table->timestamps();
});
}

Inner Join-Laravel

I have three tables in my database. User, Employer and Jobs.
Some Users are Employers who have posted some jobs.
I am trying to display jobs by users.
My code:
User Model
public function jobs(){
return $this->hasManyThrough('App\Employer','App\Job');
}
Routes:
Route::get('/find_user_jobs',function(){
$user=User::find(1);
foreach($user->jobs as $job){
echo $job->created_at."<br>";
}
});
But I get this error
Column not found: 1054 Unknown column 'jobs.user_id' in 'field list' (SQL: select `employers`.*, `jobs`.`user_id` from `employers` inner join `jobs` on `jobs`.`id` = `employers`.`job_id` where `jobs`.`user_id` = 1)
I get that its trying to find user_id in jobs but here is what I want it to do
My desire for the program
When I give the user id, go to employers table search for user_id, if it exists ,go to jobs table and search for the employers_id and return all the jobs with the employer_id.
User Migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->integer('employer_id');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
Job migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateJobsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->increments('id');
$table->integer('employer_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('jobs');
}
}
Employer Migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateEmployersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('employers', function (Blueprint $table) {
$table->increments('id');
$table->string('company_name');
$table->integer('user_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('employers');
}
}
The relationship arguments are in the wrong order:
public function jobs(){
return $this->hasManyThrough('App\Job', 'App\Employer');
}
Because Employee are User who have Jobs you can create a model App\Employee which extends the App\User Model
class Job {
public function employee()
{
return $this->belongsTo(App\Employee::class,'user_id');
}
}
and Create an Employee class like this
Here in the Employee Model I set the $table property to users, when we make some query that query will have the target table set to users instead of the employees table which would be the default behavior of Eloquent.
class Employee extends User
{
protected $table = "users";
public function jobs()
{
return $this->hasMany(Job::class, 'user_id');
}
}
You can use directly the Employee Model and get jobs
And here are the corresponding migration
the create_user_table
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->string('company_name')->nullable();
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
}
The create_job_table
class CreateJobsTable extends Migration
{
public function up()
{
Schema::create('jobs', function (Blueprint $table) {
$table->increments('id');
$table->integer("user_id")->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
public function down()
{
Schema::drop('jobs');
}
}

Laravel converting DB query to eloquent

I'm new to laravel and have been pondering with this issue for a short while now. The main reason that I'd like to use eloquent is so that the datetime stamps work as the DB method ignores the created_at and updated_at fields. I am trying to reproduce the following query to eloquent:
$user_results = DB::table('users')->
leftJoin('roles', 'users.role_id','=', 'roles.id')->
get();
I have the following database setup
user migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('role_id')->unsigned()->index();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
roles migration
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRolesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('rolename');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('roles');
}
}
and the user model contains
public function role() {
return $this->belongsTo('App\Role');
}
Any help would be much appreciated.
thanks.
Simply you can replace DB::table('users') with App\User
App\User::leftJoin('roles', 'users.role_id','=', 'roles.id')->get();

Categories