where('provider', $provider) ->where('provider_id', $providerId) ->first(); } if (!$movie) { $movie = new Movie(); } // Fill scalar fields $movie->fill([ 'provider' => $provider, 'provider_id' => $providerId, 'external_ids' => $details['external_ids'] ?? null, 'title' => $details['title'] ?? '', 'original_title' => $details['original_title'] ?? null, 'description' => $details['description'] ?? null, 'poster_url' => $details['poster_url'] ?? null, 'backdrop_url' => $details['backdrop_url'] ?? null, 'rating' => $details['rating'] ?? null, 'release_date' => $details['release_date'] ?? null, 'year' => $details['year'] ?? null, 'runtime' => $details['runtime'] ?? null, ]); $movie->save(); // Sync relations using names from details payload $this->syncByNames($movie, Genre::class, 'genres', $details['genres'] ?? []); $this->syncByNames($movie, Actor::class, 'actors', $details['actors'] ?? []); $this->syncByNames($movie, Director::class, 'directors', $details['directors'] ?? []); $this->syncByNames($movie, Studio::class, 'studios', $details['studios'] ?? []); $this->syncByNames($movie, Country::class, 'countries', $details['countries'] ?? []); $this->syncByNames($movie, Language::class, 'languages', $details['languages'] ?? []); return $movie->refresh(); }); } /** * @param Movie $movie * @param class-string $modelClass * @param string $relation * @param array $names Names to sync */ protected function syncByNames(Movie $movie, string $modelClass, string $relation, array $names): void { // Create or fetch IDs by name (case-insensitive normalization) $ids = collect($names) ->filter() ->map(function ($name) use ($modelClass) { $original = (string) $name; $normalized = $this->normalizeName($original); if ($normalized === '') return null; // Find existing row in a case-insensitive way /** @var \Illuminate\Database\Eloquent\Model|null $existing */ $existing = $modelClass::query() ->whereRaw('lower(name) = ?', [mb_strtolower($normalized)]) ->first(); if ($existing) { return $existing->getKey(); } /** @var \Illuminate\Database\Eloquent\Model $model */ $model = new $modelClass(); $model->setAttribute('name', $normalized); $model->save(); return $model->getKey(); }) ->filter() ->values() ->all(); // Sync relation if method exists if (method_exists($movie, $relation)) { $movie->{$relation}()->sync($ids); } } /** * Normalize a person/genre/studio/etc name for de-duplication. */ protected function normalizeName(string $name): string { // Trim, collapse internal whitespace to single spaces $name = trim(preg_replace('/\s+/u', ' ', $name) ?? ''); // Leave original casing (provider’s) but comparisons will be lowercase. return $name; } }