I'm developing a Laravel 9 web app and there I have two tables (users and feedbacks) which connects using a foreign key named username. One single user can have many feedbacks. As I know if I get details of a a user those data contains the relevant feedbacks too. My issue is that the user data is fetched properly but it comes with all feedbacks and not the feedbacks which connect to that specific user. The Laravel executes a query like this.
select * from `feedback` where `feedback`.`username` = 0 and `feedback`.`username` is not null
As I understand 0 should be replaced by the user's username. What is the issue here?
Feedback Model-
class Feedback extends Model
{
use HasFactory;
//One single user can have many feedbacks.
public function user() {
return $this->belongsTo(User::class);
}
}
User model-
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array<int, string>
*/
protected $fillable = [
'name',
'username',
'gender',
'email',
'password',
'is_admin',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
'is_admin',
];
protected $primaryKey = 'username';
public function feedbacks() {
return $this->hasMany(Feedback::class, 'username');
}
/**
* The attributes that should be cast.
*
* #var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
create_users_table migration-
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('userId');
$table->string('name');
$table->string('username')->unique();
$table->string('gender');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->boolean('is_admin')->default(0);
$table->rememberToken();
$table->timestamps();
});
}
create_feedback_table migration-
public function up()
{
Schema::create('feedback', function (Blueprint $table) {
$table->increments('feedbackId');
$table->text('feedback');
$table->string('username');
$table->timestamps();
$table->foreign('username')
->references('username')
->on('users')
->onDelete('cascade');
});
}
FeedbackController to get the data,
class FeedbackController extends Controller
{
public function giveFeedback($username)
{
$userData = User::find($username);
dd($userData->feedbacks);
return view('feedback.givefeedback', compact('userData'));
}
}
users table-
feedback table-
This is the output on the blade, As you can see it outputs all the feedback even though I only requested the feedbacks of nerigupex using routes.
Please request if you need more code to resolve this issue, I will update the question accordingly. TIA.
Do like this (Only addressing Dataload issue)
1. Refator the Migration
User Migration
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id'); # change your current primary key to this
.... rest of the code
}
Feedback Migration
Schema::create('feedback', function (Blueprint $table) {
$table->bigIncrements('id'); # change your current primary key to this
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
.... rest of the code
}
2. Refator the Model
//protected $primaryKey = 'username'; --> remove this
public function feedbacks() {
return $this->hasMany(Feedback::class);
}
3. In Feedback Controller
class FeedbackController extends Controller
{
public function giveFeedback($username)
{
$userData = User::with('feedbacks')->where('username', $username)->get();
dd($userData->feedbacks);
return view('feedback.givefeedback', compact('userData'));
}
}
Related
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();
}
I have the following code in my App\User model.
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username','dob','name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token','created_at','updated_at',
];
protected $dates =[
'dob',
];
public function roleuser(){
return $this->belongsTo('App\Role');
}
}
class CreateRolesTable extends Migration
{
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('rolename');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('roles');
}
}
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->unsigned()->default(2);
$table->string('username',32);
$table->date('dob');
$table->string('name');
$table->string('email');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
}
i'm using 1 to 1 relationship between user and role.
Calling {{ Auth::user()->roleuser }} from a Blade template returns null but I am expecting a App\Role instance.
Can someone tell me what's wrong?
I'm using 1 to 1 relationship between user and role.
If you're using a one to one relationship, you should use the hasOne method that way it will return an instance of the model and not a collection which I think is what you're getting now (not null) like you thought.
You have to define the key used for the relationship. You are not passing any additional paremeters to the relationship method to override the naming conventions. By default it looks for very particular named fields. It is going to look for roleusers_id because you named the method roleusers instead of the more normal role name. If you named it role it would look for the role_id field by default. You will need to override the key used if you keep it named roleusers. [The docs mention this directly]
Laravel 5.3 Docs - Eloquent - Relationships - One to Many (Inverse)
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 trying to fetch the type of user using the foreign key in the users table i.e. user_types_id but when I do it I just get null and cant get into the function userType in User Model. Any help would be much appreciated.
Thank you in advance. I have provided related models and tables
Controller
public function dashboard() {
$userType = UserType::all();
$id = Auth::user()->id;
var_dump($id); // returns id
$users = User::find($id);
var_dump($user->user_types_id); // returns user_type_id in users table
if($users->userType){
var_dump($users->userType->types); // error is in here. Not taking userType.
} else {
echo 'does not exit';
}
die();
return view('dashboard', compact('users'));
}
User Model
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\UserType;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function userType() {
return $this->belongsTo(UserType::class);
}
}
UserType Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\User;
class UserType extends Model
{
protected $fillable=['types'];
public function users() {
return $this->hasMany(User::class);
}
}
User Table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_types_id')->unsigned()->index();
$table->string('username')->unique();
$table->string('password');
$table->string('salt');
$table->rememberToken();
$table->timestamps();
});
}
UserType Table
public function up()
{
Schema::create('user_types', function (Blueprint $table) {
$table->increments('id');
$table->string('types');
$table->timestamps();
});
}
You've named your relation userType, therefore Eloquent assumes that the foreign key is called user_type_id, not user_types_id.
Replace
return $this->belongsTo(UserType::class);
with
return $this->belongsTo(UserType::class, 'user_types_id');
to tell Eloquent the name of foreign key column and it should work.
I have been stuck for most of the day getting an empty array any time I eager loaded product images while requesting products in my controller in Laravel.
public function ProductImages() {
return $this->hasMany('App\ProductImage', 'product_id'); // this matches the Eloquent model
}
I changed my code to make the FK 'test' and suddenly it has started returning the appropriate data I want back. I put the FK back to product_id but again am back to an empty array. Below are My product Model ProductImages Model and the migrations for both with the call Im making in the controlelr
Product Model
class Product extends Model
{
protected $fillable = array('name', 'url_name', 'sku', 'description', 'short_description', 'enabled', 'track_inventory', 'stock_level', 'allow_backorder', 'updated_user_id' );
//protected $hidden = array('id');
// LINK THIS MODEL TO OUR DATABASE TABLE ---------------------------------
// Database table is not called my_products
protected $table = 'products';
// each product HAS many product images
public function ProductImages() {
return $this->hasMany('App\ProductImage', 'productId'); // this matches the Eloquent model
}
}
Product Images Model
class ProductImage extends Model
{
protected $fillable = array('name', 'description', 'path', 'sort_order', 'product_id');
// DEFINE RELATIONSHIPS --------------------------------------------------
// each attribute HAS one product
public function Product() {
return $this->belongsTo('App\Product', 'id'); // this matches the Eloquent model
}
}
Product 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');
$table->string('url');
$table->string('sku');
$table->string('description');
$table->string('short_description');
$table->integer('enabled');
$table->integer('track_inventory');
$table->integer('stock_level');
$table->integer('allow_backorder');
$table->dateTime('updated_user_id');
$table->timestamps();
});
}
}
Product Images Migration
class CreateProductImagesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('product_images', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->string('path');
$table->integer('sort_order');
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->timestamps();
});
}
}
Product Controller Snippet
public function index()
{
//
$Products = Product::with('ProductImages','productTypes')->get();
//dd($Products);
return response()->json( $Products, 200);
}
If you could help me understand why this strange behavior is happening i would be very grateful.