---
title: "Importéry — Imports for Laravel | Roundly"
description: "Jedna trieda na typ záznamu rozširujúca Importer — metódy a predvolené hodnoty, prirodzené kľúče, callbacky create a update, rollback a registrácia."
url: https://roundly-consulting.com/sk/open-source/navody/imports-for-laravel/importery
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Imports for Laravel](https://roundly-consulting.com/sk/open-source/navody/imports-for-laravel.md)

# Importéry

Importér opisuje jeden typ záznamu: jeho model, polia, ako záznamy patria vlastníkovi, kto ich smie importovať, ako sa z riadka stane záznam a ako sa rozpozná existujúci. Rozšírte RoundlyConsulting\\Imports\\Importer a triedu zaregistrujte:

```php
// config/imports.php
'importers' => [
    App\Imports\AssetsImporter::class,
    App\Imports\DocumentsImporter::class,
],

// or at runtime, e.g. in a service provider's boot()
use RoundlyConsulting\Imports\Facades\Imports;

Imports::register(AssetsImporter::class);
```

Importéry sa vytvárajú cez kontajner — injektovanie do konštruktora funguje — a overia sa raz za proces, lenivo, pri prvom použití.

## Metódy a predvolené hodnoty

| Metóda | Povinná | Predvolené | Poznámky |
| --- | --- | --- | --- |
| `model(): class-string<Model>` | áno | — | Musí byť na spojení tabuliek balíka — jedna transakcia. |
| `fields(): list<Field>` | áno | — | Aspoň jedno; názvy unikátne, ^\[a-z\]\[a-z0-9\_\]\*$. |
| `ownership(): Ownership` | áno | — | Bezpečné odmietnutie — pozrite Vlastníci a oprávnenia. |
| `authorize(?Authenticatable, Model $owner, ImportOperation): bool` | áno | — | Pýta sa na View, Upload, Commit a Rollback. |
| `create(ImportRow, ImportContext): Model` | áno | — | Vráťte uložený model v rámci vlastníka. Vrátiť existujúci záznam je v poriadku — v evidencii je ako linked a nikdy sa nevracia. |
| `update(Model, ImportRow, ImportContext): Model` | pre Update | vyhodí výnimku | Jej prepísanie zapne režim Update. |
| `key(): string` | nie | názov triedy bez Importer v snake case (AssetsImporter → assets, TeamMembersImporter → team\_members) | ^\[a-z\]\[a-z0-9\_.-\]{0,63}$, unikátny. V produkcii ho uveďte — kľúčujú sa ním uložené mapovania aj vyhľadávanie cez HasImportSource. |
| `label(): string\|array` | nie | kľúč ako nadpis (Team Members) | Prekladový kľúč, text alebo \['en' => …, 'sk' => …\]. |
| `naturalKey(): ?NaturalKey` | nie | null | Bez kľúča nie je detekcia duplicít. |
| `modes(): list<DuplicateMode>` | nie | Skip, Update (ak je prepísané update()), CreateNew | — |
| `defaultMode(): DuplicateMode` | nie | Skip | Musí byť jedným z modes(). |
| `rollback(Model, ImportContext): RollbackOutcome` | nie | zmaže → Deleted | Vráťte Handled (vrátené inak) alebo Kept. |
| `changeDetection(): ChangeDetection` | nie | ChangeDetection::checksum() | Alebo ::updatedAt(), prípadne ::checksum(\['name', …\]). |
| `checksumAttributes(Model): array` | nie | surové atribúty bez kľúča, časových pečiatok a deleted\_at | Čo pokrýva kontrolný súčet. |
| `diff(Model, ImportRow): list<FieldChange>` | nie | namapované, neprázdne polia (okrem odkazov) oproti rovnomenným atribútom | Náhľad aktualizácií — prázdna bunka nie je zmena. |
| `formats(): list<SourceFormat>` | nie | CSV, XLSX | — |
| `limits(): Limits` | nie | z konfigurácie | Limits::fromConfig()->withRows(50\_000)->withColumns(200)->withFileSize(20\_480)->withCellLength(255) — riadky najviac 100 000, stĺpce 16 384, dĺžka bunky orezaná na 1 … 1 048 576 a kontrolovaná pre každú bunku (too\_long). |

Finálni pomocníci na každom importéri: kind() (ImportKind::Rows), supportsUpdate() (či je prepísané update()), field(string $name) a labelIn(?string $locale).

```php
use RoundlyConsulting\Imports\Definition\{ChangeDetection, Limits};
use RoundlyConsulting\Imports\Enums\{DuplicateMode, SourceFormat};

public function key(): string { return 'assets'; }          // declare it in production
public function label(): string|array { return ['en' => 'Assets', 'sk' => 'Majetok']; }

public function modes(): array { return [DuplicateMode::Skip, DuplicateMode::Update]; }
public function defaultMode(): DuplicateMode { return DuplicateMode::Update; }
public function formats(): array { return [SourceFormat::Xlsx]; }

public function limits(): Limits
{
    return Limits::fromConfig()->withRows(50_000)->withColumns(200)->withFileSize(20_480)->withCellLength(255);
}

public function changeDetection(): ChangeDetection
{
    return ChangeDetection::checksum(['name', 'serial_number']);   // or ChangeDetection::updatedAt()
}
```

V produkčných importéroch uveďte key(). Kľúčujú sa ním uložené mapovania aj vyhľadávanie cez HasImportSource, takže pri predvolenej hodnote premenovanie triedy premenuje aj kľúč a tie sa stratia. Názov triedy, z ktorého nevznikne platný kľúč — anonymná trieda, trieda s názvom len Importer — sa odmietne s uvedením triedy.

## Prirodzené kľúče

```php
use RoundlyConsulting\Imports\Definition\NaturalKey;

public function naturalKey(): ?NaturalKey
{
    return NaturalKey::by('asset_tag')->then('serial_number');   // candidates, tried in order
}

NaturalKey::by('first_name', 'last_name')->caseInsensitive();    // one candidate, several fields
```

- Najprv prebehne overenie: neplatný riadok sa nikdy nespáruje ani sa neráta ako duplicita.
- Zhodou riadka je prvý vyplnený kandidát, ktorý nájde záznam. Neskorší kandidát, ktorý nájde iný záznam, je conflicting\_match; dva záznamy pre jeden kľúč sú ambiguous\_match.
- Riadok, ktorý opakuje kľúč skoršieho platného riadka alebo sa spáruje s rovnakým záznamom, je duplicate\_in\_file.
- Kľúče sa porovnávajú aj so soft-deleted záznamami. Živý záznam má vždy prednosť, no kľúč, ktorý má len soft-deleted záznam, urobí riadok neplatným (matches\_deleted\_record, v každom režime) — váš unikátny index tento záznam stále pokrýva, takže vytvorenie by pri importe zlyhalo.

## Callbacky create a update

```php
public function create(ImportRow $row, ImportContext $context): Model
{
    return Asset::create([...$row->attributes(), ...$context->ownerAttributes()]);
}

public function update(Model $asset, ImportRow $row, ImportContext $context): Model
{
    return tap($asset)->update($row->changes());
}
```

ImportRow ponúka dve mapy pripravené na zápis. attributes() obsahuje všetky hodnoty, pričom každé pole s odkazom sa zmení na svoj stĺpec storeAs() s kľúčom odkazovaného záznamu (\['asset\_tag' => 'AST-1', 'vendor\_id' => 5\]) — použite ju v create(). changes() je attributes() obmedzené na namapované polia s neprázdnou bunkou — použite ju v update().

Prázdne bunky v režime Update ponechajú uloženú hodnotu: exporty z iných nástrojov bežne nechávajú stĺpce prázdne a aktualizácie sa pri vrátení importu nikdy nevracajú. update(), ktoré zapisuje $row->changes(), sa týmto pravidlom riadi a predvolené diff() pri prázdnej bunke neukáže zmenu. Ak chcete hodnoty zámerne mazať, zapisujte v update() $row->attributes() a diff() prepíšte rovnako.

## Čo dostanú callbacky

```php
use RoundlyConsulting\Imports\Exceptions\ImportRowException;

public function create(ImportRow $row, ImportContext $context): Model
{
    $row->number();                    // the spreadsheet row number
    $row->get('name');                 // the coerced value
    $row->has('purchased_on');         // the field is mapped
    $row->filledIn('serial_number');   // mapped and not blank
    $row->reference('vendor');         // the resolved Vendor model, or null
    $row->raw('name');                 // the cell as text
    $row->cell('name');                // the Cell (type, value)
    $row->all(); $row->filled(); $row->only('name'); $row->except('vendor');
    $row->attributes();                // ['asset_tag' => 'AST-1', …, 'vendor_id' => 5]
    $row->changes();                   // attributes() of mapped, non-blank cells only

    $context->owner; $context->actor; $context->mode; $context->locale; $context->timezone;
    $context->sessionId; $context->batchId;
    $context->query(Vendor::class);    // a query constrained to the owner
    $context->ownerAttributes();       // ['team_id' => 7] for Ownership::column('team_id')

    if ($row->get('status') === 'retired') {
        throw ImportRowException::because(__('app.imports.retired'));   // fails this row only
    }

    return Asset::create([...$row->attributes(), ...$context->ownerAttributes()]);
}
```

ImportContext sprístupňuje owner, actor, importer, sessionId, batchId, mode, locale a timezone (časové pásmo relácie — v ňom sa čítali časy zo súboru) ako verejné vlastnosti, k tomu query(string $model, ?Ownership $rule = null) — dopyt obmedzený na vlastníka pravidlom importéra alebo tým, ktoré odovzdáte — a ownerAttributes(). Výnimkou ImportRowException::because('…') necháte zlyhať jeden riadok s vlastnou preloženou správou.

## Háčik rollback

Vrátenie importu zmaže vytvorené záznamy, ak sa odvtedy nezmenili. Ak chcete záznam vrátiť inak, prepíšte rollback():

```php
use RoundlyConsulting\Imports\Enums\RollbackOutcome;

public function rollback(Model $record, ImportContext $context): RollbackOutcome
{
    if ($record->accepted_at !== null) {
        return RollbackOutcome::Kept;      // leave it alone
    }

    $record->revoke();                     // undone another way

    return RollbackOutcome::Handled;       // the default deletes it: RollbackOutcome::Deleted
}
```

## Pravidlá registrácie

Registrácia odmietne výnimkou InvalidImporterDefinitionException s názvom importéra a pravidla:

- chybný kľúč, dva importéry s rovnakým kľúčom, chýbajúce ownership, model na inom spojení;
- žiadne polia, chybné alebo duplicitné názvy polí, choice bez options, reference bez to() alebo by();
- polia prirodzeného kľúča, ktoré chýbajú alebo sú odkazmi;
- režim Update bez update(), predvolený režim mimo modes(), žiadne formáty;
- storeAs() na poli, ktoré nie je odkazom, alebo stĺpec storeAs(), ktorý nie je názvom stĺpca či je názvom iného poľa;
- pravidlá prítomnosti v databáze — reťazce exists: / unique:, Rule::exists() / Rule::unique() — pretože obchádzajú scope vlastníka a mohli by prezradiť dáta iného vlastníka. Namiesto nich použite Field::reference() a naturalKey().

Odkaz, ktorý zdedí pravidlo, aké jeho model nemôže niesť (team\_id na modeli bez neho), vyhodí UnscopedQueryException — na poli uveďte ->ownedBy().

## Zisťovanie pre UI

```php
Imports::importers()->available($user, $team);     // list<ImporterDescriptor> the user may view
Imports::importers()->describe('assets', 'sk');    // fields: label, type, required, options, example, help, aliases, format
Imports::importers()->all(); Imports::importers()->has('assets'); Imports::importers()->find('assets');
Imports::importer('assets')->modes();
Imports::importer('assets')->descriptor('sk');
```

available() vráti len importéry, ktorých authorize() povolí View. Register vypíše:

```bash
php artisan imports:importers   # key, label, kind, fields, modes, formats
```

## Octane a dlho bežiace workery

Inštancie importérov sú v registri singletony kontajnera počas celej životnosti procesu — queue workera aj Octane workera. Do konštruktora importéra neinjektujte nič, čo patrí k požiadavke (aktuálneho používateľa, request, nájomcu): prenieslo by sa to do ďalšej požiadavky alebo úlohy. Všetko, čo sa týka importu, prichádza cez ImportContext a ImportRow.

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/imports-for-laravel.md)
