Laravel Relationships - Questions, Answers and userAnswers - php

I have some problem, i have 3 tables:
questions
id | text
answers
id | question_id | text
user_answers
id | user_id | question_id | text
Example records:
questions
1 | Gender
2 | Age (input type, answers not exist in answers table)
3 | What kind of pets do you have?
answers
1 | 1 | Male
2 | 2 | Female
3 | 3 | Cat
4 | 3 | Dog
5 | 3 | Parrot
user_answers
1 | 100 | 1 | 1
2 | 100 | 2 | 30
3 | 100 | 3 | 4
3 | 100 | 3 | 5
So, I wonder if exists the way to do relationships without RAW SQL (with joins etc.) in models. For example, something like this:
$questions = Question::with('userAnswer')->where('user_id', 100);
foreach($questions as $q)
{
echo $question->text;
foreach($question->userAnswers as $ans)
{
echo $ans->text
}
}
And result:
Gender
- male
Age
- 30
What kind of pets do you have?
- dog
- parrot
You know what I mean? Some ideas? :)
Thank You for Your attention!
EDITED:
This not work (relation stdAnswer is empty),
$questions = LucidStandardQuestion::with('userAnswers.stdAnswer')->find(x);
this work:
LucidStandardQuestion::with('userAnswers')->find(x)
and in model LucidStandarQuestion:
public function userAnswers()
{
$uid = 1576;
return $this->hasMany(LucidUserAnswer::Class, 'question_id')->where('user_id' , $uid);
}
and in model LucidUserAnswer:
public function stdAnswer()
{
return $this->belongsTo(LucidStandardAnswer::class, 'question_id');
}

It's a simple hasMany relation:
class Question extends Model
{
public function userAnswer()
{
return $this->hasMany(LucidUserAnswer::class,'question_id');
}
}
Now your code may look like:
$questions = Question::with(['userAnswer' => function($query)
{
$query->where('user_id', 100)->with('answer');
}])->get();
and in LucidUserAnswer model you should make the relation
class LucidUserAnswer extends Model
{
public function answer()
{
return $this->belongsTo(Answer::class,'text');
}
}

Related

How to filter post by category in laravel?

I am currently trying to make a relation between 3 tables.
post
id
name
category
id
name
post_category
id
post_id
category_id
Database
post
| 1 | post1 |
| 2 | post2 |
| 3 | post3 |
category
| 1 | cat1 |
| 2 | cat2 |
| 3 | cat3 |
post_category
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 2 |
| 3 | 2 | 2 |
| 3 | 1 | 3 |
Model Post.php
public function getCategory()
{
return $this->belongsToMany(Category::class, 'post_category');
}
PostController.php
$data = Post::with('getCategory')->get();
It returns correct post list.
Now i want to filter the post by category. I try, but it not working
$categoryId = [1,2];
$data = Post::with('getCategory')->whereHas('category', function ($query) use ($categoryId) {
$query->whereIn('id', $categoryId);
})->orderBy('id','DESC')->get();
please help me
use Laravel 5.4
apparently everything is fine!
One suggestion is to add two more parameters to the belongsToMany method, like:
public function getCategory()
{
return $this->belongsToMany(Category::class, 'post_category', 'post_id', 'category_id');
}
https://laravel.com/api/7.x/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_belongsToMany
You should rename your getCategory() function to simply category(). That makes the relation names much more straightforward and probably fixes your issue.
THEN, you should be able to call whereHas('category', ...).
If it still does not work, simply chain a ->toSql() to any of your queries and debug the actual query that way.

How to fetch record from three table in laravel eloquent

