#import from csv into multiple related tables

20 messages · Page 1 of 1 (latest)

fossil cedar
#

Hi folks,

Sorry for asking but I'm really struggling to find any definitive documentation on how to implement this and I'm not even certain that's even possible at least with the ImportAction from Filament.

I have a csv with data we've broken down to be distributed into 6 different tables. I understand the relationship model in the Import action is still in its infancy and only supports belongs_to relationships. However I figured even with that there's no reason I couldn't manage to make my objectives work. So what I'm trying to do is this:

  • create records for tables if they don't already exist and retrieve the id of the record to be recorded as a foreign key
  • have the import be one single function, not 6 different import actions.

I tried stacking ->importer(MyclassImporter::class) in the Resource I want the imort button to be in but if I do that it ignores every importer except for the last one (yet doesn't return an error)

Right now I'm trying to define everything under one MyclassImporter.php file and see if I can make relationships work but I'm not having much luck. I tried using dot notation in ImportColumn::make() but although this doesn't throw an error on screen, it doesn't seem to work either. I was trying to see if perhaps the ->resolveRelatedRecord() method for the ImportColumn class would work but I can find no documentation at all on how to use that. The Filament docs have nothing at all on this method.

It seems odd to me that there is so little documentation on how to import into multiple tables. Perhaps my search skills have failed me but I would appreciate any guidance you could provide, even if that's just pointing me towards other ways to do this that don't involve Filament. I hope this all makes sense.

Cheers

vital agateBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

jade juniper
fossil cedar
#

Yes but I have no idea what else to do beyond that. It's really unclear how to do what I need when you don't refer to a record which already exists

fossil cedar
#

Bumping this in case people don't look at this forum on weekends. It would be a great help to find a solution to this today. Thanks

jade juniper
#

If you set the relationship, then the column can resolve etc as per the documents on that? So you could resolve the Author column by email or username within the database.

We would need more details of what you are trying to achieve for anything else, with say the data you are trying to import.

fossil cedar
#

I'm not using authors but why not it works as an example. I can't give you the exact data I'm working with as it's confidential but for the sake of moving forward say I have a CSV of books and authors.

Both the author and book tables are empty to start with. I want for each line it reads to search if an author already exists and add one if not, then retrieve the author id from there to add it to the book table as a foreign key.

That's a 2-table example but of course I'll need to expand that to my 6 tables. Does that make sense?

jade juniper
# fossil cedar I'm not using authors but why not it works as an example. I can't give you the e...

We know your not using Author but the Author is an example of the context.

So as per the doc's adjust:

->relationship(resolveUsing: function (string $state): ?Author {
        return Author::query()
            ->where('email', $state)
            ->orWhere('username', $state)
            ->first();
    })

to:

->relationship(resolveUsing: function (string $state): ?Author {
        return Author::query()
            ->where('email', $state)
            ->orWhere('username', $state)
            ->firstOrCreate([
                'email' => $state,
                'username' => $state,
            ]);
    })

This would in Author context find and return it to be mapped as the relationship, else create it then map it.

fossil cedar
#

Right thanks I didn't know you could append firstOrCreate() in that way. I'll try it and get back to you

fossil cedar
#

Ok so the upload form always wants to map author to one of the columns of the csv which means $state always has the same value. How do I make sure this $state contains multiple columns which can then be mapped to a single table columns?

jade juniper
#

Seperate the values in the column with say: ; and explode state in the find record to get the multiple values?

fossil cedar
#

But the docs say you can pass multiple columns to resolveUsing. It's just unclear whether this also works when passing a function

jade juniper
#

That's not what it's saying, it's saying Database Columns. So 'author' column in the CSV can be used to look in email and username columns within the database.

fossil cedar
#

Yeah that's not very clear then. So there's no way to pull more than one column in one statement then, not without modifying the structure of the imported file

jade juniper
fossil cedar
#

Any tips on how I can retrieve either of those? Everything I try seems to end up in the wrong scope :/

jade juniper
fossil cedar
#

Thanks I appreciate that

jade juniper
#

@fossil cedar can you pass in $data? and try this to see if $data is populated.

use Illuminate\Support\Facades\Log;

->relationship(resolveUsing: function (string $state, $data): ?Author {
    Log::info('Data:', ['data' => $data]);

    return Author::query()
        ->where('email', $state)
        ->orWhere('username', $state)
        ->firstOrCreate([
            'email' => $state,
            'username' => $state,
        ]);
})

Then check the laravel log?

fossil cedar
#

This worked a treat thank you. I still have some cleaning up to do on my data but now I have something I can use to move forward. Very grateful for your help