How to query a customize key in Laravel? - php

Considering this tables: person and employee to which connected to person by person_id. This person_id is also the Primary & Foreign key of employee table. Thus in my migrations, i have this:
Schema::create('employees', function (Blueprint $table) {
$table->bigIncrements('person_id');
$table->foreign('person_id')->references('id')->on('persons')->onDelete('cascade');
});
and my show method is like this one
public function show(Employee $employee){
dd($employee->person_id);
$employee = Employee::where('person_id', $employee->person_id)->orderBy('employee_number', 'asc')->join('persons', 'employees.person_id', '=', 'persons.id')->first();
return view('employee.show', compact('employee'));
}
But i am experiencing this issue:
Illuminate\Database\QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: select * from `employees` where `id` = 5 limit 1)
Does the query is not aware of the column i am using?

Change the primary key in the Employee model
class Employee extends Model
{
/**
* The primary key associated with the table.
*
* #var string
*/
protected $primaryKey = 'person_id';
public function person()
{
return $this->belongsTo('App\Employee', 'person_id', 'person_id');
}
}
Then query using find
Employee::find($employee->person_id)->with('person')->first();
orderBy and first are redundant on one result queries
And if you want to return the Employee with the Person, just access the relationship object (employee is returned from route model binding)
public function show(Employee $employee) {
$person = $employee->person;
return view('employee.show', compact('employee', 'person'));
}
Hope this helps

Related

Why is the request not working correctly when using BelongsToMany Laravel?

I have 2 models in my app, 'Subject' & 'Professor' (each Subject belongs to many Professors).
I made the many-to-many relation between two model using belongsToMany(). belongsToMany() doesn't work.
I'm trying to get data like this:
$subjects = Subject::with(["professors"])->whereHas("professors", function ($q){ $q->where("id", \request("professor_id")); })->get();
Error:
"SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous (SQL: select * from `subjects` where exists (select * from `professors` inner join `subjects_of_professor` on `professors`.`id` = `subjects_of_professor`.`professor_id` where `subjects`.`id` = `subjects_of_professor`.`subject_id` and `id` = 39))",
Does anyone know where did I make a mistake?
Here's the code to Models:
class Subject extends Model
{
public function professors(): BelongsToMany
{
return $this->belongsToMany(Professor::class, "subjects_of_professor");
}
}
class Professor extends Model
{
public function subjects(): BelongsToMany
{
return $this->belongsToMany(Subject::class, "subjects_of_professor");
}
}
And here is my database structure:
subjects:
id
title
subjects_of_professor:
id
subject_id
professor_id
professors:
id
name
description
I'm found mistake, i was needed to add table in my code, when i trying to get data:
$subjects = Subject::whereHas("professors", function ($q){ $q->where("professors.id", \request("professor_id")); })->get();

Controller keeps generating SQL query with wrong foreign key name

I have a database tables Users, Listings
Users table:
id, name, email, password
Listings table:
id, title, seller_id
Listing migration:
public function up()
{
Schema::create('listings', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->bigInteger('seller_id')->unsigned();
$table->timestamps();
$table->foreign('seller_id')->references('id')->on('users')->onDelete('cascade');
});
}
User model:
public function listings()
{
return $this->hasMany(Listing::class);
}
Listing model:
public function seller()
{
return $this->belongsTo(User::class, 'seller_id', 'id');
}
ListingResource:
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ListingResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return parent::toArray($request);
}
}
ListingsController:
public function index()
{
return ListingResource::collection(auth()->user()->listings()->latest());
}
I keep getting this error:
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'listings.user_id' in 'where clause' (SQL: select * from listings where listings.user_id = 1 and listings.user_id is not null order by created_at desc limit 1)"
How come it returns the query with user_id as the foreign key, even though I specifically put 'seller_id' as the foreign key inside the User.php model?
I have tried to put:
public function listings()
{
return $this->hasMany(Listing::class, 'seller_id');
}
As I have read that this could work, but this generates the following error:
"Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::mapInto()"
While the error message isn't the most clear for this, what is essentially happening is that {Resource}::collection($collection); requires a Collection to function, but at the current point in it's lifecycle, your argument is a Builder instance. To fix this, simply pass a closure to convert your Builder to a Collection:
public function index(){
return ListingResource::collection(auth()->user()->listings()->latest()->get());
}
->latest() is shorthand for ->orderBy('created_at', 'DESC'); (or id, not sure which it uses internally), but doesn't actually execute the query. Simply adding ->get() will convert the Builder to a Collection and allow this resource to work.
On another note, the original error was being caused by missing seller_id in your listings() function on your User model. The foreign id of any relationship is guessed by Laravel based on the Model name (User translates to user_id), but since you're using seller_id, you need to specify that in both the original relationship and in the inverse definition. You figured that out, but a quick explanation is always helpful.

Search pivot table Eloquent

