How to join tables in laravel 5.4 - laravel

In my case, I have 3 tables like Question, options, and answers
Questions table
|id | question_name|
------------------------------
1 question1
2 question2
3 question3
options table
id | question_id | options |
----------------------------------------
1 1 option1
----------------------------------------
1 1 option2
----------------------------------------
1 1 option3
----------------------------------------
1 1 option4
Answers table
id | customer_id | question_id | answer(selected by user) |
--------------------------------------------------------------------
1 1 1 option1
--------------------------------------------------------------------
1 2 2 option2
--------------------------------------------------------------------
1 1 3 option3
--------------------------------------------------------------------
1 1 3 option2
How can I get below output from answers using joins table
For customer 1
question1
--option1
question2
--option2
question3
--option3
--option2
I have eloquent relation,
Question model
class Question extends Model
{
public function options()
{
return $this->hasMany(Option::class);
}
public function customer()
{
return $this->belongsTo(CustomerProfile::class);
}
public function answers()
{
return $this->hasMany(Answer::class);
}
}
Option model
public function question()
{
return $this->belongsTo(Question::class);
}
Answer model
public function customer()
{
return $this->belongsTo(CustomerProfile::class);
}
public function question()
{
return $this->belongsTo(Question::class);
}
That is how my relationships looks like, Now I just need to join the tables to get output.

In order to get the related options for your questions, you can use eager loading.
An example would be:
$questions = Question::with('options')->get();
You will then have a collection with the questions, and their related options. You will need to construct a loop to get the data you want.

Going off the comment you left on Aaron Fahey's answer, you'll need to add a constraint to the query and the eager-load:
$customerId = 1;
$questions = Question::with([
'options', 'answers' => function ($query) use ($customerId) {
$query->where('customer_id', $customerId);
}])
->whereHas('answers', function ($query) use ($customerId) {
$query->where('customer_id', $customerId);
})
->get();
https://laravel.com/docs/5.4/eloquent-relationships#constraining-eager-loads
https://laravel.com/docs/5.4/eloquent-relationships#querying-relationship-existence
Hope this helps!

I guess, you also have defined eloquent relations in Customer Model class.
If you do so, then you can retrieve all the answers of a particular customer through customer model and this will give you the hook to get the answer's question and its all options:
$customer = Customer::find($customerId);
$answer = $customer->answers()->where('id', $answerId)->get();
$question = $answer->question;
$questionOptions = $question->options;
I hope it will help.

Related

Laravel createMany on createMany while preserving relation

I have the same issue as this question asked. However, I would like to insert the data on the nested createMany with it's relation, and not insert multiple entries like:
id question_id answer
1 1 Good
2 1 Meh
3 2 Good
4 2 Meh
So if the question_id is 1 and the answer on that question is Good and for question_id 2, the answer on that question is Meh so that result should be:
id question_id answer
1 1 Good
2 2 Meh
Basically what I have is:
A User hasMany orders
An Order hasMany sub orders
A SubOrder hasMany sub order products
Here are the relations:
User Model:
class User extends Model
{
public function orders() {
return $this->hasMany(Order::class);
}
}
Order Model:
class Order extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
public function subOrders() {
return $this->hasMany(SubOrder::class);
}
}
SubOrder Model:
class SubOrder extends Model
{
public function order() {
return $this->belongsTo(Order::class);
}
public function subOrderProducts() {
return $this->hasMany(SubOrderProducts::class);
}
}
SubOrderProducts Model:
class SubOrderProducts extends Model
{
public function subOrder() {
return $this->belongsTo(SubOrder::class);
}
}
Here are the tables:
orders table:
id name
sub_orders table:
id order_id date price
sub_order_products table:
id sub_orders_id product_id
Then on the store method:
$order = auth()->user()->orders()->create($request->validated());
$order_subs = $order->subOrders()->createMany($request->orders);
foreach ($order_subs as $order_sub) {
$order_sub->subOrderProducts()->createMany($request->orders);
}
The $request->orders data is:
{
"name": "My Order",
"orders": [
{
"date": "2022-05-17",
"product_id": [1],
"price": 1
},
{
"start_date": "2022-05-18",
"product_id": [2],
"price": 2
}
]
}
This means that the order has two sub orders, with their corresponding products. I end up getting:
orders table:
id name
1 Super Order
sub_orders table:
id order_id date price
1 1 2022-05-17 1
2 1 2022-05-18 2
sub_order_products table:
id sub_orders_id product_id
1 1 1
2 1 2
3 2 1
4 2 2
My desired output would be to preserve the relation on the sub_order_products table, save and match the correct IDs. That would be:
sub_order_products table:
id sub_orders_id product_id
1 1 1
2 2 2
I'm thinking to change request->orders data and have some IDs for the sub_orders_id or maybe nest the createMany methods but I can't figure out how to. How to achieve this? Thanks!

Get Data through relation in laravel

