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
Related
I'm newbiу in laravel 9. I just want create simple blog with the tables:users, stories,comments.I have next relationship
users->stories(One To Many, hasMany laravel) ,
stories->users(One To Many (Inverse) / Belongs To),
users->comments(One To Many, hasMany laravel) ,
comments->users(One To Many (Inverse) / Belongs To),
stories->comments(One To Many, hasMany laravel) ,
comments->stories(One To Many (Inverse) / Belongs To).
class User
<?php
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;
use App\Models\Story;
use App\Models\Comment;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function stories()
{
return $this->hasMany(Story::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class Story:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Model\User;
use App\Model\Comment;
class Story extends Model
{
use HasFactory;
protected $fillable = ['description', 'textStory'];
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class Comment:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Models\Story;
use App\Models\User;
class Comment extends Model
{
use HasFactory;
public function storyFunction()
{
return $this->belongsTo(Story::class);
}
public function userFunction()
{
return $this->belongsTo(User::class);
}
}
Stories migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('stories', function (Blueprint $table) {
$table->id();
$table->string('description');
$table->text('textStory');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('stories');
}
};
Comments migration:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('textComment');
//$table->foreignId('story_id')->constrained('stories')->onDelete('cascade');
/*$table->foreign('story_id')
->references('id')->on('stories')
->onDelete('cascade');*/
$table->timestamps();
});
Schema::table('comments', function(Blueprint $table) {
$table->foreignId('user_id')->constrained()->onDelete('cascade');
});
Schema::table('comments', function(Blueprint $table) {
$table->foreignId('story_id')->constrained()->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('comments');
}
};
But when i run php artisan migrate or php artisan migrate:refresh i see next error:
SQLSTATE[42P01]: Undefined table: 7 ?z?????С?s??: ??NВ????N??╡?????╡ "stories
" ???╡ N?N?NЙ?╡N?NВ??N??╡NВ (SQL: alter table "comments" add constraint "comment
s_story_id_foreign" foreign key ("story_id") references "stories" ("id") on dele
te cascade)
But if i delete or comment next strings in comments migration file:
Schema::table('comments', function(Blueprint $table) {
$table->foreignId('story_id')->constrained()->onDelete('cascade');
});
Migration run succesfull.
Please help me resolve this error.
Most likely, the table that Laravel finds using the conventions is missing. Specify the table explicitly as an argument to the constrained method like this Schema::table('comments', function(Blueprint $table) {
$table->foreignId('story_id')->constrained('Your_table_name')->onDelete('cascade');
});Foreign Key Constraints
Hi I need to insert data from register form to 2 or 3 tables, users and members. I need when you click on register button to send only user id and password to users.table and the rest informations into members.table
*edit
My model
namespace App;
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 = [
'name', 'email', 'password', 'admin', 'predmet',
];
/**
* 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',
];
}
My migration
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->bigIncrements('id');
$table->string('name');
$table->integer('admin');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
I need cote that will import the id, predmet and name to members table
First all of your field create nullable() like these
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->nullable();
$table->integer('admin')->nullable();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken()->nullable();
$table->timestamps();
});
then in the controller
public function store()
{
$user = new User;
$user->password = bcrypt($request->password);
$user->save();
$member = new Member;
$member->name = $request->name;
$member->username = $request->username;
$member->email= $request->email;
$member->save();
return back();
}
The product data always return null when i get the incoming_goods data (belongsTo).
Here is my Product Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Product extends Model
{
use SoftDeletes;
protected $guarded = [
'id', 'created_at', 'updated_at', 'deleted_at',
];
public function transaction_details()
{
return $this->hasMany('App\Transaction_detail');
}
public function incoming_goods()
{
return $this->hasMany('App\Incoming_good');
}
}
Here is my Incoming_good Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Incoming_good extends Model
{
protected $guarded = [
'id', 'created_at', 'updated_at',
];
public function product()
{
return $this->belongsTo('App\Product');
}
}
And here is my migration of that two table:
products table Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 50);
$table->integer('price');
$table->integer('stock')->nullable();
$table->integer('available');
$table->string('image1', 190)->nullable();
$table->string('image2', 190)->nullable();
$table->string('image3', 190)->nullable();
$table->string('image4', 190)->nullable();
$table->string('image5', 190)->nullable();
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('products');
}
}
incoming_goods migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTableIncomingGoods extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('incoming_goods', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id');
$table->integer('stock');
$table->text('note')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('incoming_goods');
}
}
Here is my code to show incomong_goods data and product (relation belongsTo):
$data = Incoming_good::select('id', 'stock', 'note', 'created_at')->with('product')->get();
I've try to use alies, but still it return the product data null. Hope you can help me :)
In order to match up the eager loaded Products with the Incoming_goods, Laravel needs the foreign key to be selected. Since you did not include the foreign key (product_id) in the select list, Laravel can't match up the related records after retrieving them. So, all your product relationships will be empty. Add in the foreign key to the select list, and you should be good.
$data = Incoming_good::select('id', 'product_id', 'stock', 'note', 'created_at')
->with('product')
->get();
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.
I am working on a project where, I have been assigned a task to create user management for the application. But I have stuck on the table relationship and their migration.
Effort
I have these tables:
Users
user_id
username
password
Profiles
profile_id
user_id
firstname
lastname
email
Address
address_id
profile_id
address
city
state
country
pincode
Configurations
config_id
configuration_name
configuration_type
parent_id
Now I have to create model and migration for the same above structure. For this i have create/modify below model and migration class.
Model: User
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'password',
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function profile()
{
return $this->hasOne('Profile','user_id');
}
}
Migration: 2014_10_12_000000_create_users_table.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('user_id');
$table->string('username');
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
Model: Profile
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
public function user(){
return $this->belongsTo('User');
}
public function address()
{
return $this->hasOne('Address','address_id');
}
}
Migration: 2016_02_26_101749_create_profiles_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->increments('profile_id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('user_id')->on('users')->onDelete('cascade');
$table->string('lastname')->nullable();
$table->string('firstname')->nullable();
$table->string('gender')->nullable();
$table->string('email')->unique();
$table->string('phonenumber', 20)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('profiles');
}
}
Model: Addess
namespace App;
use Illuminate\Database\Eloquent\Model;
class Address extends Model
{
public function profile(){
return $this->belongsTo('Profile');
}
public function city() {
return $this->hasOne('Configuration', 'config_id');
}
public function state() {
return $this->hasOne('Configuration', 'config_id');
}
public function country() {
return $this->hasOne('Configuration', 'config_id');
}
}
Migration: 2016_02_26_102805_create_addresses_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAddressesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->increments('address_id');
$table->integer('profile_id')->unsigned();
$table->foreign('profile_id')->references('profile_id')->on('profiles')->onDelete('cascade');
$table->string('address')->nullable();
$table->integer('city')->unsigned();
$table->foreign('city')->references('config_id')->on('configurations')->onDelete('cascade');
$table->string('pincode')->nullable();
$table->integer('state')->unsigned();
$table->foreign('state')->references('config_id')->on('configurations')->onDelete('cascade');
$table->integer('country')->unsigned();
$table->foreign('country')->references('config_id')->on('configurations')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('addresses');
}
}
Model: Configuration
namespace App;
use Illuminate\Database\Eloquent\Model;
class Configuration extends Model
{
public function children() {
return $this->hasMany('Configuration','parent_id');
}
public function parent() {
return $this->belongsTo('Configuration','parent_id');
}
public function address(){
return $this->belongsTo('Address');
}
}
Migration: 2016_02_26_104519_create_configurations_table.php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateConfigurationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('configurations', function (Blueprint $table) {
$table->increments('config_id');
$table->string('configuration_name');
$table->string('configuration_type');
$table->string('parent_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('configurations');
}
}
Now, when I run php artisan migrate I am getting error that :
.
Please suggest me how to do that. I have to use same table structure and cannot modify it. If any further update require or I forgot something please let me know.
That happen because migration will try to migrate address table before configuration so it will not found the foreign key config_id you're referenced, so you could change the name of migrations files then the migration commad could pass the configurations_table migrate file first then the addresses_table migrate file, so just change :
2016_02_26_104519_create_configurations_table.php
To :
2016_02_26_102005_create_configurations_table.php
_____________^
After that you should run optimize command to regenerating optimized class loader :
php artisan o
And rerun php artisan migrate command now the problem should be solved.
Hope this helps.