simonhamp / laravel-nova-csv-import

The best CSV import component for Laravel Nova
https://novapackages.com/packages/simonhamp/laravel-nova-csv-import
MIT License
168 stars 76 forks source link

Handle relationships better #5

Open simonhamp opened 5 years ago

simonhamp commented 5 years ago

For BelongsTo relationships it would be great to be able to make the relationship where the name matches an existing related resource, even to have the option to create records that don't exist.

At the moment, you have to know the ID of the related resource and update your CSV before you upload it.

richardjkeys commented 5 years ago

@simonhamp This would be really useful!

pepijn-vanvlaanderen commented 5 years ago

Also at the moment the whole import crashes (returns a 404 on the JSON preview link) when using a resource with any BelongsTo relationships.

techguydev commented 3 years ago

@simonhamp thanks a lot for this great package.

I understand that working with relationships is a bit more complex, so far I think that a workaround would be to create a temporary table where to import the data and after it is persistent in the DB we can create a command to handle it as we wish and create models with its relationships.

The best way would be using events, although I've checked and when saving new data to this import table is not firing any saved event, how can it be added?, can it be done through the custom import class you mention in the docs or it would need some extra work?

Thanks

philsturgeon commented 1 year ago

@simonhamp I'm getting a 404 for my Tree resource as many others are, probably becasue it belongs to Site, Species, and Supervisor. The species should be optional, but the other two are required, and as I'm not given any sort of Nova Action-esque way to prompt the user for those fields they cannot be provided.

The functionality you described in this issue would be amazing, because that import CSV is coming from ArcGIS which has no clue what the IDs are.

Can I throw some money your way to get this working? LMK what sort of sponsorship you need.

simonhamp commented 1 year ago

@philsturgeon that would be super awesome

What would be ideal from my POV so I can get cracking on this one with less setup is:

In terms of sponsorship, it's entirely up to you - I'd really appreciate some ongoing support (even a small amount) as this would allow me to continue improving the package 🙏

But if you prefer a one-off just to get this feature out, I will leave it up to you to determine the value. I suspect it will take me a couple of days to polish it off and maybe work through some testing with you

nenads commented 9 months ago

Hi i have some POC.

Idea is that on save dynamically i will get if attribute is relation and if it is i will search it's name and add it. Any comments would be nice before i do PR. Thanks in advanced.

P.S. maybe this is wrong place ?!

class Importer

public function model(array $row): Model
    {
        $model = $this->resource::newModel();

        $relationshipMethods = collect(
            (new ReflectionClass($model))
                ->getMethods(\ReflectionMethod::IS_PUBLIC)
        )
            ->filter(function (\ReflectionMethod $method) {
                // The `?` makes the code work for methods without an explicit return type.
                return is_subclass_of($method->getReturnType()?->getName(), Relation::class);
            })->values();
        foreach ($relationshipMethods as $key => $relationshipMethod) {

            $relation = $relationshipMethod->getName();

            switch ($relationshipMethod->getReturnType()?->getName()) {
                case BelongsTo::class:
                    $tmp = $model->{$relation}()->make()->where('name', $row[$relation])->firstOrFail();
                    $model->{$relation}()->associate($tmp);
                    unset($row[$relation]); //remove from array since we have added real model
                    break;
                default:
                    # code...
                    break;
            }
        }

        $model->fill($row);

        event("eloquent.creating: $this->model_class", $model); //NOTE:: used for outl1ne/nova-sortable

        return $model;
    }