When using "find" on relation it gives me the pivot id - laravel-4

I have a Organization model and when i try to retrieve a specific user from this organization it gives me the user, but the ID on the user object is the pivot-id from the many-to-many relation table.
class Organization extends Eloquent
{
public function users()
{
return $this->belongsToMany('User', 'organizations_users', "organization_id" ,"user_id");
}
}
And a user model
class User extends Eloquent implements UserInterface, RemindableInterface
{
use RemindableTrait;
protected $table = 'users';
protected $hidden = array('password');
protected $fillable = array('email', 'password');
public function organizations()
{
return $this->belongsToMany('Organization', 'organizations_users');
}
}
But when i retrieve a specific organizations users with this method
$org = Organization::find(12);
$org->users()->find(4);
It returns the pivot-table id on the user-object instead of the users own id.
"id" => 74
"first_name" => "Thomas"
"last_name" => "Bolander"
....
"organization_id" => 12
"user_id" => 4
....
This works
$org = Organization::find(12);
$org->users()->where("users.id",4)->first();
Anybody have an idea whats wrong here ?

Hey Thomas you can try this too
$org->users()->getRelated()->find(4);
https://laravel.com/api/4.2/Illuminate/Database/Eloquent/Relations/BelongsToMany.html#method_getRelated

Related

laravel 8 store request with foreign key user_id not working

I would like to store the corresponding logged in user when adding a new School data. What I'm trying to do is store the logged in user_id in the schools table, in order to know on who added the school data. I have a users table already, which will establish the relation in the schools table.
My goal is when an admin is logged in, he/she can see all of the School records, otherwise if it's a user, then only fetch the records he/she added. The problem is that I can't figure out on when and where to insert the user_id data during the store request as I'm getting an error "user id field is required". Here's what I've tried so far:
Migration:
class CreateSchoolsTable extends Migration
{
public function up()
{
Schema::create('schools', function (Blueprint $table) {
$table->id();
$table->string('school_name');
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->timestamps();
});
}
}
School Model:
class School extends Model
{
use HasFactory;
protected $fillable = ['school_name', 'user_id'];
public function User() {
return $this->belongsTo(User::class);
}
}
Store Request:
class StoreSchoolRequest extends FormRequest
{
public function rules(): array
{
return [
'school_name' => 'required|string|max:255',
'user_id' => 'required|exists:users,id'
];
}
}
Controller:
class SchoolController extends Controller
{
public function store(StoreSchoolRequest $request) {
$school_data = $request->validated();
$user_id = \Auth::user()->id;
$school_data['user_id'] = $user_id;
School::create($school_data );
return Redirect::route('schools.index');
}
}
Any inputs will be of big help! Thanks.
Laravel has elegant way to bind authenticated user_id. Remove user_id from request class and chaining method. Also setup relationship from User model to School Model
Form Request Class
class StoreSchoolRequest extends FormRequest
{
public function rules(): array
{
return [
'school_name' => 'required|string|max:255',
];
}
}
User Model
protected $fillable = ['school_name', 'user_id'];
...
// new line
public function schools() {
return $this->hasMany(School::class);
}
Your Controller
class SchoolController extends Controller
{
public function store(StoreSchoolRequest $request) {
auth()->user()->schools()->create($request->validated());
return Redirect::route('schools.index');
}
}
UPDATE ANSWER
Since user_id value is school name (based on image link from comment), probably there's something wrong either in User or School model. Here the quick fix
Your Controller
class SchoolController extends Controller
{
public function store(StoreSchoolRequest $request) {
auth()->user()->schools()->create(
array_merge(
$request->validated(),
['user_id' => auth()->id()]
)
);
return Redirect::route('schools.index');
}
}
You can add 'created_by' and 'updated_by' fields to your table. so you can register in these fields when additions or updates are made.
Then you can see who has added or updated from these fields.
class School extends Model
{
use HasFactory;
protected $fillable = ['school_name', 'user_id', 'created_by', 'updated_by'];
public function User() {
return $this->belongsTo(User::class);
}
}
Your controller part is correct but since you get the logged in user, you wont be having user_id in the request. So you should remove the rules about user_id from your StoreSchoolRequest.
class StoreSchoolRequest extends FormRequest
{
public function rules(): array
{
return [
'school_name' => 'required|string|max:255'
];
}
}
Problem is here ..
$school_data = $request->validated();
Since you are using $request->validated()..
You have to safe()->merge user_id into it , here Docs : .
$validated = $request->safe()->merge(['user_id' => Auth::user()->id]);
Then put this $validated into create query , Thanks. –

Cannot Extend Laravel Model

I have 2 models. The User model, and the relationship works correctly, I use tinker, and I can see the application that is associated with the user.
User::find(4)->application
However, the application will not return the user - in tinker I get null, whats worse, if I try to access rep in tinker, I get Bad Method Exception Call
Application::find(8)->user
is null
Note: I have an id column in users which I "find" users. and there is "ucid" column in users that I have defined as the primaryKey in Application.
Application Model:
class Application extends Model
{
protected $data = [
'data' => 'array'
];
protected $primaryKey = 'ucid';
protected $fillable = [
'ucid', 'data'
];
public function user()
{
return $this->belongsTo(User::class,'ucid');
}
public function rep()
{
return 'Test';
}
}
User Model
class User extends Authenticatable
{
public function application()
{
return $this->hasOne(Application::class,'ucid');
}
}
What am I missing?
Can you try this? Let me know if it works..
Application Model
class Application extends Model
{
protected $data = [
'data' => 'array'
];
protected $primaryKey = 'ucid';
protected $fillable = [
'ucid', 'data'
];
public function user()
{
return $this->hasOne(User::class, 'ucid');
}
public function rep()
{
return 'Test';
}
}
User Model
class User extends Authenticatable
{
public function application()
{
return $this->belongsTo(Application::class, 'ucid', 'ucid');
}
}
As you see I switched hasOne and belongsTo in your models.
Also.. third argument on hasOne of Application Model is not required since value from $primaryKey will be used since its defined, however you have to specify the third argument in belongsTo of User model

