Laravel - for some reason, max breaks my query - laravel

I have this piece of code:
$query = Student::whereHas('statusuri', function($q) use ($status) {
$q->latest('status_student.id')->take(1)
->where('status_id', $status)
->whereNotNull('status_id');
});
and it works fine, but I don't necessarily get the desired result.
I tried changing the first line to max (so I don't filter all my records then do a limit 1), I just get the highest ID from the beginning - like this:
$query = Student::whereHas('statusuri', function($q) use ($status) {
$q->max('status_student.id')
->where('status_id', $status)
->whereNotNull('status_id');
});
but then my query breaks.
For some reason, I get this:
Unknown column 'students.id' in 'where clause' (SQL: select max(`status_student`.`id`) as aggregate from `statusuri` inner join `status_student` on `statusuri`.`id` = `status_student`.`status_id` where `students`.`id` = `status_student`.`student_id`)
Why does my query break after I do this change?
Thanks.
Tables:
students
id bigint(20)
//other non-related data
statusuri
id bigint(20)
nume VARCHAR(255)
status_student
id int(11)
student_id int(10)
status_id int(10)
stare_stagiu_id int(11)
created_at timestamp
updated_at timestamp
statusuri() from Student
public function statusuri()
{
return $this->belongsToMany(Status::class, 'status_student')
->withPivot('id', 'data_inceput', 'data_sfarsit', 'document', 'status_id', 'stare_stagiu_id')
->withTimestamps();
}
Status and StatusStudent classes
class StatusStudent extends Model
{
protected $table = 'status_student';
protected $fillable = ['id', 'student_id', 'status_id', 'stare_stagiu_id'];
}
class Status extends Model
{
protected $table = 'statusuri';
public $fillable = ['nume'];
}

Your relations are messed up. The query is trying to use a column from the student table, but the student table is not available in said query as it is not joined. See this fiddle to see what goes wrong in the SQL.
http://sqlfiddle.com/#!9/52c96fa/6
In the end, I'd do it like this if I understood you correctly:
In StatusStudent.php (Model):
public function student() {
return $this->hasOne(Student::class, 'id', 'student_id');
}
In Controller:
public function stackoverflowtest() {
//Set teststatus
$status = 1;
//Get the latest status of all users - and if that status is correct, retrieve into array
$latest = DB::select( DB::raw("SELECT max(id) as id, student_id FROM status_student group by student_id"));
$array = [];
foreach ($latest as $l) {
$status_id = StatusStudent::whereId($l->id)->whereStatusId($status)->first();
if ($status_id) {
array_push($array, $status_id);
}
}
//$array now holds all the StatusStudent, simply user ->student to get the student related to said status, example below
if($array) {
dd($array[0]->student);
return $array;
} else {
return 'No match';
}
}
First, we get all latest records for each user IF the status is correct. Then, we simply get the Student from the status_student table via the relation.

Related

Search Query by Child field Eloquent relation

My Product Model is
public function IncomeRepo(){
return $this->hasMany(Income::class,'Product');
}
My Income Report Model Is
public function ProductData(){
return $this->belongsTo(Product::class,'Product','id');
}
My Query is
public function SearchIncomeData(Request $request){
$GetFromDate = $request->FromDate;
$GetToDate = $request->ToDate;
$ProductData = Product::with('IncomeRepo')->whereBetween('created_at', [$GetFromDate, $GetToDate])->get();
return view('Admin.Report.ProductSalesReport',compact('ProductData'));
}
When I return $ProductData it return products table created_at Data. BUT I nee Income table created_at data which be multiple
How can I get it?
My expectation show incomes table created_at data
If you want to filter data by child tables date then you need to use whereHas relationship.
$GetFromDate = $request->FromDate;
$GetToDate = $request->ToDate;
$ProductData = Product::with('IncomeRepo')
->whereHas('IncomeRepo',function($que) use($GetFromDate,$GetToDate) {
$que->whereBetween('created_at',[$GetFromDate, $GetToDate])})->get();
return view('Admin.Report.ProductSalesReport',compact('ProductData'));
In controller. (Use whereBetween)
public function SearchIncomeData(Request $request)
{
$GetFromDate = $request->FromDate;
$GetToDate = $request->ToDate;
$ProductData = Product::with(['IncomeRepo' => function ($query) use ($GetFromDate, $GetToDate)
{
$query->whereBetween('created_at', [$GetFromDate, $GetToDate]);
}
])->get();
return view('Admin.Report.ProductSalesReport', compact('ProductData'));
}
In view
foreach ($ProductData as $product)
{
foreach ($product->IncomeRepo as $income)
{
echo $income->created_at;
}
}

Laravel - How to get max_score of related parent of a child

In my Laravel-5.8 project, I have this table:
CREATE TABLE `appraisal_goal_types` (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
`max_score` int(11) DEFAULT 0,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
From the table, if parent_id is null then the row is a parent. Each child field will have its parent_id. The parent can have many child rows. Also, Only the parent can have value for max_score. The child will have 0 as its default for max_score
In my view blade I have a dropdown that will only be populated with the child fields.
I have written this function in my Controller
public function maxScore(Request $request)
{
$data = DB::table('appraisal_goal_types')->select('max_score')->where('id', $request->id)->first();
return response()->json($data);
}
When a child field is selected, I want to load the max_score of its parent.
How do I complete the code in the function above to select the max_score of the parent of a requested id of the child.
Thank you.
Use conditional statement to get max_score :
public function maxScore(Request $request)
{
$item = DB::table('appraisal_goal_types')->find($request->id) or abort(404);
$return['max_score'] = $item->parent_id == null ? $item->max_score : 0;
return response()->json($return);
}
If $request->id is a child, and you don't have relation in model, you can use :
public function maxScore(Request $request)
{
$child = DB::table('appraisal_goal_types')->find($request->id) or abort(404);
$parent = DB::table('appraisal_goal_types')->select('max_score')->find($child->parent_id);
return response()->json($parent);
}
Or you can add relation method :
Your Model
public function parent()
{
return $this->hasOne(Model::class, 'id', 'parent_id');
}
Once the relationship has been defined, you can retrieve the parent :
public function maxScore(Request $request)
{
$child = Model::find($request->id) or abort(404);
$parent['max_score'] = $child->parent->max_score;
return response()->json($parent);
}
You can see my answer https://stackoverflow.com/a/60373514/984422
so do it like this:
public function maxScore(Request $request)
{
$child = DB::table('appraisal_goal_types')->find($request->id);
if($child) {
$data['child'] = $child;
$data['parent'] = DB::table('appraisal_goal_types')->select('max_score')->find($child->parent_id);
}
return response()->json($data);
}

Relationship hasManyThrough in Laravel?

I have three models: User, Category, Announcement.
User model:
public function categories()
{
return $this->belongsToMany("App\Category");
}
public function announcements()
{
return $this->hasManyThrough('App\Announcement', 'App\Category');
}
Category model:
public function announcements()
{
return $this->belongsToMany('App\Announcement');
}
Announcement model:
public function categories()
{
return $this->belongsToMany('App\Category');
}
I need to select all announcements through user_categories table.
For this I do:
$res = User::where("id", 1)->with("announcements")->get();
dd($res);
In result I get SQL error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'announcements.category_id' in 'on clause' (SQL: select `announcements`.*, `categories`.`user_id` from `announcements` inner join `categories` on `categories`.`id` = `announcements`.`category_id` where `categories`.`user_id` in (1) and `announcements`.`deleted_at` is null)
Why Laravel does try to search ``announcements.category_id` in table?
In conclusion I need to get all announcements on categories which user subscribed.
Table Database structure:
Users
id | name
Announcements
id | name
categories
category_id | announcement_id
users_categories
category_id | user_id
So, I need to get all announcements through table users_categories where there are relation this table with categories that is belong to announcement table.
You cannot eager load this relationship because
To perform this query, Eloquent inspects the foreign key on the intermediate table.
Thus the error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'announcements.category_id'
Because HasManyThrough() looks for the relationship in the specified model table.
I would suggest you look at this thread:
https://laravel.io/forum/05-21-2014-problem-with-eloquents-hasmanythroughs-query
They show you how to write your own query to do that. An example would be, in the user model do
public function getAnnouncements() {
$announcements = [];
foreach( $this->categories as $category ) {
foreach( $category->announcements as $annoucement ) {
if ( !isset($announcements[$annoucement->id]) ) { //avoid duplicates
$annoucements[$announcement->id] = $announcement;
}
}
}
}
The nested foreach will give all announcement belonging to a category that related to a user.
Improving the function
public function getAnnouncements() {
$announcements = new Collection();
foreach( $this->categories as $category ) {
$announcements->collect($category->announcements);
}
}

Error Number: 1066 Not unique table/alias: 'core_user'

I have 3 tables in a database.
core_user
core_company
ct_company
i want to join 2 tables core_user and core_company where foriegn key is cmp_id column..
but it shows an error.
Error Number: 1066
Not unique table/alias: 'core_user'
SELECT * FROM (core_user, core_user) JOIN core_company ON core_company.cmp_id = core_user.cmp_id WHERE usr_email = 'fahad#gmail.com' AND usr_password = '123456' AND cmp_name = 'corpoleave'
Filename: F:/xampp/htdocs/corpoLeave/application/models/loginmodel.php
Line Number: 10
here is my model. please help. thanks
<?php class LoginModel extends CI_Model{
public function login_valid($email,$password,$cname){
$q= $this->db->where(['usr_email'=>$email,'usr_password'=>$password,'cmp_name'=>$cname])
->from('core_user');
$this->db->join('core_company', 'core_company.cmp_id = core_user.cmp_id');
$q = $this->db->get('core_user')->result();
if($q->result()==true)
{
return $q->row()->user_id;
}
else{
return false;
}
}}
?>
In the Codeigniter Query Builder, the get() and from() methods perform similarly.
As seen on the Codeigniter docs:
get()
$query = $this->db->get('mytable');
// Produces: SELECT * FROM mytable
from()
$this->db->select('title, content, date');
$this->db->from('mytable');
$query = $this->db->get();
// Produces: SELECT title, content, date FROM mytable
Both the get("tablename") and from("tablename") methods effectively append FROM tablename to the built statement, looking something like this:
$this->db->select('title, content, date');
$this->db->from('mytable');
$query = $this->db->get('mytable');
// Produces: SELECT title, content, date FROM mytable FROM mytable
(Notice the double "FROM" statement)
You are getting the error because you are using both from() and get() with tablenames. You can either remove the from() statement, or remove the tablename from the get() statement.
This would look like:
<?php
class LoginModel extends CI_Model {
public function login_valid($email, $password, $cname) {
$this->db->where(['usr_email' => $email, 'usr_password' => $password, 'cmp_name' => $cname]);
$this->db->from('core_user');
$this->db->join('core_company', 'core_company.cmp_id = core_user.cmp_id');
$q = $this->db->get();
if ($q->result()) {
return $q->row()->user_id;
} else {
return false;
}
}
}

Laravel how to get a Model by two parameters

Hi I'm new to Laravel and got stuck in a Problem.
I have a model Contact
class Contact extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'contacts';
}
The table have these fields:
user_id (int)
contact_id (int)
...
these two fields represent the primary key.
In the ContactsController I have the function store in wich I create or update the database:
public function store()
{
switch (Input::get('type')){
case 'make_contact_request':
$user = User::where('email', '=', Input::get('login'));
$request_self = new Contact;
$request_contact = new Contact;
$request_self->user_id = Auth::user()->id;
$request_self->contact_id = $user->id;
$request_self->status = 2;
$request_self->message = Input::get('message');
$request_contact->user_id = $user->id;
$request_contact->contact_id = Auth::user()->id;
$request_contact->status = 1;
$request_contact->message = Input::get('message');
$request_self->save();
$request_contact->save();
break;
case 'answer_contact_request':
$request_self = Contact::where('user_id', '=',Input::get('contact_id'))->where('contact_id', '=', Auth::user()->id)->first();
//$request_self = Contact::whereRaw('user_id = '.Input::get('contact_id').' AND contact_id = '.Auth::user()->id.' ');
$request_contact = Contact::whereRaw('user_id = '.Auth::user()->id.' AND contact_id = '.Input::get('contact_id').' ');
$request_self->status = 3;
$request_contact->status = 3;
$request_self->save();
$request_contact->save();
break;
}
}
I tried two different ways to get the Contact Object for the request_self Object and I get the following error:
message: "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: update `contacts` set `status` = 3, `updated_at` = 2014-08-02 16:16:56 where `id` is null)"
for the request_contact Object it throws a fatal error (don't get the description) and close the session.
At the end I am at the beginning of laravel so I hope the solution is pretty easy to find :) but I dont even really know for what to search.
Update:
At the end I fixed the Problem with the update function.
case 'answer_contact_request':
$request_self = Contact::where('user_id', '=',Input::get('contact_id'))->where('contact_id', '=', Auth::user()->id)->update(array('status' => 3));
$request_contact = Contact::where('user_id', '=', Auth::user()->id)->where('contact_id', '=', Input::get('contact_id'))->update(array('status' => 3));
break;
I think you can add
public function scopeComposite($query, $user_id, $contact_id)
{
return $query->where('user_id', '=', $user_id)->where('contact_id', '=', $contact_id);
}
and then you can get the contact with:
$request_self = Contact::composite(Input::get('contact_id'), Auth::user()->id)->get();
source: http://laravel.com/docs/eloquent#query-scopes
I'm not sure you can make it like this.
There is a way to make sure it works:
add a column id ( auto increment, primary ) and make the group ( contact_id, user_id ) unique and you can use query scopes and id based

Resources