I have four tables
jobposts:
id | user_id | cat_id | job_title
1 | 1 | 1 | job 1
2 | 1 | 2 | job 2
3 | 2 | 3 | job 3
4 | 1 | 3 | job 4
categorymasters:
id | category_name
1 | cat1
2 | cat2
3 | cat3
4 | cat4
lastsubcategoryselectedbycompanies:
id | jobposts_id | lastsubcategorymasters_id
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
4 | 1 | 3
lastsubcategorymasters:
id | LastSubCategoryName
1 | lastsubcat1
2 | lastsubcat2
3 | lastsubcat3
4 | lastsubcat4
jobposts have unique rows.
lastsubcategoryselectedbycompanies is a mapping of jobposts and lastsubcategorymasters.
Now assume some user is logged in with their credentials (EX: take user_id 1 in jobposts). Now I need to show LastSubCategoryName in a comma separated list from the lastsubcategorymasters table, grouped by the jobposts, lastsubcategoryselectedbycompanies and lastsubcategorymasters tables.
allpostedjob.blade.php is:
#foreach($jobposteddetails as $jobposteddetail)
<tr>
<td>{{ $jobposteddetail->job_title }}</td>
</tr>
#endforeach
cotroller is:
public function index()
{
$user = Auth::user();
$jobposteddetails = jobpost::with('categorymaster')->where('user_id', '=', $user->id)->get();
return view('jobprovider.allpostedjob', compact('user','jobposteddetails'));
}
jobpost.php model is:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class jobpost extends Model
{
function categorymaster()
{
return $this->belongsTo(categorymaster::class, 'cat_id');
}
}
It is working proper.
But I also need to show LastSubCategoryName grouped by the tables jobposts, lastsubcategoryselectedbycompanies and lastsubcategorymasters.
function lastsubcategory()
{
return $this->belongsTo(lastsubcategoryselectedbycompanies::class);
}
It is not working. How can I fetch my result?
I am not very skilled at applying complex queries with eloquent, I prefer to use DB query builder with the join method
https://laravel.com/docs/5.8/queries

Laravel Relationship result can not fetch for same foreign key

My table looks like below,
donation_requests
---------------------------------------------------------------
| id name donation_type_id donation_request_type_id
|--------------------------------------------------------------
| 1 xyz 1 3
| 2 pqr 3 2
| 3 abc 3 1
| 4 klm 4 1
donation_types
------------------------
| id name
-----------------------
| 1 jakat
| 2 sadka
| 3 lillah
| 4 fitra
donation_request_types
------------------------
| id name
-----------------------
| 1 widow
| 2 masjid
| 3 madresha
i want donation_request data with donation_types name and donation_request_types name
In my DonationRequest model code is as below
public function donation_types()
{
return $this->belongsTo('App\DonationType','id','donation_type_id');
}
public function donation_request_types()
{
return $this->belongsTo('App\DonationRequestType','id','donation_request_type_id');
}
but in first two row i get proper result but for third row has same donation_type_id as 3 so it give blank and same as in donation_request_type_id
public function donation_types()
{
return $this->belongsTo('App\DonationType');
}
public function donation_request_types()
{
return $this->belongsTo('App\DonationRequestType');
}
As per my above question relationship is working fine, and it has issue in laravel tinker. While testing in postman i found perfect result, but in tinker there will be some issue. Update tinker but still have same problem.

Eloquent Multitable query

I trying to create a search function in php with Slim and Eloquent 5.1, but i have a problem to get the results from the database.
This are my tables
Listing Table
id | title | description | price | size |etc...
-----|--------|-------------|-------|--------|-------
1 | list1 | some text | 500 | 50 |
2 | list2 | some text | 700 | 80 |
3 | list3 | some text | 350 | 120 |
Listings Option Table
id | id_listing | opt_name | opt_value
-----|-------------|-------------|----------
1 | 1 | rooms | 3
2 | 1 | baths | 4
3 | 2 | rooms | 8
4 | 3 | baths | 1
5 | 3 | rooms | 6
Listings Images Table
id | id_listing | file_name
-----|-------------|-------------
1 | 1 | file_1.png
2 | 1 | file_2.png
1 | 2 | file_3.png
2 | 3 | file_4.png
Now i found a way to get all the results with all they options with
listado = $app->listing->with(['options'],['imgs'])->get();
My classes
//Listing Class
class Listing extends Eloquent{
protected $table = 'listings';
public function options(){
return $this->hasMany('Casas\Listing\ListingOption', 'id_listing', 'id');
}
public function imgs(){
return $this->hasMany('Casas\Listing\ListingImg', 'id_listing');
}
}
// ListingOption class
class ListingOption extends Eloquent{
protected $table = 'listings_options';
public function listings()
{
return $this->belongsTo('Casas\Listing\Listing', 'id_listing');
}
}
// ListingImg Class
class ListingImg extends Eloquent{
protected $table = 'listings_imgs';
public function listings()
{
return $this->belongsTo('Casas\Listing\Listing', 'id_listing');
}
}
but i cannot find a way to filter the query the way i want to. I tried many thing.
Example: I want to get all the listings that have price less than 600 and have more than 2 rooms.
So that be listing id 1 and 3
If anyone can help create this query i'll appreciate that.
What you want want to use is whereHas.
When accessing the records for a model, you may wish to limit your results based on the existence of a relationship
$result = $app->listing->with('options', 'imgs')
->whereHas('options', function ($query) {
$query->where('opt_value', '>', 2)
->where('opt_name', 'room');
})
->where('price', '<', 600)->get();
So what we are doing here is, eager loading options and imgs tables and fetching only the listings that have at least one option where opt_value is bigger than two and opt_name is room.
You can find more in info about querying relationships in here
I would try something like this:
$result = $app->listing->with(
['options' => function ($query) {
$query->where('opt_value', '>', 2);
}
],
['imgs'])->where('price', '<', 600)->get();
The last, outer where should be assigned to listing. The inner where, passed in a callback, should be assigned to options directly.
Take a look at the docs (the "Constraining Eager Loads" section).