How to get value from child table using eloquent in Laravel?

I have two table : users and profile.
A user may have one or multiple profile. I want to access the combined data of both table: 'ID' in user table is foreign key in profile table
User model :
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'first_name','last_name', 'email', 'password','phone','user_type',
];
protected $hidden = [
'password', 'remember_token',
];
public function profile()
{
return $this->hasMany(profile::class);
}
}
Profile model is :
class profile extends Model
{
protected $fillable = [
'id','relationship_status','dob','height',
'weight','primary_language'
];
protected $primaryKey = 'profile_id';
public function User()
{
return $this->belongsTo(User::class,'id','id');
}
}
Change your user model profile relationship like this
User Model
public function profile()
{
return $this->hasOne(Profile::class); //assuming your user has single profile
}
Profile model
class Profile extends Model
{
protected $fillable = [
'id', 'user_id', 'relationship_status','dob','height',
'weight','primary_language'
];
//add user_id field in profiles table
//protected $primaryKey = 'profile_id'; //no need of this, because you have id field in profiles table
public function user()
{
return $this->belongsTo(User::class);
}
}
after that you can fetch data like this
$user = User::find(2);
dd($user);
dd($user->profile)
When fetching multiple users details, then use eager loading
$users = User::with('profile')->get();
foreach($users as $user){
dd($user->profile)
}
Check details https://laravel.com/docs/5.6/eloquent-relationships#one-to-one

hasOne and belongsTo relation tables - laravel

My tables :
users :
id fname email
brands:
id title user_id_made
each user has many brands and each brand belongTo an user.
class Brand extends Model
{
protected $table = 'brands';
protected $fillable = array('title_fa',
'title_en','logo','user_id_made');
public function user()
{
return $this->hasOne('App\Models\User');
}
}
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'fname' ,'lname' , 'username', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function brand()
{
return $this->belongsTo('App\Models\Brand','user_id_made');
}
}
my code hasn't any output about users .
$data['brands'] = \DB::table('brands')->find(1);
var_dump($data['brands']);
return;
This will not load user. I will suggest you to use model instance in place of DB instance. if you want to load user with brands then you can use laravel's eager loading.
First in your Brand.php model
You need to pass the second argument as user_id_made to hasOne function otherwise it will assume it user_id.
public function user()
{
return $this->hasOne('App\Models\User','user_id_made');
}
You can do something like that.
$data['brands'] = Brand::with('user')->find(1);
Now If you will return $data['brands'] then it will return user information also.
Hope this will help.

unique name rule validation based on pivot table laravel

I have a system where renting companies have cars. A car can be available in many renting companies. So it is a many-to-many relationship.
I want to provide the companies with the possibility to add new cars when they buy them. If the car already exists, the system wouldn't create it, but flash an error message saying they already have that car.
How to use the unique validation rule on the name field of the Car being added? The challenge is that the Car model doesn't have the id of the company, and the pivot table doesn't have the name of the car, it contains just the car_id and the company_id.
Many thanks
My Car Model
class Car extends Model
{
protected $fillable = ['name'];
protected $dates = ['purchased_at'];
public function company(){
return $this->belongsToMany('App\Company')->withPivot('quantity', 'purchased_at')->withTimestamps();
}
}
My Company Model
class Company extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
protected $table = 'companies';
protected $hidden = ['password', 'remember_token'];
public function setPasswordAttribute($password){
$this->attributes['password'] = bcrypt($password);
}
public function cars(){
return $this->belongsToMany('App\Car')->withPivot('quantity', 'purchased_at')->withTimestamps();
}
}
My car Controller
class CarsController extends Controller
{
public function store(CarRequest $request)
{
$car = new Car;
$car->name = $request->input('name');
$car->save();
$car->company()->attach(Auth::user()->id,array('quantity' => $request->input('quantity'),'purchased_at' => \Carbon\Carbon::now()));
return Redirect('companies/'. Auth::user()->id .'/cars')->with(['success'=>'You have just created a new car!']);
}
}
My Car Request
class CarRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required | unique:car_company,car_id',
'quantity' => 'required'
];
}
}
I found a solution. Basically, we can conditionally modify a rule entry. In this case, I look for cars inside the authenticated company, if the car name exists, then I change the rule to be unique on the cars table, which will fail because there is already a car with the same name in this table.
Here is my new rules function inside my CarRequest class:
public function rules()
{
$rules = [
'quantity' => 'required',
];
$car = Auth::user()->cars->where('name', $this->input('name'));
if (count($car) === 0)
{
$rules['name'] = 'required';
}
else{
$rules['name'] = 'required | unique:cars';
}
return $rules;
}

Resources