I'm using this query to get data using relation
return Product::with('attributes')
->whereHas('attributes', function ($query) use ($attribute_id,$attribute_value){
$query->whereIn('attribute_id', $attribute_id);
$query->whereIn('value', $attribute_value);
})
->paginate(10);
$attribute_id and $attribute_value are arrays, i'm getting data using this relation but when $attribute_id and $attribute_value are empty then i'm not getting any result but it should return result through product table if there are no attributes.
I have changed it to something like this:
if(!empty($attribute_id))
{
$query->whereIn('attribute_id', $attribute_id);
}
if(!empty($attribute_value))
{
$query->whereIn('value', $attribute_value);
}
model relation :
public function attributes()
{
return $this->hasMany(ProductsAttribute::class, 'product_id ');
}
Table:
id | Title | Price
1 Title 1 5000
2 Product 2 7000
this is related to product_attribute table
id | product_id | attribute_id | attribute_name | value
1 1 5 Color Red
2 1 6 Size XL
3 2 5 Color Green
Is there any other way to make a check in query so that if attributes are not provided then atleast product data should return.
A cleaner way might be to use local scopes. That way, your controllers will look cleaner. It also makes the code easily testable. Here is how I might approach this.
NOTE: Code hasn't been tesed.
In your controller:
return Product::with([
'attributes' => function ($query) use ($attribute_id, $attribute_value) {
return $query->inAttributeId($attribute_id)
->inAttributeValue($attribute_value);
}
])->paginate(10);
In your ProductsAttribute model:
public function scopeInAttributeId($query, $attributeId)
{
if (empty($attributeId)) {
return $query;
}
return $query->whereIn('attribute_id', $attributeId);
}
public function scopeInAttributeValue($query, $attributeValue)
{
if (empty($attributeValue)) {
return $query;
}
return $query->whereIn('value', $attributeValue);
}
As you can see, the scopes modify the query only if there are values in the passed in array. If the passed in array is empty, it returns the original query.

Display data in view from database Laravel

So i have two tables:
orders
id | time | meals_id | vege
1 | 12:00 | 1 | 0
ingredients
id | value | meals_id
1 | cheese| 1
2 | beef | 1
where ingredients id is type of ingredients like meat.
I'd like to display data in my order view, but I have no idea how show value of ingredients.
This is my order model
public function ingredients(){
return $this->hasMany(ingredient::class);
}
ingredient model
public function order(){
return $this->hasMany(order::class);
}
and orderController
public function show(){
$orders = order::where('vege', 0)->get();
return view('home', ['orders' => $orders]);
}
Thanks for any advice.
in order model make a relation with ingredients
public function ingredients()
{
return $this->hasMany('App\Order', 'order_id' ,'id');
}
you must have a field in ingredients order_id
then you can get order with ingredients
$orders = Orders::with('ingredients')->where('vege',0)->get();
return view('home',compact('orders'));
in home view you can easily
foreach($orders as $order){
foreach($order->ingredients as $i){
echo $i->id;
}
}
orderController
public function show(){
$orders = order::where('vege', 0)->get();
return view("home",compact('orders'));
}
home view
foreach($orders as $order){
foreach($order->ingredients as $i){
echo {{ $i->id }};
}
}

How to query a table based on criteria of another table in Laravel?

In my laravel project I have an inventory and a medicine table which the formats are as the following:
Inventory Table
id | medicine_id | expiry_date
-------|-----------------|-------------
1 | 1 | 13-11-2021
2 | 2 | 01-01-2020
3 | 2 | 23-05-2024
Medicine Table
id | name | category
-------|-----------------|-------------
1 | Hemophine | Syringe
2 | andrenalin | Tablet
3 | aspirin | Capsule
The models are set as below:
Inventory Model
class Inventory extends Model
{
public $incrementing = false;
public function medicine(){
return $this->belongsTo('App\Medicine', 'medicine_id');
}
}
Medicine Model
class Medicine extends Model
{
public $incrementing = false;
public function inventory(){
return $this->hasMany('App\Inventory', 'medicine_id');
}
}
For retrieving all the inventories with a specific category such as Syringe, I tried eager loading, but couldn't figure out the flaws. Here is what I did to get all the inventories with a Syringe category, but it didn't work.
public function index()
{
$medicines = Inventory::where('medicine_id'->category, "Syringe")->get();
foreach($medicines as $medicine){
echo $medicine->medicine->name ." ".$medicine->expiry_date;
echo "<br>";
}
}
Now, Is there anyway to get all the inventory items based on their categories they are in? in this case in "Syringe" category?
Your syntax is a bit wrong, in order to load the medicine for each inventory you need to use with and the where function is where('column', value)
So change it to this:
$medicines = Inventory::with([
'medicine' => function($query) {
$query->where('category', "Syringe");
}
])->get();
or even better the other way around:
$medicines = Medicine::with('inventory')->where('category', 'Syringe')->get();

Relation between 2 tables with a link table

I have this tables :
topics
-------
id | title
------+----------
1 | Sport
2 | Social
posts_topics
------------
id | post_id | topic_id
------+--------------+------------
1 | 1 | 1
2 | 1 | 2
posts
------
id | title
-----+----------
1 | A Test Post
I store topics in topics table and use posts_topics to link between my posts table and topics
now I want select title of topics when selecting posts,
After some searching in StackOverflow and Google, I've written this models:
Posts.php
public function post_topics()
{
return $this->hasMany('App\PostTopics');
}
PostTopics.php
public function topics()
{
return $this->hasManyThrough('App\Posts', 'App\Topics', 'id', 'topic_id');
}
Topics.php
protected $table = 'topics';
and in my controller I trying to fetch:
$post = Posts::with('post_topics')->find($post_id);
dd($post);
Now this code will work but cannot return title of topics.
Change the code to a Many to Many relationship in Posts.php:
public function post_topics()
{
return $this->belongsToMany('App\Topics', 'posts_topics', 'post_id', 'topic_id');
}
And then call it:
$post = Posts::with('post_topics')->find($post_id);
Try this and check if it works for you.

Resources