Laravel - Filament Import Action
Hi,
I have a country-state-city relationship, which I defined has many and belongs to both relationships in models and database schema as foreign id. So, the country has many states, the state has many cities.
so what I want is, i create a city CSV in which I mention all country-state city names, now what I want if the country does not exist in DB then create and likewise states and cities, and in the cities table assign the id of states and cities to their respected column,
i created a code like
use League\Csv\Reader;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use App\Models\Country;
use App\Models\State;
// Retrieve the latest file path from the imports table $latestFilePath = DB ::table ( 'imports' ) -> latest () -> value ( 'file_path' );
// Access the file contents using the full path
$fileContents = File ::get ( $latestFilePath );
// Create a CSV reader instance from the file contents
$csv = Reader ::createFromString ( $fileContents );
// Iterate through each city record
foreach ( $csv -> getRecords () as $record ) {
$cityData = array_values ( $record ); // Adjust for your column order
$city = $cityData[ 0 ];
$state = $cityData[ 1 ];
$country = $cityData[ 2 ];
// Find or create the country
$country = Country ::firstOrCreate ( [ 'name' => $country ] );
// Find or create the state
$state = State ::firstOrCreate ( [ 'name' => $state , 'country_id' => $country -> id ] );
// Create the city record
$createdCityNames = City ::create ( [
'name' => $city ,
'state_id' => $state -> id ,
'country_id' => $country -> id ,
] );
}
and i want to use it with filament as import action, looking for serious help if possible, also adding my importer code as well,
use App\Models\City;
use Filament\Actions\Imports\ImportColumn;
use Filament\Actions\Imports\Importer;
use Filament\Actions\Imports\Models\Import;
use Filament\Forms\Components\Checkbox;
use Illuminate\Support\Str;
class CityImporter extends Importer
{
protected static ?string $model = City::class;
public static function getColumns () : array
{
return [
ImportColumn ::make ( 'name' )
-> requiredMapping ()
-> fillRecordUsing ( fn ( City $record , string $state ) => $record -> name = Str ::title ( $state ) )
-> rules ( [ 'required' , 'max:191' ] ) ,
ImportColumn ::make ( 'state' )
-> requiredMapping ()
-> relationship ()
-> rules ( [ 'required' ] ) ,
ImportColumn ::make ( 'country' )
-> requiredMapping ()
-> relationship ()
-> rules ( [ 'required' ] ) ,
];
}
public function resolveRecord () : ?City
{
if ( $this -> options[ 'updateExisting' ] ?? false ) {
return City ::firstOrNew ( [
// Update existing records, matching them by `$this->data['column_name']`
'name' => $this -> data[ 'name' ] ,
] );
}
return new City();
}
public static function getCompletedNotificationBody ( Import $import ) : string
{
$body = 'Your city import has completed and ' . number_format ( $import -> successful_rows ) . ' ' . str ( 'row' ) -> plural ( $import -> successful_rows ) . ' imported.';
if ( $failedRowsCount = $import -> getFailedRowsCount () ) {
$body .= ' ' . number_format ( $failedRowsCount ) . ' ' . str ( 'row' ) -> plural ( $failedRowsCount ) . ' failed to import.';
}
return $body;
}
public static function getOptionsFormComponents () : array
{
return [
Checkbox ::make ( 'updateExisting' )
-> label ( 'Update existing records' ) ,
];
}
}
Please or to participate in this conversation.