Laravel eloquent multiple relationships to find max date less than x days, using eager loading

I'm using Laravel, and I have a simple task of find all rooms that haven't been cleaned in the past x number of days.
I need to use Eloquent and eager loading, and the result should ONLY include results with child records, for example if all the rooms in Building 1 have been cleaned in 'x' days, Building 1 should not be returned at all...
Buildings
+----+---------------+
| id | building_name |
+----+---------------+
| 1 | Building 1 |
| 2 | Building 2 |
+----+---------------+
Rooms
+----+-----------+-------------+
| id | room_name | building_id |
+----+-----------+-------------+
| 1 | Room 1 | 1 |
| 2 | Room 2 | 1 |
| 3 | Room 3 | 2 |
+----+-----------+-------------+
maintenancelog
+----+-------------------+---------+---------------------+
| id | maintenance_value | room_id | created_at |
+----+-------------------+---------+---------------------+
| 1 | Cleaned | 1 | 2015-09-01 00:54:59 |
| 2 | Cleaned | 1 | 2015-09-06 01:55:59 |
| 3 | Cleaned | 2 | 2015-09-02 02:56:59 |
| 4 | Cleaned | 2 | 2015-09-07 03:57:59 |
| 5 | Cleaned | 3 | 2015-09-03 04:58:59 |
| 6 | Cleaned | 3 | 2015-09-08 05:59:59 |
+----+-------------------+---------+---------------------+
Building Model
class Building extends Model
{
public function rooms() {
return $this->hasMany('App\Room');
}
}
Room Model
class Room extends Model
{
public function maintenancelog() {
return $this->hasMany('App\Maintenancelog');
}
public function needCleaning() {
return $this->hasMany('App\Maintenancelog')->whereRaw('id in (select id from (select id, max(created_at) as created_at from maintenancelog
group by id having created_at < DATE_SUB(NOW(), INTERVAL 10 DAY)) x')
}
}
maintenancelog Model
class Room extends Model
{
}
Controller
use App\Room;
$result = Room::has('needCleaning')->with('needCleaning')->get(); //this seems redundant?
While I can get the Room and corresponding maintenancelog records,
the controller code seems redundant (both has() and with()) referencing the same method...
I'm also not quite sure how to start off with Building and then rooms etc so that I have all (and only) the buildings->rooms->maintenancelogs that are relevant, all others are not included in the collection.
The Room model seems a little clunky using whereRaw?? Should this logic be in the maintenancelog model instead? the query is clunky as well
Is there an easier or better way to do what I'm trying to do?
Try this
model
Class Building extends Eloquent
{
public function Rooms()
{
return $this->hasMany('Room');
}
}
Class Room extends Eloquent
{
public function MaintenanceLogs()
{
return $this->hasMany('MaintenanceLog');
}
}
code
//set number of days before
$no_days = 5;
//get the start date where room was not cleaned
$start_date = date('Y-m-d', strtotime('-'.$no_days.' days', strtotime(date('Y-m-d'))));
//start eager loading
$query = Building::with(
array
(
'Rooms' => function($qry)
{
$qry->with('MaintenanceLogs');
}
)
);
//get all rooms that has
$query->whereHas('Rooms', function($qry) use ($start_date)
{
//exclude room that has maintenance log within this period date
$qry->whereDoesntHave('MaintenanceLogs', function($q) use ($start_date)
{
$q->where('created_at', '>=', $start_date);
});
});
$data = $query->get();
it will search for room that has no maintenancelog in 5 days
I am not sure how to do a nested scope though

Categories