About form data

Question, why does my dd($data)outputs the data I want to insert into my database but when I return($data) it ignores the second array of data I want to insert? I'm iterating into the repeater array so that every repeater data gets distributed on the other form data that I want to save. I'm using
->mutateFormDataUsing(function (array $data) {
$dispensedMedicines = $data['dispensed_medicines'];
unset($data['dispensed_medicines']);
$result = [];
foreach ($dispensedMedicines as $dispensedMedicine) {
$mergedData = array_merge($data, $dispensedMedicine);
$result[] = $mergedData;
}
$data = $result;
return ($data);
->mutateFormDataUsing(function (array $data) {
$dispensedMedicines = $data['dispensed_medicines'];
unset($data['dispensed_medicines']);
$result = [];
foreach ($dispensedMedicines as $dispensedMedicine) {
$mergedData = array_merge($data, $dispensedMedicine);
$result[] = $mergedData;
}
$data = $result;
return ($data);
36 Replies
Resonance
ResonanceOP2y ago
dd($data) which is what I was expecting, multiple value insertion
Resonance
ResonanceOP2y ago
return $data mountedActionData
Resonance
ResonanceOP2y ago
I know I'm doing something wrong or my approach was wrong, IG?. Can some enlighten me? Really appreciate it
cheesegrits
cheesegrits2y ago
It's really unclear what you are trying to do. Are you expecting Filament to write out multiple table rows on your main form table for a single form submission?
Resonance
ResonanceOP2y ago
Yes, that's right Is it not possible in my current logic flow? If it is not, can you recommend or suggest a better approach for it? Appreciate it
cheesegrits
cheesegrits2y ago
Well, Filament just doesn't do that. It creates / edits a single table row for the main form's table. If you use a relationship with the Repeater, it'll write out multiple rows in your related table automatically. But you can't turn the $data state array for the form into an array of state arrays and have it create multiple main table rows. It might help if you explained a bit more about your app and what you are trying to achieve.
Resonance
ResonanceOP2y ago
I was implementing this, my form data looks like on the photo on my other thread. https://discord.com/channels/883083792112300104/1084046030707904533 Using repeater data and disseminate it to other form data, so that I can repeatedly add other row data with the same data on the other form data. Because using create and creat another is somewhat not best for our system usecase
Resonance
ResonanceOP2y ago
My form data look like this
Resonance
ResonanceOP2y ago
And this is what I'm trying to achieve
cheesegrits
cheesegrits2y ago
OK, but what you really need to do is have two tables, like whatever your main table is, I'll make up a name like 'consultations', which has the patient name, the dispensing physician, etc, and a medication_dispensed table, which is a one-to-many relationship on your Consultation model:
public function medicationDispensed(): HasMany
{
return $this->hasMany(MedicationDispensed::class);
}
public function medicationDispensed(): HasMany
{
return $this->hasMany(MedicationDispensed::class);
}
... and on your MedicationDispensed model:
public function consultation(): BelongsTo
{
return $this->belongsTo(Consultation::class);
}
public function consultation(): BelongsTo
{
return $this->belongsTo(Consultation::class);
}
This assumes the normal Laravel conventsion of your medication_dispensed table having a consultation_id foreignId() field. Then on your Repeater, just have a relationship ...
Repeater::make('medications')
->relationship('medicationsDispensed')
->schema([...])
Repeater::make('medications')
->relationship('medicationsDispensed')
->schema([...])
Resonance
ResonanceOP2y ago
I already have the required relationship and it is working on my normal form without the repeater field But I didn't try the ->relationship() method. This is the mountedActionData look likes, which, of course, failed, because its not inserting the repeater field. Because i don't want to convert my column to json array . I tried to iterate the repeater array data to each of the rest of the form field data and just insert value to multiple rows.
Resonance
ResonanceOP2y ago
Resonance
ResonanceOP2y ago
Which is I achieved, but not inserting to the table.
cheesegrits
cheesegrits2y ago
OK, then all you need to do is just make that repeater a relationship to your medication table.
Resonance
ResonanceOP2y ago
I'll try this later, thank you for the help! Much appreciated
cheesegrits
cheesegrits2y ago
So just to be clear, you have two tables and two models, yes? One for the "consultation", and one for the "medications dispensed"?
Resonance
ResonanceOP2y ago
I have 3 tables, one for main inventory, one for pharmacy inventory and one for dispensed medicines. Relationship are hasMany and belongsTo. That form modal is for my dispensed medicine resource, as you can see, it's much easier if i can just submit all of the needed medicine to dispense and assign the name and the user+date as one.
Resonance
ResonanceOP2y ago
Hence, this form format
Resonance
ResonanceOP2y ago
All of it works, I just want to improve it because it is a hassle to always use create and create another Thats why I'm implementing repeater field, just for the medicines to dispense
cheesegrits
cheesegrits2y ago
In which case, if I'm understanding correctly, you need 4 tables. What you are trying to shoe-horn into a single "dispensed medicines" table needs to be two tables.
Resonance
ResonanceOP2y ago
Can you explain it more on why I need another table? And what will be the table use for? Conversation is going lonher and longer and I just want to say to you that I really appreciate the explanation and help that you give
cheesegrits
cheesegrits2y ago
Because the data you are collecting in that "Medicines to Dispense" repeater needs to be a separate table, a one-to-many join to the main table. This is just how relational databases work. And if you do that, and make that Repeater a relationship, Filament will magically handle creating all the rows for you on the child table.
Resonance
ResonanceOP2y ago
I think I'm grasped the idea youre trying to explain . I will try this, thank you! I didn't know that I cannot just use multiple value insertiion on table row in livewire/filament
cheesegrits
cheesegrits2y ago
It's not a Livewire/Filament thing. It's a database thing. When you have data like you have in your picture, with a parent table then multiple instances of related data ... that's two tables with a one-to-many relationship.
Resonance
ResonanceOP2y ago
I will do this, the relationship is oneToMany right? On the new table to dispensed medicine table
cheesegrits
cheesegrits2y ago
Yes - re-read my post up ^^ there with the small code examples.
Resonance
ResonanceOP2y ago
Well, coming from sql, i just use sql insert with multiple value. Yes yes I will, again, thank you!
cheesegrits
cheesegrits2y ago
Again, it's not an "insert" thing, it's how to structure and normalize data in a relational database. The way you have it in your head that you want to structure the data is wrong, you need to rethink it as a parent record (the "consultation") with multiple child rows in a related table ("medications_dispensed"). Once you get that data structure right, suddenly Filament will work like magic.
Resonance
ResonanceOP2y ago
🙏🙏🙏
cheesegrits
cheesegrits2y ago
You'll just add your repeater like I showed above with the added relationship() method, and it'll all just work without you having to do anything special to load the data or save the data. Repeater::make('medications') ->relationship('medicationsDispensed') ->schema([...]) That's it, that's the code (well, with the schema for the child table). No extra coding required. Feel free to DM me if you get stuck building the models / tables or whatever. I know there's a steep learning curve with this stuff.
Resonance
ResonanceOP2y ago
I will and I really appreciate your help!
cheesegrits
cheesegrits2y ago
n/p
Resonance
ResonanceOP2y ago
Last followup question. Since repeater field stores the data as json array. Do i need to cast the model also? And the db column type to json/longtext. Or I just make it as a normal, string/int column type and the relationship will handle the rest?
cheesegrits
cheesegrits2y ago
The repeater only stores data as a json array if you aren't using a relationship, and are instead storing the repeated data in a field on the main table. Once you are using a HasMany relationship to a child table, the data just gets stored as normal table field data. So in your picture, where you have (say) "Generic Name", instead of stroing the repeat data as a JSON array of multiple names in a generic_name field on your main table, you'll have a generic_name on your related table, with one name per row in the table. So your tables will look something like this (I'm making up names, but you get the idea) consultations: id, patient_name, dispensed_by, dispensed_date medications_dispensed: id, consultation_id, medication_id, qty_dispensed (I'm assuming "generic name" is actually a relationship to a medications table, if not then 'medication_id' would be 'generic_name') Then as per a previous answer of mine, on the Consultation model you have a HasMany relation to MedicationsDispensed, and on MedicationsDispensed model you have a BelongsTo to Consultations.
Resonance
ResonanceOP2y ago
My pharmacy model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PharmacyStock extends Model
{
use HasFactory;

protected $fillable = [
'medicine_inventory_id',
'released_stock',
'qty_pcs',
'total_qty',
'total_dispensed_holder',
];

public function MedicineInventory()
{
return $this->belongsTo(MedicineInventory::class);
}

public function DispensedMedicine()
{
return $this->hasMany(DispensedMedicine::class);
}
}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PharmacyStock extends Model
{
use HasFactory;

protected $fillable = [
'medicine_inventory_id',
'released_stock',
'qty_pcs',
'total_qty',
'total_dispensed_holder',
];

public function MedicineInventory()
{
return $this->belongsTo(MedicineInventory::class);
}

public function DispensedMedicine()
{
return $this->hasMany(DispensedMedicine::class);
}
}
My dispensed model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class DispensedMedicine extends Model
{
use HasFactory;

protected $fillable = [
'pharmacy_stocks_id',
'dispensed_qty',
'patient_name',
'dispensed_by',
'dispensed_date',
];

public function PharmacyStock()
{
return $this->belongsTo(PharmacyStock::class, 'pharmacy_stocks_id');
}
}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class DispensedMedicine extends Model
{
use HasFactory;

protected $fillable = [
'pharmacy_stocks_id',
'dispensed_qty',
'patient_name',
'dispensed_by',
'dispensed_date',
];

public function PharmacyStock()
{
return $this->belongsTo(PharmacyStock::class, 'pharmacy_stocks_id');
}
}
My medicine inventory model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class MedicineInventory extends Model
{
use HasFactory;

protected $fillable = [
'batch_no',
'generic_name',
'dosage_form',
'stock',
'released_stock',
'qty_pcs',
'total_pcs',
'expiration_date',
];

public function PharmacyStock()
{
return $this->hasMany(PharmacyStock::class);
}
}
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class MedicineInventory extends Model
{
use HasFactory;

protected $fillable = [
'batch_no',
'generic_name',
'dosage_form',
'stock',
'released_stock',
'qty_pcs',
'total_pcs',
'expiration_date',
];

public function PharmacyStock()
{
return $this->hasMany(PharmacyStock::class);
}
}
I'll add later the other table and model to try out the idea that you gave to me
cheesegrits
cheesegrits2y ago
Basically you would move 'pharmacy_stocks_id' and 'dispensed_qty' to the new table/model, and add a 'dispensed_medicine_id' to the new table. Then make a HasMany from DispensedMedicine to the new table/model, and a BelongsTo from the new model back to DispensedMedicine. It might make sense to rename the models so DispensedMedicine is the new one, and the existing DispensedMedicine becomes something like "DispensedPatient" or "Consultation" or "Order" or some such, but that just depends on what names make sense to you.

Did you find this page helpful?