Could Some one help me to get figure this out.To start of this is not a duplicate of CRUD and relation between three tables/Models in Laravel.
There are 2 tables Medication_Patient Pivot Table and Med_Time
Medication_Patient Pivot Table
id medication_id patient_id
1 1 (MED X) 1 (Patient X)
2 2 (MED y) 1 (Patient X)
3 2 (MED y) 2 (Patient Y)
And MEdTime which store time and where the medication was given or not
id med_patient_id(foreign key) Day time given
1 1 Yesterday 0900 1
2 1 Today 0900 0
3 1 Today 2000 0
4 2 Today 0600 1
On the Models I have
class Medication extends Model {
protected $guarded = [];
public function patient()
{
return $this->belongsToMany('App\Patient');
} }
class Patient extends Model
{
public function medication()
{
return $this->belongsToMany('App\Medication');
}
}
To get the Medication's assign to a Patient
$assignedMeds = $patient->medication()->get();
but it doesn't give me the ID of Pivot table which I need to find the Time for medication, So I used (PLEASE LET ME KNOW IF THERE IS A BETTER WAY TO DO THIS)
//get the id from medication_patient pivot Table
$medPatient = DB::table('medication_patient')->select('id')
->Where([
['patient_id','=', $patient->id],
['medication_id' ,'=', $medication->id]
])->get()->first;
$medPatientId = $medPatient->id->id;
//Using Medication_patient_id to find MedTime
$assignedMedTimes = MedTime::where('med_patient_id' ,'=' , $medPatientId)->get();
//Filtering the Med Time according to the day
$yesterdayMedTimes = $assignedMedTimes->where('day', '=', 'yesterday')->all();
$todayMedTimes = $assignedMedTimes->where('day', '=', 'today')->all();
$tomorrowMedTimes = $assignedMedTimes->where('day', '=', 'tomorrow')->all();
return view('medicationPatient.medTime', compact('patient','medication'),[
'assignedMedTimes' => $assignedMedTimes,
'yesterdayMedTimes' => $yesterdayMedTimes,
'todayMedTimes' => $todayMedTimes,
'tomorrowMedTimes' => $tomorrowMedTimes,
]);
}
But this only works when I am getting the Time for 1 Medication (Med X time assigned to Patient X), how do I setup a loop or relation in query or eloquent to get me all the medication time (MED X,Y time for Patient X) and pass it into blade.
Sorry of the long post. Would Appreciate if you could show me the Code.
Thank you
You may be making it a little harder on yourself having to go directly to the table in that query. If it were me, I might consider refactoring the database a little bit to make this easier, and to easily take advantage of the Laravel relationships & pivots.
I'm not sure you need to store the data in two separate tables. I would look to normalize as much as possible and collapse this down to a single table. You don't seem to need to reiterate yourself in the Med_Time table -- the med_patient table adds multiple pill's given, so it serves the same purpose as the med_time table (I think). I suggest just a medication_patient table with the pivots:
id medication_id patient_id Day time given
1 1 (MED X) 1 (Patient X) Yesterday 0900 1
2 2 (MED y) 1 (Patient X) Today 0900 0
Your relations will be much the same as you have them, but you can draw the pivots right from the model. This is from the Patient model, but your relations are good for both in your question
public function medication()
{
return $this->belongsToMany('App\Medication')->withPivot('Day', 'time', 'given');
}
Then, when you need to access the data, just pull the pivot. Example:
$patient->pivot->Day... or $patient->pivot->time
Have you tried something like?
public function patient()
{
return $this->belongsToMany('App\Patient')->withPivot(['id']);
}
Related
CONTEXT
I am managing products. This is a shoe store. I would like to offer a view of the other variants.
The database is shaped like this:
For example you can have a leather shoe (id 1), and there is 3 variants of this shoe: a black (id 1), a brown (id 2), and a grey (id 3).
What I try to do is to construct a Laravel relationship to be able, from one variant, to get its siblings. Here is what it looks like in the database according to the example I mentioned.
SHOE
id
====
1
SHOE_VARIANT
id shoeId colorId
===================
1 1 1
2 1 2
3 1 3
...
8 2 5
9 3 2
10 3 4
In this case, if the user is viewing the black variant (id 1), I whish I could show him the 2 others variants (brown, id 2, and grey, id 3).
QUESTION
How can I construct a Laravel relationship in order to retrieve siblings from a parent id, and make sure the current record itself is not included?
EXPERIMENTS
I already tried to construct a relationship like below, but the current record itself is included and I can't figure out how to exclude the record itself because I did not find how to get the current id of the record.
// app/ShoeVariant.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ShoeVariant extends Model {
public function siblings() {
return $this->hasMany("App\ShoeVariant", "shoeId", "shoeId");
}
}
This means:
For the current shoe variant, get the shoe variants that matches knowing that you should match the foreign column named "shoeId" and the local column named "shoeId"
So if 2 shoe variants share the same column "shoeId", this works. Stuck in excluding the current record from these results.
This should do what you want:
public function siblings() {
return $this->hasMany('App\ShoeVariant', 'shoeId', 'shoeId')
->where('id', '!=', $this->id);
}
Just filter out the current variant by id and get all the others.
Alternatively, you can just make a new property:
public function getVariantsAttribute() {
return $this->siblings->reject(function($elem) {
return $elem->id == $this->id;
});
}
And then use it in code like:
$variants = $model->variants; // all except this one
I want to know that how can I get that how many days are left in course duration.
course-duration is just a column and hold an integer in database like 30.
I want to compare course-duration with created_at and return me that left days in laravel.
id username course course-duration(days) created_at
---------------------------------------------------------------------
1 krish SSB 14 2018-11-19
---------------------------------------------------------------------
2 Brij SSB 30 2018-11-18
---------------------------------------------------------------------
3 Sagar SSB 90 2018-11-15
I want to get remaining days of the course after comparing course-duration with created_at.
You can get the remain days like this:
\DB::statement("SELECT (course-duration - DATEDIFF(NOW(), created_at)) remained FROM your_table");
You can use Carbon to get the value of days between created_at and now
$diff_from_now = Carbon::parse($course->created_at)->diffInDays();
$course_duration = $course->duration;
$remaining_days = $course_duration- $diff_from_now;
Try this one
Select sub(course-duration - DATE(created_at)) as left_days from table_name;
Just define a method in your Course model to calculate remaining days of each course:
class Course extends Model
{
public function remainingDays() {
return $this->course-duration - $this->created_at->diffInDays(Carbon::now());
}
}
And to get remaining days of every course:
$course->remainingDays();
Below is my 1:n relational database.
my_left_table
left_id name
1 A
2 B
3 C
my_right_tabe
right_id thing left_id_fk
1 D 1
2 E 1
3 F 2
4 G 3
5 H 3
6 I 3
I would like to have the following result.
my_left_table
left_id name
2 B
Because left_id = 2 has only one related record in the my_right_tabe. How to use the ActiveRecord in Yii framework 2? Using scope is more desirable if possible, otherwise any working solution is also great. Thanks you guys!
You should use groupBy together with having. Try this:
$result = MyLeftTable::find()->joinWith('myRightTable rt')->groupBy('rt.right_id')->having(['count(rt.right_id)' => 1]);
Assuming that your MyLeftTable model has the has-many relationship getMyRightTable.
You can extend your model class for left_table adding a proper get function (eg: getRight)
class Customer extends ActiveRecord
{
// ...
public function getRight()
{
return $this->hasMany(MyRightTableModel::className(), ['left_id_fk' => 'left_id']);
}
}
then when you access to each left model
$leftModel = MyLeftModel::findOne(123);
you have rightModels is an array of rightModels objects
$rightModels = $leftModel->right;
see thi guide for som tips http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#relational-data
I have models/tables as follows:
table room_category
id room_category
1 Classic
2 Deluxe
table room_charges
id room_category room_name room_charges
1 1 c1 600
2 2 d1 800
table ipd_charges
id doctor room_category charges_cash charges_cashless
1 1 1 200 300
2 1 2 300 400
table patient_detail(patient_admission)
id patient_name tpa_name(if not null, equivalent to charges_cashless)
1 1 Null
2 2 1
table daily_ward_entry
id patient_name room_name(id) doctor_name(id) charges ( from ipd_charges)
1 1 1 1 200
2 2 2 1 400
Now there is a dropdown field in daily_ward_entry table for doctor. When I select the drop-down field the charges field needs to be autofilled.
I achieve this using Jason and ajax with the following code without taking into account the room_category. but the charges vary for room_category.(this is only working after saving the record, I prefer if there is someway to pull the charges before save.)
Here is my code in the controller:
public function actionChargesCash($id){
$model = \app\models\IpdCharges::findOne(['doctor'=>$id]);
return \yii\helpers\Json::encode(['visit_charges'=>$model->charges_cash]);
}
public function actionChargesCashLess($id){
$model= \app\models\IpdCharges::findOne(['doctor'=>$id]);
return \yii\helpers\Json::encode(['visit_charges'=>$model->charges_cashless]);
}
I have also tried this variaton:
public function actionChargesCash($id){
$model = \app\models\IpdCharges::find()
->where(['doctor'=>$id])
->andwhere(['room_category'=>'daily_ward_entry.room_name'])->one();
If I replace the 'daily_ward_entry.room_name' with room_name id like 3 or 6, I am getting the result, which means I am not using the correct syntax for referring the column from current table.
How can I include the condition for room_name in the above code?
Thanks in advance for your valuable help.
daily_ward_entry.room_name is meaningless without any relation or join or sub-query. Actually, the query does not know the daily_ward_entry.
Suggestions:
1- Create a relation and use with or Join With
2- Create a query with Join of daily_ward_entry and ipd_charges on room_name=room_category
3- Create a query with a sub-query, to find all|one IpdCharge(s) that have room_category in SELECT room_name FROM daily_ward_entry
All of above suggestions satisfy your requirements.
Another important note:
andWhere()/orWhere() are to apply where to the default condition.
where() is to ignore the default condition
I don't see any default condition (Overridden Find()), So, there is no need to use andWhere, Just:
where(['doctor'=>$id,'room_category'=>3,...])
Would be sufficient.
I am using Laravels Eloquent ORM and i ran into a little problem with a special relationship. Lets assume i have the following table:
Recipe:
id | ... | ingredient1 | ingredient2 | ingredient3 | ingredient4
Every recipe has exactly 4 ingredients and i get the data from an external source in this specific format, thats why i have the ingredients as columns and not as a normal many-to-many relation.
I could set these up as 4 one-to-many relations, but i want to be able to write $ingredient->usedInRecipes()->get().
With 4 one-to-many relations i would have to write $ingredient->usedInRecipesAsIngredient1()->get(), [...], $ingredient->usedInRecipesAsIngredient4()->get() and merge them after afterwards, which would result in 4 queries.
If you know a good way to join these before querying the database or how to make a 4-to-many relation work please answer!
From the question I can't tell if you have already attempted this or not although as I see it you just need to use a single many-to-many relationship.
Each ingredient presumably has a common set of properties that can all be handled in one table ingredients.
id name created_at updated_at
1 Paprika 01/01/1970 00:00:00 01/01/1970 00:00:00
1 Rosemary 01/01/1970 00:00:00 01/01/1970 00:00:00
1 Basil 01/01/1970 00:00:00 01/01/1970 00:00:00
1 Oregano 01/01/1970 00:00:00 01/01/1970 00:00:00
Then your recipes table
id name created_at updated_at
1 Herb Soup 01/01/1970 00:00:00 01/01/1970 00:00:00
To hold the relationships, a pivot table ingredient_recipe
id recipe_id ingredient_id
1 1 1
2 1 2
3 1 3
4 1 4
Now all you require is a belongsToMany relationship on both your Recipe and Ingredient model.
You can code safeguards to make sure one recipe only ever has 4 relationships with ingredient if you wish but to keep it simple:
Recipe::with('ingredients')->get();
Would retrieve all the ingredients along with the recipe.
You can read more about this relationship in the documentation here.
Without Pivots
If you kept the columns ingredient_1, ingredient_2 and so on in the recipes table you could add something like this to your Recipe model.
public function scopeGetWithIngredients($query)
{
$query->leftJoin('ingredients i1', 'recipes.ingredient_1', '=', 'i1.id')
->leftJoin('ingredients i2', 'recipes.ingredient_2', '=', 'i2.id')
->leftJoin('ingredients i3', 'recipes.ingredient_3', '=', 'i3.id')
->leftJoin('ingredients i4', 'recipes.ingredient_4', '=', 'i4.id')
->select('recipes.name', 'i1.name AS ing_1', 'i2.name AS ing_2');
}
You can then just get the ingredients in your model with
Recipe::getWithIngredients();
I found a solution that seems to work in all my use cases.
In the Recipe model i defined the 4 ingredients as One-to-Many relations and made two helper scope functions.
class Recipe extends Eloquent {
public function ingredient1()
{ return $this->belongsTo('Ingredient', 'ingredient1'); }
public function ingredient2()
{ return $this->belongsTo('Ingredient', 'ingredient2'); }
public function ingredient3()
{ return $this->belongsTo('Ingredient', 'ingredient3'); }
public function ingredient4()
{ return $this->belongsTo('Ingredient', 'ingredient4'); }
public function scopeHasIngredient( $query, Ingredient $ingredient ) {
return $query-> where( 'ingredient1', '=', $ingredient->id )
->orWhere( 'ingredient2', '=', $ingredient->id )
->orWhere( 'ingredient3', '=', $ingredient->id )
->orWhere( 'ingredient4', '=', $ingredient->id );
}
public function scopeWithIngredients( $query ) {
return $query->with('ingredient1', 'ingredient2',
'ingredient3', 'ingredient4');
}
}
class Ingredient extends Eloquent {
public function ingredientForRecipes() {
return Recipe::hasIngredient( $this )->withIngredients();
}
}
To get all recipes for an Ingredient i can now call $ingredient->ingredientForRecipes()->get() and use the ingredients without extra queries.