I have 3 tables
students
- id
- name
classes
- id
- name
student_class
- id
- student_id
- class_id
- score
I want to return a list of the students that belong to class_id = 100
$students = \Student::where(['class_id' => 100])->get();
this is my Student Class
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
protected $table = 'students';
public function store(Request $request)
{
$student = new Student;
$student->save();
}
}
the error I´m getting is:
<strong>Message:</strong> SQLSTATE[42S22]: Column not found: 1054 Unknown column 'class_id' in 'where clause' (SQL: select * from `students` where (`class_id` = 100))
update: I can do
$students = \Class::find(100)->with(['students'])->get();
and it will return all the students as a child of classes but I don´t need that.
I need the data from students and the pivot table (student_class) in particular de score column.
thank you for your help
Update your student model as
public function classes(){
return $this->belongsToMany(Class::class, 'student_class', 'student_id', 'class_id');
}
//query
Student::whereHas('classes', function ($query) {
$query->where('id', 100);
})->get();
UPDATE : in both of your model relation add
return $this->belongsToMany('App\Class')->withPivot('score');
now you can do this inside your loop
foreach ($student->classes as $class) {
echo $class->pivot->score;
}

Laravel 5.3 hasManyThrough through an intermediate table

I have the following table relationship:
organizations
id - integer
organization_users
organization_id - integer (FK)
user_id - integer (FK)
users
id - integer
I am trying to get all the users of an organization through eloquent relationships. Here is my Organization.php model with its relationships:
class Organization extends Model
{
public function Users(){
return $this->hasManyThrough('App\User', 'App\OrganizationUser',
'organization_id', 'user_id', 'id');
...
}
I have tried many combinations of that relationship such as
return $this->hasManyThrough('App\User', 'App\OrganizationUser',
'user_id', 'organization_id', 'id');
But all turn up somewhat the same error (this one is from the first query):
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not
found: 1054 Unknown column 'organization_users.id' in 'on clause' (SQL: select
`users`.*, `organization_users`.`organization_id` from `users` inner join
`organization_users` on `organization_users`.`id` = `users`.`user_id` where
`organization_users`.`organization_id` = 1)'
Is it possible that I can have the relationship retrieve the user_id to query on the users table instead of Laravel trying to retrieve organization_users.id? If not is there another way around this?
This is many to many relationship.
User Model:
public function organizations()
{
return $this->belongsToMany('App\Organization','organization_users');
}
Organization Model:
public function users()
{
return $this->belongsToMany('App\User','organization_users');
}
To, get all the users with their organizations:
$users=User::with('organizations')->get();
foreach($users as $user)
{
print_r($user->name);
foreach($user->organizations as $organization)
{
print_r($organization->name);
}
}
What you are describing looks like it may be a 'Many-to-Many' relationship.
https://laravel.com/docs/5.3/eloquent-relationships#many-to-many

Has many through

A Venue has many Subscriptions.
A Subscription has many Subscribers (User).
Theres a pivot table, containing the relation between user_id and subscription_id.
How can I get all Subscribers from a Venue?
I have tried with:
class Venue {
/**
* Members
*/
public function members() {
return $this->hasManyThrough('App\User', 'App\Subscription');
}
}
But it fails with MySQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.subscription_id' in 'on clause' (SQL: select `users`.*, `sub
scriptions`.`venue_id` from `users` inner join `subscriptions` on `subscriptions`.`id` = `users`.`subscription_id` where `
users`.`deleted_at` is null and `subscriptions`.`venue_id` = 1)
How my Subscription model look:
`Subscription`
class Subscription extends Model {
protected $table = 'subscriptions';
/**
* Subscripers
*/
public function subscribers() {
return $this->belongsToMany('App\User');
}
/**
* Venue
*/
public function venue() {
return $this->belongsTo('Venue');
}
}
Simple question: Why are you using a third model for Subscriptions? It sounds like a normal n:m relation between User and Venue, as already written in the comments above.
class User {
public function venues() {
return $this->belongsToMany('App\Venue');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User');
}
}
This constellation actually needs three tables, which are (i gave each model a column name):
users
- id
- name
venues
- id
- name
user_venue
- user_id
- venue_id
But to access the relations, you can simply use the Eloquent magic:
// List of all venues (as Venue models) that are in relation with User with id $id
$venues = User::find($id)->venues()->get();
// Returns the alphabetically first user that has a relation with Venue with id $id
$user = Venue::find($id)->users()->orderBy('name', 'asc')->first();
If you need to store additional information in the pivot table (e.g. when the relation has been established), you can use additional pivot fields:
user_venue
- user_id
- venue_id
- created_at
class User {
public function venues() {
return $this->belongsToMany('App\Venue')->withPivot('created_at');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User')->withPivot('created_at');
}
}
// Returns the date of the relations establishment for the alphabetically
// first Venue the User with id $id has a relation to
$created_at = User::find($id)->venues()->orderBy('name', 'asc')->first()->pivot->created_at;
I've never tried to do whatever you are trying to do there, because it seems (with the current information) conceptually wrong. I also don't know if it is possible to set up an own model for a pivot table, but I think it should work if the pivot table has an own primary id column. It could probably be helpful if you've a third model that needs to be connected with a connection of two others, but normally that doesn't happen. So try it with pivot tables, like shown above, first.
Alright, I still don't see a good use case for this, but I can provide you a query that works. Unfortunately I wasn't able to get an Eloquent query working, but the solution should be still fine though.
class Venue {
public function members($distinct = true) {
$query = User::select('users.*')
->join('subscription_user', 'subscription_user.user_id', '=', 'users.id')
->join('subscriptions', 'subscriptions.id', '=', 'subscription_user.subscription_id')
->where('subscriptions.venue_id', '=', $this->id);
if($distinct === true) {
$query->distinct();
}
return $query;
}
}
The relation can be queried just as normal:
Venue::find($id)->members()->get()
// or with duplicate members
Venue::find($id)->members(false)->get()

Categories