Termék importálás Magento webshopba a Magmi rendszerrel

Tartalom

    • Mi is az a Magmi?
    • A Magmi és a Magento 2.0
    • A Magmi telepítése
    • A Magmi alapbeállítása
    • Magmi plugin-jainak a beállítása
  • Egyszerű termék importálása
  • Hogyan kell csoportos árat (Group Price) importálni?
  • Hogyan kell mennyiség kedvezmény árat (tier prices) beállítani?
  • Hogyan tudom a termékeket hozzárendelni a több website-os áruházban?
  • Hogyan kell importálni?
  • Konfigurálható termék importálása
  • Kötegelt termék importálása
  • Csoportos termék importálása
  • Letölthető termék importálása
  • Virtuális termék importálása
  • Jellemző és jellemzőhalmaz importálása
  • Termékkategóriák importálása
  • Többnyelvű importálás

Mi is az a Magmi?

A Magento egy erőteljes, a legtöbb e-kereskedelemmel kapcsolatos feladat ellátására alkalmas platform. Alapértelmezett kezelőfelülete azonban hagy némi kívánnivalót maga után. A Magmi, azaz a Magento Mass Importer feladata, hogy segítsen ezeknek a réseknek a kitöltésében, és könnyebbé tegye a Magento rendszeren üzemeltetett webáruházunk működtetését.

Gyakran merül fel az igény például arra, hogy egyszerre több száz, vagy akár több ezer termékből álló online katalógus hozzunk létre és kezeljünk, a lehető legegyszerűbb és leghatékonyabb módon. Ennek kivitelezése a Magento kezelőfelületén keresztül, manuális módon egyáltalán nem egyszerű feladat.

A Magmi egy olyan, nyílt forráskódú rendszer, melynek segítségével egy sor olyan import/export opcióhoz férhetünk hozzá, amelyek alapból nem találhatóak meg a Magento rendszerében, ám rendkívül megkönnyíthetik az ilyen, és ehhez hasonló munka elvégzését. Lényegében egy külső felhasználói felület, mely segítségével könnyedén importálhatunk termékeket (akár nagy számban is) egyszerű CSV-fájlokból a Magento alapú webáruházunkba.

Sajnos az adatbázist valamilyen módon mindenképpen nekünk kell kialakítanunk, ami azt jelenti, hogy az ehhez használt .csv kiterjesztésű fájlokat továbbra is nekünk kell létrehoznunk. Ezek a fájlok azonban az MS Excel vagy a LibreOffice Calc segítségével is könnyen szerkeszthetők, a Magmi segítségével pedig gyorsabbá és egyszerűbbé tehetjük az adatbázis feltöltésének feladatát. Legnagyobb erőssége, hogy olyan dolgokat is megtehetünk a segítségével, mint például a képek tömeges importálása, vagy éppen a kategóriák automatikus létrehozása termékeink importáláskor.

A Magmi használatának hátránya mindössze annyi, hogy a már megszokott magento kezelőfelület mellett egy újabb adminisztrációs interfész használatát meg kell tanulnunk, a tapasztalatok szerint azonban ez egyáltalán nem teljesíthetetlen feladat. Az applikáció bőséges dokumentációja ugyanis lépésről lépésre vezet minket végig minden fontos funkción, a fejlesztők pedig még saját Wikit is létrehoztak annak érdekében, hogy segítség a Magmi használata mellett döntő felhasználókat..

A Magmi és a Magento 2.0

Mint azt már nyilván sokan tudják, a Magento 1.x verzióinak hivatalos támogatása 2020 júniusában véget ér. Ez azt jelenti, hogy a keretrendszer 2.0-nál korábbi verziói ettől az időponttól kezdve sem szoftveres, sem pedig biztonsági támogatásban nem részesülnek hivatalosan, így használatuk veszélyessé válik.

A legtöbb e-kereskedő éppen ezért árhatóan a Magento 2.x verzióira vált majd, ezzel a váltással pedig óhatatlanul felmerül a kérdés: mi a helyzet a Magmi-val, ami a Magento 1.x verziói esetében olyan jó szolgálatot tett, ha a webruházba történő importálás és expotálás feladatáról volt szó?

Nos, van egy jó hírünk! A Magmi természetesen a Magento 2.0 verziójához is elérhető, habár bizonyos funkciói egyelőre kevésbé működnek hatékonyan, mint a rendszer korábbi változatai esetében. A Magento 1.x támogatásának megszűnésével azonban várható, hogy a fejlesztők belevetik magukat a Magmi új rendszerrel kompatibilis verziójának tökéletesítésébe, és hamarosan egy minden funkciójában tökéletes, az export és import feladatokat hibátlanul ellátó kiegészítőt köszönthetünk a legújabb Magmi-frissítés személyében.

A Magmi telepítése

A Magmi telepítése

A Magmi telepítése némi gyakorlatot igényel, azonban az interneten rengeteg segédanyagot találhatunk azzal kapcsolatban, hogyan is csináljuk helyesen, és természetesen most mi is azért vagyunk itt, hogy segítsünk.

A cikkben a Magmi 0.7.22 verziójának telepítését és alkalmazását fogjuk bemutatni.

  • Első lépésként töltsük le a Magmi-t a GitHub-ról. A Magento 2.0 verziójával kompatibilis változat az oldalon, ide kattintva érhető el.
  • Ha ez megtörtént, az FTP-kliens segítségével másoljuk fel a magento root könyvtárunkba.
  • Aki régebbi Magmi verziót használ (< 0.7.22) annak ajánlott a Magmi mappát átneveznie, és e mellet még htaccess-es megoldással levédeni a magmi/ root mappáját. Ha ezeket a beállításokat nem végezzük el, akkor bárki elérheti a Magmis felületünket.

 

Magmi plugin-jainak a beállítása

Magmi pluginjainak a beállítása

A Magmi kiegészítőinek beállításai a Configure Current Profile opció alatt, illetve a general és az itemprocessors résznél találhatók.

Mindegyik plugin-nál található egy Info gomb, melyre rákattintva rövid leírást kapunk az adott kiegészítőről. A Documentation gomb (mely nem biztos, hogy minden felhasználónál megjelenik) pedig a Magmi Wiki oldalára visz, ahol részletesebb leírást is találhatunk az adott pugin-ról.

Ha az egyik plugin-t aktiváljuk, megjelenik egy Configure gomb is, melynek megnyomása után be tudjuk állítani a kiegészítőhöz tartozó, fontos beállításokat.

Most minden plugin-ról leírunk pár fontos tudnivalót, a teljes, részletes ismertetőket a plugin-ok fentebb említett dokumentációjában találhatod meg.

Magmi beállítás általános

Remote Agent Plugin v0.0.1

  • Fejlesztette: Dweeves
  • Leírás: ez a plugin lehetővé teszi a távoli rendszeren való működést, akkor használatos, ha a Magmi távoli rendszeren van telepítve
  • Beállításai:
    • HTTP Url for magento base dir: távoli rendszer magento mappa url-je

Attribute Cleanup v0.0.1

  • Fejlesztette: 5byfive GmbH
  • Leírás: ez a plugin eltávolítja azokat a jellemzőket, melyek az adott terméknél nem használunk
  • Beállításai: nincs

Attribute Set Importer v0.0.2

  • Fejlesztette: 5byfive GmbH
  • Leírás: ez a plugin lehetővé teszi a jellemzőhalmazok és jellemzők importálását.
  • Beállításai:
    • Enable attribute import (Engedélyezzük-e a jellemző importálását)
      • CSV import mode: fentebb részletezve (a további beállítások is ugyanazok, mint a CSV options-nál)
      • Set default values for non-existing columns in CSV (JSON): ide kell beírni azokat az értékeket, amelyek mindegyik jellemzőnél ugyanazok, JSON formátumban kell megadni, pl. {“is_user_defined”:1,”is_visible”:1,”default_value”:”Test”}
      • Prune attributes which are not in CSV from database: ha ez be van kapcsolva, akkor először lefutatja a jellemző-importot, majd az összes olyan jellemzőt törli, ami nincs a csv-ben. Ez akkor jó, ha mindig az összes jellemzőt importáljuk és szeretnénk, ha a felesleges jellemzőket a plugin törölné.
      • Don’t touch non-user attributes when pruning (ha a prune attributes be van kapcsolva): Ezt akkor kell használnunk, ha csak azokat a jellemzőket szeretnénk törölni, amik is_user_defined = 1, vagyis a nem rendszer attribútumok. (ezt az egyedi fejlesztések során létrejött jellemzőkre szoktuk állítani)
      • additionally, keep following attributes when pruning, even if not given in CSV (comma-separated): Ebbe a mezőbe azoknak a jellemzőknek a kódját kell beírni (vesszővel elválasztva), amelyeket nem szeretnénk törölni (ezt akkor érdemes használni, ha a csv-ben nem adjuk meg a jellemzőt, de mégse szeretnénk, hogy a rendszer törölje)
      • Delete attributes marked “magmi:delete” = 1: ha ez be van kapcsolva és a csv-ben a magmi:delete oszlop létezik, amelynél 1-es értékre van állítva, akkor azt a jellemzőt törölni fogja
      • Create attributes from CSV which are not in database: ha ez bevan kapcsolva, akkor a plugin létrehozza azokat a jellemzőket, amelyek még nincsenek az adatbázisban. Ha nincs bekapcsolva, akkor a csv-ben lévő jellemzők
      • Update attributes from CSV which are already in database: kapcsoljuk be, ha szeretnénk, hogy frissítse a csv-ben megadott jellemzőket (ami szerepel az adatbázisban)
    • Enable attribute set import: engedélyezzük a jellemzőhalmaz importálását, Az itt található többi beállítás ugyanaz, mint a jellemzőnél.
    • Enable attribute association import: Ezzel tudjuk összepárosítani, hogy melyik jellemző melyik jellemzőcsoportba tartozzon.
      • CSV import mode: fentebb részletezve (a további csv beállítás is ugyanaz, mint a CSV options-nál)
      • Add these attribute associations to given CSV data: ide lehet plusz jellemző párosítást beletenni, vesszővel kell elválasztani ilyen formában: (attribute_set_name,attribute_code,attribute_group_name)

Ehhez tartozó beállítás ugyanaz, mint az előbbiekben leírtaknál.

Import Report Mail Notifier v1.0.0

  • Fejlesztette: Dweeves
  • Leírás: ezzel tudunk jelentést küldeni az importról
  • Beállításai:
    • Email report to: Kinek küldje a jelentést. Vesszővel elválasztva több e-mail címet is megadhatunk.
    • Report sender: küldő e-mail címe
    • Report sender alias: küldő alias-a
    • Subject: tárgy
    • Body: tartalom
    • Attachments: csatolmányok:
      • Attach import log: csatolja-e a jelentés log-ot
      • Attach source CSV: a csv forrást csatolja-e
      • Zip attachments: összecsomagolja-e a csatolmányokat

Magmi Import Url UI v1.0.3

  • Fejlesztette: Dweeves
  • Leírás: ez nem befolyásolja az importot, csak kiírja nekünk, hogy milyen url-en lehet meghívni. Ezeket általában cronjob-okba szokták írni.
  • Beállításai: nincs

Magmi Optimizer v1.0.5

  • Fejlesztette: Dweeves
  • Leírás: ez a plugin indexeket tesz pár olyan táblára, ahol észleli, hogy szükség van rá.
  • Beállításai: nincs

Magmi Magento Reindexer v1.0.3a

  • Fejlesztette: Dweeves
  • Leírás: ez a plugin a Magento-s reindexet hívja meg shell-ből, vagyis reindexelést végez.
  •  Beállításai:
    • PHP CLI command: php cli parancs
    • Indexing : Ki kell választani, hogy melyik index típusokat szeretnék, ha újraindexelné.

On the fly category creator/importer v0.2.5

  • Fejlesztette: Dweeves
  • Leírás: ezzel lehet importáláskor a kategóriákat létrehozni.
  • Beállításai:
    • Assign product to: Melyik kategóriához rendelje a terméket.
      • all categories in tree: az összes kategóriához a kategória fában (pl. Fő kategória/Alkategória/ ebben az esetben mind a 2 kategóriába bele fog tartozni)
      • last category of each branch: itt csak az utolsó szinten lévő kategóriába teszi bele a terméket.
    • Tree level separator: Alkategória elválasztójel (pl. / ebben az estben Kategória 1/Kategória 2)
    • base category tree: főkategória, ezt akkor ajánlott használni, ha mindegyik kategóriánk ugyanabba a főkategóriába tartozik.
    • url ending: url utótag, általában ajánlott a .html végződés

Downloadable products importer v1.0.0.1

  • Fejlesztette: Tangkoko SARL
  • Leírás: ez a plugin importálja a letölthető termékeket
  • Beállításai: Bővebben a „Letölthető termék importálása” résznél foglalkozunk vele

Group Price Importer v0.0.4 info

  • Fejlesztette: Tim Bezhashvyly és Dweeves
  • Leírás: csoportos árakat lehet importálni vele
  • Beállításai:
    A csv-ben ezt az oszlopot kell megadni:
    “group_price:groupName” ahol a groupName a vevőcsoport neve.
    Bővebben kifejtem a „Egyszerű termék importálása” résznél.

Image attributes processor v1.0.33a

  • Fejlesztette: Dweeves és Tommy Goode
  • Leírás: ez a plugin importálja a termékekről készült képeket.
  • Beállításai:
    • Image search path: melyik mappákban keresse a képeket (ezeket előzőleg fel kell tölteni a szerverre, ajánlott a media/import mappa), pontosvesszővel kell elválasztani, ha több mappát szeretnénk megadni
    • Image Renaming: átnevezze-e a képeket; hagyjuk üresen, ha az eredeti fájlnevet szeretnénk megtartani.
      Itt lehet dinamikus változókat használni.
      Ha szeretnénk átnevezni a képet, a következő formátumot javaslom:
      {item.sku}_{meta.attr_code}_{meta.store}.{meta.imagename.ext}
    • Image import mode: importálás módja
      • Keep existing images: ebben az esetben nem írja felül, vagy nem fogja letölteni (távoli url-ről) azokat a képeket, amelyek ugyanazon a néven léteznek.
      • Overwrite Existing Images: felülírja és újra letölti (távoli url-ről) az ugyanazon a néven szereplő képeket.
    • Assing only existing images: (ezt a beállítást nem figyeli a rendszer ebben a verzióban)
      • Import into DB: adatbázisba importálja-e; ezt csak akkor állítsuk Enabled-re, ha be van állítva a Magento-nkba a Media storage.
      • Debug mode: hibakeresés be legyen-e kapcsolva
      • Remote Image root: tavoli képek útvonala (ha nincs, üresen kell hagyni)
      • Remote root Authentication: szükség van-e távoli bejelentkezésre
      • Pre-download check: (ezt a beállítást nem figyeli a rendszer ebben a verzióban)

On the fly indexer v0.2

  • Fejlesztette: Dweeves
  • Leírás: ez a plugin importáláskor ír néhány index táblába (url_rewrites és a category_products)
  • Beállításai:
    • URL endings: url végződések, legyenek-e használva, és ha igen, akkor mik legyen azok.
    • Use Categories in Url: kategoriák legyenek-e az url-ben

Custom Options v0.0.7a

  • Fejlesztette: Pablo és Dweeves
  • Leírás: ezzel a plugin-nal lehet beimportálni a termékekhez az egyedi opciókat
  • Beállításai: a következőképp kell beállítani a csv-ben a custom optionokat:
    Name:Type:Is Required:sort number
    vagyis pl. Size:drop_down:1:1, és a terméksorba pedig pl: Small|Medium|Large
    A többi részletes variációt megtalálhatjuk a plugin dokumentációs oldalán.

Product Deleter v0.0.2

  • Fejlesztette: Dweeves
  • Leírás: ezzel a plugin-nal termékeket lehet törölni
  • Beállításai:
    • Delete Children products: törölje-e az alá tartozó termékeket. Ez a konfigurálható és kötegelt termékeknél lényeges.
      A csv-be új oszlopként fel kell venni a magmi:delete-et, és a törlendő termékeknél 1-re kell állítani.

Product Tags Importer v0.0.3

  • Fejlesztette: Dweeves, Pawel Kazakow
  • Leírás: termék címkéket lehet importálni vele
  • Beállításai:
    csv-ben vesszővel elválasztva kell beírni a címkéket a tags oszlopba

Tier price importer v0.0.9a

  • Fejlesztette: Dweeves, bepixeld
  • Leírás: ezzel lehet mennyiségre vonatkozó, kedvezményes árat importálni
  • Beállításai:
    Bővebben az „Egyszerű termék importálása résznél” foglalkozunk vele.

Weee Tax importer v0.0.5

  • Fejlesztette: Garbocom & Dweeves
  • Leírás: ezzel lehet a Weee-ket, vagyis környezetvédelmi adókat importál
  • Beállításai:
    • Weee Tax Attribute name: a környezetvédelmi adó jellemző kódja
    • Weee Tax Country code: az adó ország kódja (pl. FR)

Column mapper v0.0.3b

  • Fejlesztette: Dweeves
  • Leírás: ezt a plugin-t akkor érdemes használni, ha az import fájlban eltérőek az oszlopok nevei a Magento jellemzőkódoktól.
  • Beállításai:
    • Mapped columns list: ide kell felsorolni, vesszőkel elválasztva a Magento-ban szereplő jellemzőkódokat
    • New name for col X: ide írjuk be az import fájlban szereplő nevét az adott jellemzőnek (ha a Mapped columns listbe újat írunk be, akkor jelenik meg a New name for col …)

SKU Finder v0.0.3

  • Fejlesztette: Dweeves
  • Leírás: ezt a kiegészítőt akkor kell használnunk, ha nem adjuk meg az import fájlunkban az SKU vagyis cikkszám oszlopot, helyette egy másik termékjellemző alapján kell összepárosítani
  • Beállításai:
    • sku find attribute code: a párosítandó jellemző kódja.

Default Values setter v0.0.5

  • Fejlesztette: Dweeves
  • Leírás: ezzel lehet beállítani az olyan értékeket, amelyek mindegyik jellemzőnél ugyanazok, így nem kell az import fájlba beírni
  • Beállításai:
    • Default attribute list: vesszővel elválasztva be kell írni a jellemző kódjait, ahogy a Magento-ban szerepel, majd az alatta lévő oszlopokba pedig az értéket

Magmi Import Limiter v0.0.7

  • Fejlesztette: Dweeves
  • Leírás: ezt akkor kell használni, ha limitálást szeretnénk az importjainkra tenni, vagyis pl. csak bizonyos jellemzőket szeretnénk beimportálni, vagy csak bizonyos sortól sorig használni azokat.
  • Beállításai:
    • Column filter: melyik jellemzőket importáljuk, pl. sku,price,qty
    • Limiter ranges: pl. 1-100, vagyis hogy melyik sortól kezdve meddig importáljon
    • Limiter filters: csak azokat a termékeket importáljuk, amelyek bizonyos szűrési feltételnek megfelelnek,
      pl. sku::00.* – vagyis csak azokat a cikkszámokat importálja, amelyek 00-val kezdődnek
      pl. sku:00.*;;!name::.*blue.* – vagyis a 00-val kezdődő cikkszámokat és a név nem blue-val kezdődik.

Generic mapper v0.0.6a

  • Fejlesztette: Dweeves
  • Leírás: ezzel a plugin-nal a Magento-s értékekkel való értékpárosítást lehet elvégezni. Tipikus jellemző a page_layout és a visibility.
  • Beállításai:
    Ha szeretnénk használni, akkor az adott jellemzőre létre kell hoznunk a jellemző nevével egy csv fájlt a „magmi/plugins/itemprocessors/genericmapper/mappings” könyvtárba, pl. „magmi/plugins/itemprocessors/genericmapper/mappings/is_recurring.csv”
    Ennek a tartalmába be kell az érték párost írni. pl.
    „Yes”,1
    „No”,0
    Részletesebb leírást a plugin dokumentációjában olvashatunk.

Value Replacer v0.0.8a

  • Fejlesztette: Dweeves
  • Leírás: ezzel a plugin-nal jellemzők értékeit tudjuk lecserélni. Dinamikus változókat is használhatunk, vagyis pl. ha az összes termék cikkszámához szeretnénk perfixet tenni, akkor a következőképp kell beírni a mezőbe: prefix-{item.sku}
  • Beállításai:
    • Replaced attributes: fel kell sorolni a jellemzőkódokat, amelyeknél szeretnénk cserélni az értéket (vesszővel elválasztva)
    • New value for X: ide kell beírni az értéket
      További leírás a dokumentációban található.

Value Trimmer for select/multiselect v0.0.3

  • Fejlesztette: Dweeves
  • Leírás: ez a plugin automatikusan levágja az üres helyeket a többszöri vagy sima kiválasztós jellemzők értékénél
  • Beállításai: nincs

Grouped Item processor v1.4.1

  • Fejlesztette: Alpine Consulting, Inc & Dweeves
  • Leírás: ezzel lehet csoportos termékeket importálni
  • Beállításai:
    • Perform simples/group link: összekapcsolja-e az egyszerű termékeket a csoportos termékkel.
    • auto match simples skus before grouped: ezzel tudjuk beállítani, hogy automatikusan keresse-e meg a csoportos termékhez tartozó egyszerű termékeket, ha nem, akkor az import fájlban léteznie kell a „grouped_skus” oszlopnak, ahol pontosvesszővel elválasztva fel kell sorolni a hozzá tartozó egyszerű terméket.
    • Force simples visibility: az egyszerű altermékek láthatóságát állítsa-e, ha igen, akkor mire.

Bundle Item processor v1.1

  • Fejlesztette: Björn Tantau, Dweeves, igi8819
  • Leírás: Kötegelt termékeket importálhatunk vele
  • Beállításai:
    A „Kötegelt termékek importálása” résznél bővebben kitérünk rá, de mindegyik beállítás arra szolgál, hogy beállítsa az értékeket a megadott típushoz, abban az esetben, ha az import fájlban nem írjuk be azokat.

Configurable Item processor v1.3.7a

  • Fejlesztette: Dweeves
  • Leírás: Segítségével onfigurálható termékeket lehet importálhatunk.
  • Beállításai: ugyanazok, mint a csoportos terméknél, melyek fentebb olvashatók.

Cross/Upsell Importer v1.0.3

  • Fejlesztette: Dweeves
  • Leírás: Segítségével cross- és upsell termékeket importálhatunk.
  • Beállításai:
    Az import fájlban két új oszlopot kell beírni:
    us_skus – Upsell
    cs_skus – Cross sell
    Mindkettőnél cikkszámokat kell felsorolni, vesszővel elválasztva.

Product relater v1.0

  • Fejlesztette: Dweeves, jwtechniek
  • Leírás: Segítségével hasonló termékeket impotálhatunk.
  • Beállításai:
    Az import fájlban a re_skus oszlopba kell beírni a cikkszámokat.
    Részletesebb leírást a plugin dokumentációban olvasnhatunk.
    A plugin beállításait a lenti Save Profile gombbal kell elmenteni.

 

Egyszerű termék importálása

Egyszerű-termék-importálás

Első lépésként fontos, hogy konfiguráljuk a plugin-ok legfontosabb beállításait.
Ezután leírjuk, hogyan is kell egy import fájlt létrehozni. Mint ahogy az elején említettük, ezt egy CSV-fájlon keresztül fogjuk bemutatni.

Mielőtt azonban nekikezdenénk, bizonyosodjunk meg róla, hogy van olyan programunk, ami alkalmas a CSV-fájlok kezelésére. Amennyiben még nem rendelkezel ilyennel, azt javasoljuk, hogy szerezd be a következő két, ingyenes program valamelyikét:

  • Open Office (azon belül is a Calc)
  • Libre Office (azon belül is a Calc)

Fontos, hogy a CSV-t mindig UTF-8 beállítással és a megadott elválasztó paraméterekkel kell megnyitnunk/mentenünk.

Magmi CSV szöveg import

Miután megnyitottuk, a következő oszlopokat kell beírni fejlécként a CSV-be:

  • sku: termék cikkszáma, ezzel fogja a rendszer módosításkor beazonosítani a meglévő terméket
  • attribute_set: jellemzőhalmaz neve, ugyanúgy kell beírnunk, mint ahogy a Magento-ban szerepel, pl. Default
  • type: a termék típusa, lehetőségek:
    • simple – egyszerű
    • configurable – konfigurálható
    • downloadable – letölthető
    • bundle – kötegelt
    • grouped – csoportos
    • virtual – virtuális
  • websites: Ez a 0.7.17 verziótól elavulttá vált.
  • store: ide kell beírni, hogy melyik store view-hoz rendeljük hozzá (mindig a store view kódot kell megadnunk). Ezzel lehet a nyelvesítést elvégezni, amit bővebben a „Többnyelvű importálás” résznél fejtünk ki. Ha egy store view-nk van, vagyis egynyelvű az áruházunk, akkor nem kell, hogy szerepeljen az import fájlban. Illetve a képen látszik, hogy admin van beírva a store-nak, ilyenkor ez ugyanaz, mintha be se írtuk volna az oszlopot.
  • categories: ide kell beírni, hogy mely kategóriákhoz rendeljük a terméket (ha nincs bekapcsolva az „On the fly category creator/importer v0.2.5” plugin, akkor a beírt kategóriáknak léteznie kell a rendszerben, még mielőtt importálunk. A beírt adatok szintaxisa:
    • Kategória1
    • Főkategória/Alkategória
    • Kategória1;;Kategória2 – vagyis ha több kategóriába is beletartozik egy árucikk, akkor kettő darab pontosvesszővel kell elválasztani
    • Kategória1/Alkategória1;;Kategória1/Alkategória2;;Kategória2/AlKategória3
  • name: a termék neve
  • description: termék hosszú leírása, html tag-ek engedélyezve vannak
  • short_description: termék rövid leírása, html tag-ek engedélyezve vannak
  • price: a termék ára, itt mindig az alapértelmezett pénznemben kell beírni, adó nélkül (tehát nettó árat), pl. 150
  • special_price: a termék kedvezményes ára, ha nincs, akkor 0
  • special_from_date: ha a terméknek van kedvezményes ára, akkor ide be lehet írni, hogy mikortól legyen akciós (pl. 2016-05-20), ha mindig, akkor üresen kell hagynunk
  • special_to_date: meddig legyen akciós a termék, üresen hagyva a végtelenségig akciós lesz
  • news_from_date: újdonságnak jelölt termék kezdeti dátuma
  • news_to_date: újdonságnak jelölt termék befejezési dátuma
  • qty: ha van készletkezelés, akkor a termék raktáron lévő mennyisége (pl. 5)
  • in_in_stock: van-e raktáron, értékek: 1 – igen, 0 – nem
  • manage_stock: használja-e ennél a terméknél a raktárkezelést (ha használunk raktárkezelést, ki lehet egyes terméknél kapcsolni, hogy legyen-e vagy sem), értékek:1 – igen, 0 – nem
  • use_config_manage_stock: használja-e a rendszerbeállításban megadott raktárkezelést. Ha állítani akarjuk az előbbi manage_stock értéket, akkor itt 0-át kell megadni, hogy ne a rendszerbeállításból olvassa ki az értéket, hanem az ennél a terméknél megadott manage_stock értékből.
  • status: engedélyezve van-e a termék, értékek: 1 – igen, 0 – nem
  • visibility: a termék láthatósága, értékek:

1 – egyedileg nem látható, ezt általában a konfigurálható, csoportos termékeknél szokták használni. Ebben az esetben a termékadatlap sem érhető el, a többinél a termékadatlap elérhető
2 – csak a katalógusban, vagyis a kategória oldalakon látható, a keresésnél nem
3 – Csak a keresésnél látható
4 – Mindenhol látható

  • weight: a termék súlya, pl. 0.5. Ha ezt nem szeretnénk használni, akkor a jellemzőnél át kell tenni, hogy ne legyen kötelező megadni.
  • tax_class_id: az adóosztály id-je vagy a neve, pl. Taxable goods
  • thumbnail: a termék bélyegképe, pl. ball-for-football.png
  • small_image: a termék kis képe
  • image: a termék főképe
  • media_gallery: termékgaléria, itt a képek nevét pontosvesszővel kell elválasztani, pl. ball-for-football.png;ball-for-football2.png

Magmi CSV minta

 

A képeket csak akkor fogja importálni a rendszer, ha a „Image attributes processor v1.0.33a” plugin be van kapcsolva.

Természetesen a többi jellemzőt bele kell írni az import fájlunkba.

A select, vagyis egyszeri kiválasztós jellemzőknél a szöveges értéket kell beírnunk. (pl. a color jellemzőnek a Red szót írhatjuk.)

A többszöri kiválasztós értékeknél ugyanúgy kell tennünk, mint a select-nél, csak ha több értéke van, akkor a Magmi beállításában megadott Multiselect Separator-nál megadott karakterrel kell elválasztanunk (pl. Red|Green|Blue)

Magmi csoportos ár

Hogyan kell csoportos árat (Group Price) importálni?

A csoportos ár importálásához a CSV-fájlba fel kell vennünk egy “group_price:groupName” oszlopot, ahol a gropName a csoport neve, ahogy a Magento-ban szerepel.

Ha több csoporthoz szeretnénk árat importálni, még ha egyformát is, akkor külön oszlopba be kell azt beírnunk.

Ha nem létezik az adott vásárlócsoport, akkor a Magmi létre fogja azt hozni.

Hogyan kell mennyiség kedvezmény árat (tier prices) beállítani?

Az import fájlban egy új oszlopként be kell írnunk a következőt:
tier_price:group1 – ahol a group1 a vásárló csoport nevét jelöli.

Ha szeretnénk, hogy az összes csoportra érvényes legyen, akkor tier_price:_all_
Ha több csoportnak szeretnénk beállítani, akkor ugyanúgy, mint a csoportos árnál, új oszlopban kell felsorolnunk.

A terméksorba pedig:
25:10.00;50:9.00;100:8.00 – ami annyit jelent ebben az esetben, hogy 25 mennyiségnél vagy felette 10-be, 50 felett 9-be, 100 felett pedig 8-ba kerül.

Százalékos kedvezményt is meg lehet adni, ilyenkor pl. 25:85%, vagyis 25 mennyiségnél vagy felette 85 százalékos kedvezményt adunk.

Magmi CSV kedvezmény ár

Hogyan tudom a termékeket hozzárendelni a több website-os áruházban?

Ha olyan áruházat üzemeltetünk, mely egyszerre több weboldallal is rendelkezik, és vannak olyan termékeink, amelyek csak egyes oldalakon érhetők el, akkor a CSV-ben a store oszlopba azokn üzletek a store_view kódjait kell felsorolnunk, amelyekben a termék elérhető. Bemutatom egy példával:

8-Magmi-egyszeru-weboldal-aruhaz

A következő képen látható, hogy van 2 weboldalunk. Mindkettőnél 1 store van, az US store-nál csak angol nyelv, az EU store-nál pedig három nyelv is szerepel.
American English store_view kódja legyen:us, eu store-nál az Engilsh legyen: en, a German: de, a Hungarian pedig: hu.

  • Ha pl. a test 1-es termékünk, csak az us websopban van, akkor a store oszlopba az us kódot írjuk be.
    • Ha pl. az test 2-es termékünk csak az eu storokban szerepel, akkor fel kell sorolni mind a 3 nyelvet, vagyis en,de,hu
    • Ha a termék mindegyiknél szerepel, akkor az admin szót kell beírni.

Magmi egyszerű weboldal áruház csv

A többnyelvűség beállításával a „Többnyelvű importálás” részben bővebben foglalkozunk.
Itt található példa egy egyszerű termék importjára: magmi_simple_example.csv

Hogyan kell importálni?

A Magmi oldalán láthatunk egy Run Magmi feliratot, ott kell kiválasztanunk, hogy melyik profil alapján, milyen módban szeretnénk elvégezni az importálást.

Importálás után szükséges a reindexálás kell (reindex plugin a Magmiban is elérhető), illetve törölni ekll a cache-t a Magento-ban.

  • Update existing items only, skip new ones: csak a már Magento-ban létező termékeket frissíti, az újakat figyelmen kívül hagyja.
  • create new items & update existing ones: újakat is és a meglévőket is frissíti
  • create new items only, skip existing ones: csak az újakat hozza létre

Ezután a run import gombot kell megnyomnunk az importálási folyamat elvégzéséhez.

Konfigurálható termék importálása

A konfigurálható termék importálás funkció eléréséhez be kell kapcsolnunk a „Configurable Item processor” plugin-t. A konfigurálható terméknél most csak az egyszerű termékhez képesti különbségeket foglaljuk össze, mivel a többi beállítás gyakorlatilag megegyezik.

Magmi CSV konfigurálható termék

A konfigurálható termék több egyszerű termékből áll össze. Az import fájlban mindig az egyszerű termékeket kell előre tenni, és utána jön a konfigurálható termék.

Konfigurálható termék importálásakor először is meg kell adnunk, hogy mely jellemzők lesznek választhatóak a vásárlók számára (pl. méret, szín).
Csak „Globális” hatókörű, „Lenyíló” típusú jellemzőt lehet használni konfigurálásra és be is kell, hogy állítsuk a jellemzőnél, hogy konfigurálásra használható.

Fontos továbbá, hogy az a jellemző az adott jellemzőhalmaz része legyen.
Ha nem írjuk bele a fájlba a párosítandó cikkszámokat, akkor a plugin-ban be kell kapcsolnunk, hogy automatikusan megkeresse az altermékeket („auto match simples skus before configurable”), ilyenkor a cikkszámot a következőképp kell elnevezni:

Magmi CSV konfigurálható auto match

A konfigurálható cikkszáma (pl. testconf) Az altermékek cikkszáma: testconf1*** – a csillag helyére bármi mást be lehet írni, javasolt a konfigurálható jellemző értéke, (pl. testconf1-white-s, testconf1-white-m).

Ha pedig egyedi cikkszámot szeretnénk a termékeknél, akkor a simple_skus oszlopba kell beírni, hogy mely cikkszámok tartoznak alá.
Ha eltér az altermékek ára (pl. az M-es méretű drágább, mint az L-es) akkor a fájlba be kell írnunk a „super_attribute_pricing” oszlopot, amibe a konfigurálhatónál a következőképp kell  megadni:
jellemzőkód::érték:ár;érték:ár, jellemzőkód::érték:ár;érték:ár

vagyis pl. size::L:43;M:55

Ha fix ár helyett százalékos növelést szeretnénk, akkor pedig:
jellemzőkód::érték:ár:százalékos-e;érték:ár:százalékos-e
size::L:15:1;M:20:1 – vagyis, ha 1-es, akkor százalék, ha 0 akkor fix ár.

Ha nem adjuk meg ezt az értéket, a rendszer alapból fix árat fog használni.

Magmi CSV konfigurálható példa

Itt található egy konfigurálható termék import példa: magmi_configurable_example.csv

Kötegelt termék importálása

Ebben a részben azt mutatjuk be, hogy mit kell beállítani az import fájlban annak érdekében, hogy kötegelt termékeket tudjunk importálhassunk.

A Magmi plugin-jai között először is kapcsoljuk be a „Bundle Item processor” plugin-t.
Itt ugyanúgy kell létrehozni és kitölteni a CSV-fájlt, mint az egyszerű terméknél, ezért csupán a két módszer közötti különbséget mutatjuk be.

A következő oszlopokat kell beletennünk:

bundle_options:

Magmi CSV kötegelt opciók

-*;Code,Option name;type:is_required;position

pl.

-*;CPU:Central Processing Unit:radio:1:0;RAM:Random Access Memory:select:1:1;MOUSE:Mouse:checkbox:0:2

Ahol:

  • -* ha ezt az elejére írjuk, akkor a rendszer törli az előzőleg beírt opciókat a Magento-ból. Ha ezt nem írjuk, akkor a meglévőkhöz hozzáteszi a beírtakat.
  • Code: ez lesz a kódja az opciónak, ezt használjuk a bundle_skus-nál az összepárosításra
  • Option name: ez a neve az opciónak, ez a szöveg fog látszódni a terméknél
  • type (radio, checkbox, select, multi): ez az opció típusa
  • is_required: kötelező-e a vásárlónak választani az adott opcióból (1-igen, 0-nem)
  • position: a termék adatlapon milyen sorrendbe jelennek meg (számokat kell írni)
  • bundle_skus:

Magmi CSV kötegelt SKUS

Code:sku:selection_qty:can_change_qty:position:is_default:selection_price_value:selection_price_type
pl.
CPU:cpu1:1:0:1:1:0:0;CPU:cpu2:1:0:0:1:0:0;RAM:ram1;RAM:ram2;MOUSE:mouse1:1:0:0:1:50:1

Ahol:

  • Code: a bundle_options-nál is megadott kód
  • sku: az altermék cikkszáma
  • selection_qty: a kosárba helyezés mennyisége
  • can_change_qty: kiválaszthatja-e a vásárló, hogy az adott opcióból mennyit vásárol
  • position: opciók pozíciója
  • is_default: alapértelmezett-e az adott opció
  • selection_price_value: a kiválasztás ára (ez csak akkor érvényesül, ha a csv-ben a bundle-nél vagy a plugin beállításánál a price_type 1-re (Percent) van állítva
  • selection_price_type: az ár típusa (0 – Fixed, 1 – Percent)
  • price_view: az ár megjelenési típusa, 1 (Legkisebb ár, amelyen megveheti), 0 (ár tartomány, tehát x összegtől y összegig)
  • price_type: ár számítási típusa, 0 – dinamikus, 1 – fix ár
  • options_container: Hol jelenítse meg az opciókat (container1, container2), ez témától függ
  • shipment_type: a kötegelt elemek szállítása, 1 – elkülönítve, 0 – egyben
  • sku_type: cikkszám típusa, 0 – dinamikus, 1 – fix
  • weight_type: súly típusa, 0 – dinamikus, 1 – fix

Magmi CSV kötegelt egyéb

Importálás után csináljunk egy reindexet és cache-frissítést. Ha mindent jó állítottunk be, akkor a képen látható módon kell a termék adatlapnak megjelennie.

16-Magmi-kotegelt-Frontend

Itt található egy kötegelt termék import példa: magmi_bundle_example.csv

Csoportos termék importálása

A csoportos termék beállításai nagyon hasonlóak a konfigurálható termékéhez.
Először is, a Magmi plugin-jai között be kell kapcsolnunk a „Grouped Item processor” plugin-t. Eztuán az import fájlba a grouped_skus oszlopot kell beillesztenünk, amiben az egyszerű altermékek cikkszámai szerepelnek.

17-Magmi-csoportos-pelda

Itt található egy példa a csoportos termék importjára: magmi_grouped_example.csv

Letölthető termék importálása

A letölthető termék importfájlja hasonló az egyszerű termékéhez. A „links” oszlop kell bele, amit a következőképp kell kitölteni:

file:link,sort_order :position,title:file title,sample :example link,is_shareable :config or 0 or 1,number_of_downloads :value

  • file: ide kell a letölthető fájl linkje, url vagy teljes útvonal, ha lokálisan szerepel
  • sort_order: pozíció (ha több links van)
  • title: fájl neve
  • sample: betekintő fájl
  • is_shareable: a vásárló megoszthatja-e mással a fájlt
  • number_of_donwloads: hányszor töltheti le a fájlt

Ha több fájlunk van, akkor csak a fenti sort kell duplázni, pontosvesszővel elválasztva (pl. file:https://aionhill.com/test.zip,sort_order:1,title:Test,sample:,is_shareable:1,number_of_downloads:100;file:https://aionhill.com/test2.zip,sort_order:2,title:Test2,sample:,is_shareable:0,number_of_downloads:1; )

Magmi letölthető példa

Itt található egy letölthető egy példa a letölthető termék importjára: magmi_downloadable_example.csv

Virtuális termék importálása

Virtuális termék importálása ugyanaz, mint az egyszerű terméké, annyi a különbség, hogy a type nem simple, hanem virtual.

Magmi Virtuális példa

Itt található egy példa a virtuális termékimportra: magmi_virtual_example.csv

Jellemző és jellemzőhalmaz importálása

Jellemző vagy jellemzőhalmaz importjához először is be kell kapcsolnunk és beállítanunk az „Attribute Set Importer” plugin-t.
Itt három CSV import fájlt kell létrehozni: egyet a jellemzőkre, egyet a jellemzőhalmazokra és egyet a párosításokra.
A jellemzőnél kötelezően meg kell adnunk az attribute_code-ot, vagyis a jellemző kódját (pl. color).
A többi oszlop megadása nem kötelező, csak akko, ha nem az alapértelmezett értéket szeretnénk használni.

Jellemző, magmi

A jellemzőcsoport esetében meg kell adnunk az attribute_set_name-et, vagyis a jellemzőcsoport nevét (pl. Ruházat).
A többi oszlop megadása nem kötelező, csak akkor szükséges, ha nem az alapértelmezett értéket szeretnénk használni.

Jellemzőhalmaz, Magmi

A jellemző és jellemzőcsoport párosításánál pedig a következőket kell megadnunk:

  • attribute_set_name: jellemzőhalmaz neve
  • attribute_code: jellemző kódja
  • attribute_group_name: melyik jellemzőcsoportba kerüljön a halmazon belül

Jellemzőhalmaz, Magmi, jellemző, párosítás

Termékkategóriák importálása

A termékkategóriák a termék importáláskor jönnek létre, ha a Magmi-ban be van kapcsolva az „On the fly category creator/importer” plugin.
Leggyakrabban a képen látható beállítás alapján használják a plugin-t.

Magmi kategória importer beállítás

Ez alapján a következőképp kell a CSV-ben a kategóriát beállítanunk.

Magmi kategória Importer CSV

A képen látható példában a termék a „Football” főkategóriában szereplő „Ball” és „Accessories” kategóriákba fog bekerülni.

A per (/) jellel lehet az alszinteket megadni, pl. Elsőszintű/Másodszintű/Harmadszintű.
A kettő darab pontosvesszővel tudjuk több kategóriába is besorolni, pl. Elsőszintű/Másodszintű/Harmadszintű;;MásikElsőszintű/MásikMásodszintű/MásikHarmadszintű
Új kategóriáknál megadhatjuk azt, hogy aktív-e, link-e, és hogy a navigációs menüben benne legyen-e, szintakszisa: category name::[is_active]::[is_anchor]::[include_in_menu]
pl. Football/Ball::1::0::0

Többnyelvű importálás

Többnyelvű (ami több store view-t jelent, ahol webáruházunk más-más nyelven jelenik meg) importálásnál minden terméket annyiszor kell a beírnunk az import fájlba, ahány nyelven azt szeretnénk megjeleníteni.

magmi többnyelvű importálás

Ahány nyelv, annyi sor, a store oszlopba kell beírni annak a store_view-nak a kódját amelyik nyelvű boltnézetbe szeretnénk beletenni.

A kategóriáknál sajnos a rendes fordítás nem megoldott, így vagy adminból fordítunk, vagy minden nyelvnek saját kategóriafát hozunk létre, pl.:

  • English Root
    • Ball
  • German Root
    • Ball
  • Hungarian Root
    • Labda

A name, description stb. oszlopba az adott nyelven kell beírni a szövegeket.

A lenyílós jellemzőknél a következőképp:
Adott nyelvű érték::[Admin érték]
Az első elem az adott nyelven megírt fordítása, a kapcsos zárójelbe kell az admin vagyis a default nyelven létező string-et írnunk. (pl. Red::[Red], Piros::[Red] )

Itt található egy példa többnyelvű importra: magmi_multilanguage_example.csv

Összegzés

A Magmi előnyei:

  • Telepítése és beállítása egyszerű
  • Használata felgyorsítja a munkát (egyszerre akár több ezer terméket is pár perc alatt importálhatunk a segítségével)
  • mind a 6 terméktípus importálására képes
  • automatizálható (vagyis automatikusan futó importokat is létrehozhatunk)

A Magmi hátrányai:

  • az importfájlok létrehozása kicsit bonyolult, maximális pontosságot igényel annak érdekében, hogy minden adat megfelelően jelenjen meg
  • mivel nyílt forráskódú, így sajnos akadnak benne apróbb hibák, egyes kiegészítők nem működnek mindig tökéletesen
  • a termék mentésekor futó observerek enm futnak le, mivel direkt SQL-el dolgozik
  • a Magento mellett még egy adminisztrációs felület használatát meg kell tanulnunk

Reméljük, sikerült minden részletre kiterjedően bemutatnunk a Magmi tulajdonságait, beállításait és használatát. Ha bármilyen témába vágó megjegyzésed vagy kérdésed lenne, ne habozz megírni alább, a komment részlegben. Ahol tudunk, segíteni fogunk abban, hogy a Magento és a Magmi segítségével te is kihozhasd saját webáruházadból a maximumot!

 

Tényleg képes a Magento több mint 500 ezer termék kezelésére?

Erre a kérdésre természetesen nehéz határozott és általános érvényű választ adni, de azért tapasztalataink alapján igyekszünk némi támpontot adni és néhány praktikus tanáccsal szolgálni.

 

Ehhez a következő gyakorlati problémákat próbáljuk körbejárni:

 

  • Hány terméket képesek a különféle Magento-verziók egy átlagos szerveren alapesetben, illetve további optimalizáció segítségével kezelni?
  • Mi a különbség  teljesítmény szempontjából az egyes Magento-verziók között?
  • Melyek azok a pontok, melyek egy nagyobb katalógus esetén szűk keresztmetszetet jelentenek? Hogyan lehet a Magentót úgy skálázni, hogy még több terméket lehessen vele kezelni?
  • Milyen gyakori hibákat lehet egy nagy méretű katalógus kezelése esetén a Magentóval elkövetni?

 

Hány terméket képesek a különféle Magento-verziók egy átlagos szerveren alapesetben, illetve további optimalizáció segítségével kezelni?

 

    • A Magento CE 1.9.x ‒ A legtöbb esetben  különösebb finomhangolás nélkül biztonságosan kezel~10 000 25 000 terméket  Széles körű skálázással, megfelelően megemelt szerver-erőforrásokkal és kód szintű optimalizációval viszont akár 100 000 ‒ 200 000 termék kezelésére is képessé tehető.
    • Magento EE 13.x. 14.x ‒ A legtöbb esetben  biztonságosan kezel különösebb finomhangolás nélkül ~100 000 200 000 terméket és akár 400 000 ‒ 500 000 vagy még több terméket megfelelő skálázás, optimalizáció és szerver-erőforrások biztosításával.
    • Magento 2 CE ‒ A legtöbb esetben, különösebb finomhangolás nélkül biztonságosan kezel ~ 100 000 200 000 terméket és akár 400 000 ‒ 500 000 vagy még több terméket megfelelő skálázás, optimalizáció és szerver-erőforrások biztosításával.
    • Magento 2 EE ‒ Úgy tervezték, hogy még több terméket is képes legyen kezelni olyan vállalati szintű megoldások segítségével, mint az adatbázis-szegmentáció, üzenetsorok illetve speciális MYSQL- és alkalmazásszerver-topológiák.

 

A fenti számok természetesen csak hozzávetőlegesek és olyan katalógusokra vonatkoznak, melyek néhány termékjellemzőt, kategóriát és kizárólag egyszerű termékeket tartalmaznak.  Az adatokat a Magento által közzétett teljesítménytesztek és saját tapasztalataink alapján állapítottuk meg és azok  a szerverkonfigurációtól, szerverszoftverektől és -erőforrásoktól függően jelentősen módosulhatnak.

 

Szintén fontos hangsúlyozni, hogy a Magento adatbázis-struktúrájának következtében néhány különösen erőforrás-igényes Magento funkció alkalmazása  megsokszorozza azoknak a termékeknek a számát, melyeket a Magento tulajdonképpen a háttérben kezel.

 

A legfajsúlyosabb funkciók a következők:

  • A Magento „bolt nézetek/nyelvek” száma
  • Termékjellemzők száma
  • Kategóriák száma és a kategóriastruktúra mélysége
  • Konfigurálható/összeállítható termékek száma
  • Különféle termékárakkal rendelkező vásárlói csoportok száma
  • Katalógus-árszabályok száma

 

Mindez adott esetben azt jelenti, hogy egy  olyan Magento webshop, mely mindössze néhány ezer terméket tartalmaz, de a Magento funkcionális lehetőségeit széles körűen kihasználja ‒  pl. 20 nyelvi változatot kezel, rengeteg termékjellemzővel, zömében konfigurálható termékekkel és több felhasználói árcsoporttal ‒ erőforrásigényét  tekintve azonos kategóriába tartozhat egy olyan Magento áruházzal, mely 100 000+ egyszerű terméket kezel egyetlen boltnézetben.

Ezek a funkciók teszik a Magentót igazán rugalmas rendszerré, de megvan a maguk ára a teljesítményoldalon.

 

Mi a különbség  teljesítmény szempontjából az egyes Magento-verziók között?

a magento verziók

 

  • Magento CE 1.x, a 1.9.x verzióval együtt
    • – az indexelés, különösen az URL- és keresés indexek nem optimalizáltak nagyobb katalógusokra (mindez az EE verzióra is érvényes 1.12.x-ig).
    • – Nem érhető el beépített funkcióként a teljes oldali gyorsítótár (Full Page Cache, FPC)
    • + elérhető néhány frontendes optimalizáció, mint például javascript és css összefűzés, CDN támogatás
  • Magento 1.x EE
    • + elérhatő az FPC, mely megfelelően alkalmazva rengeteg szerver-erőforrást képes felszabadítani.
    • +  inkrementált indexelés a 1.13+.x verziótól kezdve, melynek során a termékek indexelését időzített folyamatok végzik a háttérben.
    • + A  1.13+.x verziótól kezdve a teljes reindexelési folyamatok is jelentős optimalizáción estek át, és megfelelően működnek nagyobb katalógusok esetén is.
    • + Beépített lehetőségként tartalmazza a Solr keresőmotort
  • Magento 2 CE
    • + örökölte az inkrementális indexelést a Magento EE 1.13+.x-től.
    • + örökölte az FPC-t az EE 1.13+.x-től  és beépített támogatást tartalmaz Varnish frontend gyorsítótár kezelésére. A Varnish gyorsítótár-szerver legnagyobb előnye, hogy a Varnish által kiszolgált kérések el sem jutnak a Magentóig, így jelentősen csökken a webszerverek terhelése, emellett drámaian lecsökken az oldalbetöltési idő.
    • + A böngésző-gyorsítótárt használja a munkamenet-függő adatok tárolására (pl. kosártartalom)
    • + A pénztári folyamatok jelentős  optimalizáláson estek át
    • + Aszinkron termék- és rendelésmentési folyamatok.
    • + Frontend-optimalizációk széles köre, pl. js/css minifikáció, függőségkezelés, statikus tartalom gyorsítótárazása, képtömörítés.
    • + alapszintű PHP 7-támogatás, mely önmagában is akár 200% teljesítményjavulást eredményezhet a php 5.6.x-hez képest.
  • Magento 2 EE
    • + Rendelkezik a Magento 2 CE minden fentebb felsorolt funkciójával.
    • + Solr (2.0) és Elasticsearch (2.1) keresőmotorok.
    • + Lehetőség van az adatbázis szegmentálására külön szervereken a katalógus, kosárkezelés és pénztári folyamatok adatbázis-tábláit elválasztva.
    • + Mysql klaszter és „multi master” architektúra támogatása
    • + Támogatja a háttérfolyamatok üzenetsorokba való kiszervezését (Rabbit MQ, első megvalósítás a késleltetett készletfrissítés)

 

Melyek azok a pontok, melyek egy nagyobb katalógus esetén szűk keresztmetszetet jelentenek? Hogyan lehet a Magentót úgy skálázni, hogy még több terméket lehessen vele kezelni?

keresztmetszet

 

  • Hoszting ‒ egy nagyobb katalógusnak nyilvánvalóan több erőforrásra van szüksége, alapkövetelmény a VPS szerver elég memóriával és többmagos processzorral, illetve szükség lehet többszerveres elosztott környezet alkalmazására.
  • Szerverszoftverek ‒ erősen javasolt az Nginx webszerver, a  PHP 7 és a  Mysql 5.6  vagy annak megfelelő adatbázisszerver (Percona/MariaDb), még  Magento 1 esetében is. Emellett szintén nagyon fontos ezeknek a szerverszoftvereknek a finomhangolása, fokozottan figyelembe véve a Magento sajátságait.
  • Termékimport ‒ az optimalizált termékimport különösen fontos ebben az esetben, és rendkívül sokat segítenek azok az eszközök, melyek lehetővé teszik a kötegelt adatbázisműveleteket. Minden olyan módszer vagy eszköz, mely teljes, egyenként végrehajtott termékmentéseket  alkalmaz,  könnyen és gyorsan szűk keresztmetszetté válhat. Az egyik legjobb ilyen importot segítő eszköz a Magmi. Néhány további szempont, amit termékimport során érdemes szem előtt tartani.
    • Csak olyan adatokat mentsünk, melyek valóban megváltoztak.
    • Az importáláshoz használjunk dedikált erőforrásokat
    • Lehetőség szerint válasszuk szét az ár-készlet és az alapjellemzők importját
    • Csak azokat a termékeket és termékadatokat indexeljük újra, ahol újraindexelésre van szükség.
  • Indexing  ‒ Az indexelés a Magentóban a termékek mentésének második lépése, és alapvetően a legkényesebb terület, amikor nagy katalógusok kezeléséről van szó. Az indexelés egy sor olyan folyamatból áll, melyek az tárolásra optimalizált adatbázis-táblákból a különféle adatelérési szempontok szerint optimalizált táblákba másolják át az adatok egy részét. Mivel ezekre az indexekre csak a vásárlói (frontend) folyamatokhoz van szükség. Az indexelést a termékmentésről és termékimportról le lehet választani. A Magento 1 EE újabb verzióiban illetve a Magento 2 CE és EE-ben használt inkrementális indexelés nagyban felgyorsítja az adminisztrációs felületen végzett munkát, de bizonyos esetekben még ez sem ideális tömeges termékimport esetén.
    • A Magento 1 CE-ben az indexelés az a folyamat, ami a legtöbb problémát jelenti napi szinten és optimaliziáció szempontjából.
      • Az URL indexelés az egyik legkényesebb művelet, részben mert az index maga képes több milliós rekordszámra felduzzadni, részben mert egyáltalán nincs nagyméretű katalógusokra optimalizálva.
      • Bizonyos katalógusméreten túl, és bizonyos boltnézet-szám fölött az úgynevezett „flat tábla indexek” által nyújtott előnyöket túlszárnyalják a hátrányaik, így ezekben az esetekben érdemesebb őket kikapcsolni.
  • Catalog search
    • A beépített Mysql fulltext kereső indexelés és teljesítmény szempontjából is meglehetősen lassú, ráadásul találati pontossága is gyenge, így még Magento 1 esetén is erősen ajánlott a lecserélése. Számos remek, akár ingyenes modul érhető el Magento 1-hez is, melyek a Solr, Eleasticsearch vagy éppen a Sphinx keresőmotorhoz kapcsolják a katalógust. A Magento 1 Enterprise verziója beépített támogatást nyújt a Solr, illetve Magento 2.1 EE-től az Elasticsearch kezelésére.
  • Full Page Cache
    • A Full Page Cache olyan mechanizmus, melynek során a szerverszoftver által generált html oldalakat egészben eltároljuk. Ha ezután legközelebb azonos az oldalra van szükség, a tárolt változatot szolgáljuk ki anélkül, hogy szükség lenne az oldal újragenerálására és az ezzel járó számítási illetve adatbázis-műveletekre.  Amíg a Magento 1 CE  nem tartalmaz beépített  FPC-t, addig a Magento 1 EE -ben a teljes oldali gyorsítótárazást maga a Magento végzi. Ez utóbbi is sok erőforrást takarít meg és nagyobb oldalbetöltési sebességet eredményez, a cachelést  azonban  a legideálisabb a Magento előtti rétegekben megvalósítani anélkül, hogy ebben aktív szerep hárulna a Magentóra. Ehhez nyújt támogatást a Magento 2-ben a Varnish támogatás. Bár a Magento 1 CE nem tartalmaz beépített FPC-t és Varnish illesztést, megfelelő kiegészítő modulok segítségével hatékonyan ki lehet aknázni ezeket a lehetőségeket.
  • Alkalmazásszintű gyorsítótárazás
    • A Magento erősen támaszkodik a különféle konfigurációs és futás idejű tartalmak elérését gyorsító un. Cache-ekre. A jelenleg elérhető legjobb megoldás a memória alapú és tartalomcímkézést is teljes körűen kezelő Redis illesztés, mely már a Magento 1 CE legújabb változataiban is beépítve elérhető.

 

A különféle Magento-verziókra levetítve megállapíthatjuk a következőket:

 

  • Magas termékszám esetén a legérzékenyebb területek a termékimport és az indexelés a backenden, illetve keresése, termékszűrő és terméklistázás a frontenden. A pénztári funkciók és a rendeléskezelés szintén fontos tényezők, de az utóbbiak inkább függenek az oldal látogatottságától mint a katalógus méretétől.
  • A termékimport jó eséllyel Magento-verziótól függetlenül optimalizálásra szorul – adott esetben még a Maegento 2 EE-ben is.
  • A Magento 1 CE a legkevésbé alkalmas nagy termékkatalógus kezelésére, de kifinomult skálázással, alkalmas szerverháttérrel és az indexelés, keresés és gyorsítótárazás csorbáit kiköszörülő modulokkal jelentősen javítható a teljesítménye. Az indexelés azonban még ebben az esetben is problémákat tartogathat.
  • A Magento 1 EE jelentős optimalizációkat tartalmaz, az ő esetében a Varnish cache bevezetése és a szerverarchitektúra finomhangolása vezethet a legkönnyebben még jobb teljesítményhez.
  • A Magento 2 CE-t a paramétereivel éppúgy a közepes méretű vállalatokat célozza meg, mint a Magento 1EE. Funkcionális szempontból nézve hiányzik belőle néhány olyan vállalati funkció, mint a vásárló hitelrendszer és  jutalompontok kezelése, verziókezelés vagy fejlett tartalomkezelés, de ami a szigorúan vett teljesítményt illeti, egy lapon említhető a Magento 1 EE-vel, sőt a Varnish-támogatás révén még meg is előzi. A teljesítmény növelésére a néhány magától értetődő módszer a már meglévő lehetőségek és beállítások minél teljesebb kiaknázása, a szerverarchitektúra testre szabása vagy akár az Elasticsearch illetve Solr bevezetése.

Magento 2 EE a közepesnél nagyobb vállalatok számára is hatékony alternatívát kíván nyújtani a felhő alapú szervermegoldások és nyújtotta lehetőségek kiaknázásával.

 

Milyen gyakori hibákat lehet egy nagy méretű katalógus kezelése esetén a Magentóval elkövetni?

 

A fentebb  említett szempontokon túl szeretnénk még néhány olyan további körülményt említeni, amelyek  figyelmen kívül hagyása gyakori problémaforrás lehet egy komolyabb forgalmat bonyolító és nagy számú terméket kezelő Magento webshopban.

 

  • Underscaling ‒ Talán a legfontosabb tanács, hogy mindig megfelelő erőforrás tartalék legyen biztosítva a rendszer számára, és fel legyünk arra készülve, hogy szükséges esetben tovább erőforrásokat biztosítsunk. Már a fejlesztés során is célszerű teljesítménytesztekkel meggyőződni arról, hogy a webshop képes az elvárásoknak megfelelni.
  • Túl sok vagy gyenge minőségű külső modul  ‒  tisztában kell lennünk azzal, hogy a harmadik féltől származó modulok nincsenek minden esetben nagy méretű termékkatalógusokra optimalizálva. Egy modul tervezése során akár egy apró figyelmetlenség is katasztrofális lehet egy ilyen webshop teljesítményére nézve.
  • Széles körű és jól beállított  monitorozás hiánya ‒ Megfelelő rendszermonitorozás nélkül lehetetlen időben felismerni és kezelni a rendszer problémás területeit.

Források:

 

Összefoglalás A Magento a kezdetek óta óriási fejlődésen ment keresztül, és mára a Magento 2 megjelenésével eljutott odáig, hogy nemcsak a funkciókban leggazdagabb, de minden bizonnyal a legjobb teljesítményre képes webshop is egyben. Kellő szakértelemmel kezelve és biztosítva számára a megfelelő erőforrásokat, tetemes méretű katalógusokat is képes sikerrel kezelni.

 

Magento frontend sebesség gyorsítás és mérése

Tartalom

  • A gyorsaság arányos a bevétellel
  • Oldalsebesség hatása a keresési helyezésekre
  • Frontend gyorsítás a Magento-ban
    • Szerveroldal
    • Varnish
    • Statikus tartalmak – JavaScript, CSS fájlok és képek
    • Frontend optimalizálása a design függvényében
    • Képek méretének optimalizálása
    • Megjelenítést gátló elemek minimalizálása
    • Szerveroldali tömörítés engedélyezése
    • HTML, CSS, JavaScript lekicsinyítése
  • Befejezés

 

Induljunk ki abból, hogy rákeresel valami kifejezésre a weben, és a kiszemelt oldal, amire rákattintottál lassan töltődik be. A következő kérdésekre kell választ adni magadban:

 

  • Mennyi idő után fogod azt mondani, hogy nem vársz tovább, és inkább visszalépsz a keresőoldalra?
  • Mennyire szívesen látogatsz vissza később a kérdéses oldalra, ha tudod, hogy nagyon lassan töltődik be?
  • Milyen bizalommal ajánlod az ismerőseidnek az adott oldalt?
  • Mi fog akkor történni, ha egy olyan szituációban vagy, ahol kénytelen vagy a mobilodat használni böngészésre és azonnal el kellene intézned az adott dolgot?

 

A válaszok egyértelműek, és mint weboldal, illetve webshop tulajdonos, pontosan ezeket a problémákat kell elkerülnöd azért, hogy több látogató használja a te oldaladat.

A céged presztízse múlik azon, hogy milyen gyorsan töltődik be az oldalad, ráadásul, ha lassú a betöltés, akkor nem is fognak visszatérni, keresnek másik hasonló oldalt, ahol a felhasználói élmény számukra sokkal jobb.

A sebesség a weboldalaknál mindig is nagyon fontos tényező volt, ám az idő előre haladtával az oldalakkal szemben támasztott követelmények is egyre komolyabbak.

A 2011-es adatok például így festettek:

 

oldalsebesség

 

Mára azonban az oldalaknak már sokkal gyorsabban kell betöltődniük.

A Google által a webmestereknek készült videóban kiderül, hogy egy webshopnak 2016-ban elfogadott érték 2 másodperc, viszont a Google-nél a jónak számító idő a 0,5 másodperc.

 

 

A Financial Times idei kimutatása szerint a következő tendencia figyelhető meg a cikkek olvasottságánál:

 

oldalak betöltési ideje

 

Vagyis jól megfigyelhető, hogy ha gyorsabb a konkurenciánál az oldalunk, akkor előnyre tehetünk szert, de ez természetesen fordítva is igaz.

A következő statisztika azt szemlélteti, hogy melyek azok a webshopokban problémás részek, amelyeket az Egyesült Királyságban nehezményeznek (Econsultancy, 2012).

 

területi problémák

 

Tisztán látszik, hogy a betöltési idő a megkérdezettek első számú problémája, mintegy 66,8%-uk nincs vele megelégedve.

Néhány további hasznos tudnivaló az oldal gyorsaságával kapcsolatban:

  • Ha 3 másodpercnél tovább kell várni az oldal betöltésére, akkor a felhasználók 40%-a inkább meg sem várja
  • Egy átlagos felhasználó mindössze 2,078 másodpercet hajlandó várni egy oldal betöltésére
  • Ha az oldal 1-2 másodperc alatt betöltődik, az 2%-os látogatószám növekedést eredményez
  • Ha 1 másodperc alatt teljesül a betöltés, akkor 4,6%-os a javulás

 

A gyorsaság arányos a bevétellel

 

Általánosságban elmondható, hogy 1 másodpercnyi oldal gyorsulás átlagosan 7%-os növekedést eredményez a konverzióban.

Megjegyzés: Akkor történik konverzió, ha valaki a hirdetésre kattint, majd olyan műveletet hajt végre, amelyet Ön a vállalkozás szempontjából értékesnek határozott meg. Ilyen lehet például az online vásárlás vagy a bolt telefonos megkeresése.

 

Ez a webshopok esetében természetesen a számokban is megmutatkozik. Érdekesség, hogy a Walmart és az Amazon egymástól függetlenül, de rájöttek, hogyha 0,1 másodperccel tudnak gyorsítani az oldal betöltésén, akkor az 1%-os növekedést jelent a bevételeikben – ekkora cégeknél az 1% is óriási pénz!

 

Néhány adat a webshopok esetében:

  • a felhasználók 83%-a elvárja, hogy a weboldal 3 másodperc alatt töltődjön be
  • ha 3 másodpercnél többet kell várnia, akkor a felhasználók 44%-a elpártol az oldaltól
  • 79% ezek után megfontolja, hogy egyáltalán visszatérjen-e az oldalra
  • 46% pedig még el is meséli az ismerőseinek az érzéseit ezzel kapcsolatban

 

Érdemes elgondolkodni azon, hogy növeljük az oldalunk sebességét, hiszen, másodpercenként általánosságban 7%-os növekedést érhetünk el, amit ha a napi bevételünk 100 000 Ft, akkor éves szinten megközelítőleg 2 500 000 Ft plusz bevételre tehetünk szert (100 000 * 0,07 * 365).

 

Oldalsebesség hatása a keresési helyezésekre

 

John Mueller SEO szakértő utánajárt a témának, és egyik cikkében kifejtette, hogy a lassú oldalak hátrébb vannak sorolva, viszont a gyors weboldalak között már nem játszik nagy szerepet pár ezredmásodpercnyi különbség.

 

Két fontos tényezőt kell megvizsgálni a weboldalak gyorsaságát illetően:

Az egyik – amit a felhasználó érez, azaz számára milyen gyorsan jelenik meg a tartalom,

A másik – ami a Google számára fontosabb –, hogy meg tudja különböztetni a lassú weboldalakat a normális sebességűektől. Kihangsúlyozta azt is, hogy minél gyorsabb az oldalunk, annál több felhasználó használja, így sokkal több aloldalt tudnak megtekinteni adott idő alatt, így több információt ismernek meg.

 

Frontend gyorsítás a Magento-ban

 

Mivel a legelterjedtebb keresőportál a Google, ezért célszerű az általa támasztott elvárásoknak megfelelni, amit legjobban a saját sebességmérő alkalmazásában lehet kipróbálni, és az ott kapott válaszok alapján javítani rajta: Google PageSpeed

Első projektünk, amiben megvizsgáltuk, hogy mivel tudjuk gyorsítani az oldal betöltési sebességét a Fradi webshop-ja, ezen a példán keresztül mutatom be a lehetőségeket:

 

Szerveroldal

 

Természetesen ahhoz, hogy a frontend tartalmak gyorsabban legyenek láthatóak a böngészőkben, a szerveroldalon is végre kell hajtani bizonyos optimalizálási folyamatokat annak érdekében, hogy a válaszidő a lehető legrövidebb legyen.

 

Varnish

 

Az egyik legelterjedtebb gyorsítótár (cache) megoldás a dinamikus tartalmak kiszolgálására, amiről már egy korábbi cikkünkben részletesen írtunk.

 

Statikus tartalmak – JavaScript, CSS fájlok és képek

 

Ezek gyorsítótárazásához az AWS CDN megoldását használjuk.

 

Frontend optimalizálása a design függvényében

 

A mai trendeknek megfelelően reszponzív design esetén a megjelenő képek mérete a böngésző méretétől függenek. A következő példában szemléltetem is, látszik, hogy a design és a sitebuild eltér az egyes töréspontok után (az AionHill a Bootstrap töréspontjait veszi alapul az általunk készítendő oldalak megvalósításakor):

 

webshop-design-1

1. ábra – minimum szélesség 1200 px

 

webshop-design-2

2. ábra- minimum szélesség 992 px

 

webshop-design-3

3. ábra – minimum szélesség 768 px

webshop-design-4

4. ábra – maximális szélesség 768 px

 

 

Fontos, hogy a megjelenő kép mérete megegyezzen annak a területnek a méretével, ahol azt megjelenítjük. Ez nem jelentene gondot akkor, ha mellőzzük a reszponzivitást, hiszen a Magento-ban le lehet kérdezni a képek átméretezett példányát:

 

$this->helper('catalog/image')->init($_product, 'small_image')->resize(710, 710);

 

Vagyis meg kell oldanunk, hogy mindig az adott böngészőmérethez jelenítse meg az átméretezett képet. Erre a legmegfelelőbb megoldás a <picture> HTML tag

A lényege, hogy meg lehet adni, hogy milyen felbontásoknál melyik kép jelenjen meg, végül pedig magát a kép <img> tag-et, hogyha a böngésző nem támogatná még ezt az új bevezetett szabványt:

<picture>
 <source srcset="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(360, 365); ?>" media="(min-width:1200px)">
 <source srcset="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(293, 297); ?>" media="(min-width:992px)">
 <source srcset="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(710, 710); ?>" media="(min-width:768px)">
<source srcset="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(710, 710); ?>" media="(min-width:300px)">
 <img class="img-responsive"
 src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(360, 365); ?>"
 alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>"/>
</picture>

 

Képek méretének optimalizálása

 

A weboldalakra feltöltött képek túlnyomó többségénél megfigyelhető, hogy minőségromlás nélkül bizonyos programokkal lekicsinyíthető a képek mérete. Erre a Google is figyel, és jelzi a vizsgálatkor, hogy melyek azok a képek, ahol ezt meg kell tenni.

 

webshop-kep-optimalizalas

 

Erre mi nem készítettünk saját modult, mert a piacon fellelhető sok ingyenes Magento bővítménynek köszönhetően ez feladat könnyen megoldható. A választásunk az Image Optimizer for Magento-ra esett, ami egy ingyenes és teljesen jól használható megoldás erre a problémára.

A lényege, hogy a média, skin és frontend mappákban fellelhető képeket kigyűjti, és utána cron segítségével kötegelve optimalizálja a szerveren található képmanipuláló könyvtárak segítségével (jpegoptim, optipng).

 

Megjelenítést gátló elemek minimalizálása

 

Ez a gyakorlatban azt jelenti, hogy ha a JavaScript és CSS fájljaink száma nagy, akkor azoknak a betöltése sokkal több időt vesz igénybe, mert a fájlok betöltésével megvárja a másikra adott választ. Ennek a legmegfelelőbb mérése a Chrome-ban a developer tools, ahol összefűzés nélkül a következő eredményt kapjuk:

 

css-developer-tools-fajl-osszefuzes-nelkul

 

Látszik, hogy rengeteg idő, míg az összes fájl betöltődik. Ha a Magento adminisztrációs felületén bekapcsoljuk a fájlok összefűzését, akkor ugyanez az oldal a következő eredményt adja:

 

fajl-keptomorites-webshop

 

A felhasználó szemszögéből ugyanaz az eredmény, viszont jóval kevesebb fájlból dolgozik. Ez a lehetőség Magento alapfunkcionalitás, és ha jól írták meg a fejlesztők a JavaScript osztályokat, eljárásokat, akkor nem is lehet gond az összefűzésnél.

Bekapcsolni a System/Configuration/Developer menüpontok alatt lehet:

 

magento-developer-menu-fajl-osszefuzes

 

Szerveroldali tömörítés engedélyezése

 

 

A PageSpeed részletesen leírja, hogy egyes webszerverek esetében mi a teendő, milyen modulokat kell telepíteni ahhoz, hogy a tömörítés be legyen kapcsolva

Tesztelni könnyedén lehet, például Chrome esetében inspector módban (Ctrl+Shift+i) a network fülön a HTML oldal header (fejléc) részében megtalálható a következő:

 

szerver-oldali-tomorites-webshop

 

Végezetül a HTML, CSS, JavaScript lekicsinyítése

Távolítsuk el a felesleges karaktereket mindhárom oldalelemből, mert így csökkentjük a válasz méretét, így növeljük a válasz sebességét.

Magento-hoz ismételten az Aptrian termékét választottuk (Minify HTML CSS JS for Magento), ami a feltelepítés után egy egyszerű adminisztrációs beállítás után egy gomb megnyomásával már végre is hajtja azokat a módosításokat a fájlokon, amik növelhetik a méretét.

Fontos megemlítenem, hogy itt nem a javascript kicsinyítéséről/titkosításáról van szó, hanem a felesleges elemek eltávolításáról:

A Magento-s Validator osztály egy kiragadott része:

 

magento-validator-osztaly

 

Ezt a modul átalakítja:

 

magento-validator-osztaly-modul-atalakitas

 

Rövidebb tartalom, kevesebb felesleges karakter, gyorsabb betöltődés.

 

 

Összegzés

Az oldalbetöltési sebesség növelése egyre fontosabb a weboldalak, különösen a webshopok, számára, hiszen a látogatók is egyre többet várnak el, egyre jobb felhasználói élményt szeretnének.

Ebben a cikkben leírtam, hogyan lehet a Magento 1.x-nél javítani az oldalbetöltési sebességet, amely során különböző megoldásokat javasoltam.

Ami a Magento 2 rendszert illeti, úgy tervezem, az ezen a platformon működő webshopok frontend gyorsításával kapcsolatban is megjelentetek egy blogcikket, hogy teljes legyen a kép.

Magento 2.0 modul fejlesztés lépésről lépésre – 4. rész (Knockout JS)

Tartalom:

  • Mi az a Knockout.js?
  • Miért kell / érdemes használni és mire jó?
  • Alap példa modul felépítése
  • Block-ok és layout létrehozása
  • Knockout JS használata PHTML template fájlban
  • Saját CustomerData osztály létrehozása és implementálása
  • Knockout JS használata HTML template fájlként

Mi az a Knockout.js?

A Knockout.js egy nyílt forráskódú egyszerűsített dinamikus javascript, mely egy Model-View-View Model (MVVM) rendszer/framework.

 

Miért kell / érdemes használni és mire jó?

Természetesen nem kell használni, viszont mivel a Magento 2.0 szerves részét képezi a full page cache használata miatt is, így a saját modulunkban megvalósítandó üzleti logika alapján célszerű elgondolkozni a használatán a fejlesztés megkezdése előtt. Anélkül, hogy különálló bonyolult javascript-ek készítenénk saját modulunkban, egy könnyű megoldással férhetünk hozzá customer, product, order stb. adatokhoz a frontenden és kezelhetjük azokat.

Alap példa modul felépítése

 

A jelenlegi cikkben is a már korábban használt alap példa modult fogjuk használni. A Magento 2.0-ban a Knockout JS jelentős szerepet kap, így érdemes vele megismerkedni.

 

Mivel korábbi cikkünk az alap modul felépítésére már kitért, most csak a modul felépítése kerül bemutatásra.

 

magento 2 modul szerkezet

 

Block-ok és layout létrehozása

 

A példához egy block-ot hozunk létre és két külön template fájlt, amiben két különböző módszerrel használjuk a Knockout JS-t. Az első példában magában a template fájlban használjuk a Knockout JS-t, míg a másodikban ennek segítségével egy másik HTML template fájlt implementálunk vagy úgy is fogalmazhatnánk, hogy töltünk be. A két külön példához első lépésben egy layout fájlt hozunk létre, és aszerint, hogy melyik block-ot használjuk, most az egyszerűség kedvéért csak kikommentezzük a megfelelőt.

Ehhez szükségünk lesz egy default.xml fájlra, ami az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/view/frontend/layout/default.xml. A fájl tartalma:

 

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
     <body>
         <referenceBlock name="sidebar.additional">
             <!-- First sample -->
             <block class="Aion\Sample\Block\Sample" name="aion.sample.knockout.sidebar" template="Aion_Sample::sidebar.phtml" after="wishlist_sidebar"/>
             <!-- Second Sample -->
             <!--<block class="Aion\Sample\Block\Sample" name="aion.sample.knockout.sidebar.second" template="Aion_Sample::second-sidebar.phtml" after="wishlist_sidebar"/>-->
         </referenceBlock>
     </body>
 </page>

 

A layout fájlban a példa kedvéért a saját block-unk és a hozzá tartozó template fájl az oldalsáv (sidebar) alatti részen fog megjelenni (<referenceBlock name=”sidebar.additional”>).

 

A következő lépésben a block osztály kerül létrehozásra, ami a fenti layout-ban is látható. Az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/Block/Sample.php. A fájl tartalma:

 

<?php
 namespace Aion\Sample\Block;
 use Magento\Framework\View\Element\Template;
 use Aion\Sample\Helper\Data as DataHelper;
 
 class Sample extends Template
 {
     /**
      * @var DataHelper
      */
     protected $_helper;
 
     /**
      * @param Template\Context $context
      * @param DataHelper $dataHelper
      * @param array $data
      */
     public function __construct(
         Template\Context $context,
         DataHelper $dataHelper,
         array $data = []
     ) {
         $this->_helper = $dataHelper;
         parent::__construct($context, $data);
         $this->_isScopePrivate = true;
     }
 
     /**
      * Get extension helper
      *
      * @return DataHelper
      */
     public function getExtensionHelper()
     {
         return $this->_helper;
     }
 
     /**
      * Sample items for example
      *
      * @return array
      */
     public function getInitSecondItems()
     {
         $sampleData = $this->_helper->getSampleProductNames();
 
         return $sampleData;
     }
 }

 

A block-ban látható getInitSecondItems() függvény a második példában fog szerepet kapni, így erre később térünk ki.

 

Knockout JS használata PHTML template fájlban

 

A Knockout JS bemutatásához szükséges még a megfelelő javascript fájlok elkészítése is. Első lépésben definiáljuk a saját modulunkhoz tartozó javascript fájlt, amit a requirejs-config.js-ban teszünk meg. Ez az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/frontend/requirejs-config.js. A fájl tartalma:

var config = {
     map: {
         '*': {
             sample: 'Aion_Sample/js/view/sample-sidebar'
         }
     }
 };

 

Itt adjunk meg, hogy a modulunkban hol található a saját javascript fájlunk.

 

Természetesen szükség van a sample-sidebar.js fájlra is. Ez az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/frontend/web/js/view/sample-sidebar.js. A fájl tartalma:

 

define([
     'ko',
     'uiComponent',
     'Magento_Customer/js/customer-data',
     'mage/translate'
 ], function (ko, Component, customerData, $t) {
     'use strict';
     return Component.extend({
         // Second example
         defaults: {
             template: 'Aion_Sample/second-sidebar'
         },
         displayContent: ko.observable(true),
         initialize: function () {
             this._super();
             this.sample = customerData.get('sample');
             // Second example
             this.someText = $t('Sample content with template.');
             // Second example. foreach examples
             this._showItems();
             // Second example, foreach example
             this._showMonths();
             // Second example, other foreach example
             this._showCategories();
             // Second example and another foreach example
             this._showMyItems();
         },
         getInfo: function() {
             return this.sample().info || this.initFullname || customerData.get('customer')().fullname;
         },
         getCartItemsCountText: function () {
             return this.sample().cart_items_text;
         },
         getCartItemsCount: function () {
             return this.sample().cart_count;
         },
         getHint: function() {
             return this.sample().hint || this.initHint;
         },
         _showItems: function() {
             var self = this;
             if (typeof this.initSampleData !== "undefined") {
                 self.sampleItems = JSON.parse(this.initSampleData);
             }
         },
         _showMonths: function() {
             var self = this;
             self.months = [ 'Jan', 'Feb', 'Mar', 'etc' ];
         },
         _showCategories: function() {
             var self = this;
             self.categories = [
                 { name: 'Fruit', items: [ 'Apple', 'Orange', 'Banana' ] },
                 { name: 'Vegetables', items: [ 'Celery', 'Corn', 'Spinach' ] }
             ];
         },
         _showMyItems: function() {
             var self = this;
             self.myItems = [ 'First', 'Second', 'Third' ]
         }
     });
 });

 

A példában szereplő függvények előtt jelzésre került, hogy melyek tartoznak a később bemutatandó második példához. Ezen objektumok és függvények előtt a //Second example látható.

Nézzük meg egy kicsit a működést!

A javascript a Magento 2.0-ban lévő uiComponent objektumot terjeszti ki, majd definiálásra kerül a saját sample objektum is, mely a CustomerData része lesz (this.sample = customerData.get (‘sample’);). Még négy függvény kerül a példában definiálásra, melyeket a template fájl fogunk használni.

 

Függvények:

  • getInfo() – a vevő (customer) nevének megjelenítésért felelős.
  • getCartItemsCountText() – string példa szöveggel, melynek része a kosárban lévő termékek száma.
  • getCartItemsCount() – integer, ami a kosárban lévő termékek számát tartalmazza (nem az összmennyiséget, sum qty)
  • getHint() – string, csak információt tartalmaz

 

Az említett függvények által visszaadott adatokat a 4. pontban leírt Sample osztály fogja kezelni.

 

Nézzük a block-hoz tartozó template fájl tartalmát, ami az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/frontend/templates/sidebar.phtml. A fájl tartalma:

 

<?php
 $sampleHelper = $block->getExtensionHelper();
 $initFullName = $sampleHelper->getIsLoggedIn() ? $sampleHelper->getCustomerFullName() : __('You are logged out.');
 ?>
 <?php if ($sampleHelper->isEnabled()) : ?>
     <div class="block block-compare block-aion-sample" data-bind="scope: 'sample'">
         <div class="block-title">
             <strong><?php /* @escapeNotVerified */ echo __('Aion Sample Block'); ?></strong>
         </div>
         <div class="block-content">
             <strong class="subtitle" style="display: inline-block">
                 <?php /* @escapeNotVerified */ echo __('Customer Info:') ?>
             </strong>
             <p class="description">
                 <span data-bind="text: getInfo()"></span><br />
             </p>
             <p class="description">
                 <!-- ko if: getCartItemsCount() -->
                 <strong class="subtitle" style="display: inline-block">
                     <?php /* @escapeNotVerified */ echo __('Cart Info:') ?>
                 </strong>
                 <br />
                 <span data-bind="text: getCartItemsCountText()"></span>
                 <!-- /ko -->
             </p>
             <p class="hint"><small data-bind="text: getHint()"></small></p>
         </div>
     </div>
     <script type="text/x-magento-init">
     { "*": {
             "Magento_Ui/js/core/app": {
                 "components": {
                     "sample": {
                         "component": "Aion_Sample/js/view/sample-sidebar",
                         "initHint": "<?php echo __('(Refresh automatically after cart modification)') ?>",
                         "initFullname": "<?php echo $initFullName ?>"
                     }
                 }
             }
         }
     }
     </script>
 <?php endif; ?>

 

Lényegében itt látható a Knockout JS használata. Nézzük, részletesen hol használjuk, és hogyan működik.

 

<span data-bind=”text: getInfo()”></span>

A javascript fájlban definiált getInfo() függvény által visszaadott string fog megjelenni a <span> tag-ben.

 

Knockout JS:

 

<!– ko if: getCartItemsCount() –>

<strong class=”subtitle” style=”display: inline-block”>

<?php /* @escapeNotVerified */ echo __(‘Cart Info:’) ?>

</strong>

<br />

<span data-bind=”text: getCartItemsCountText()”></span>

<!– /ko –>

 

Amennyiben a javascript fájlban definiált getCartItemsCount() függvény értéke nem 0, akkor megjelenítésre kerül az if szekcióban lévő rész. A getCartItemsCountText() függvény pedig egy string-gel tölti ki a <span> tag-et.

 

<p class=”hint”><small data-bind=”text: getHint()”></small></p>

A getHint() függvény egy string-gel tölti ki a <small> tag-et.

 

Nézzük meg, hogy ezek után hogyan jelenik meg az elkészült block a Magento 2.0 sidebar részében.

 

magento 2 modul fejlesztés sidebar

 

Hogyan módosíthatjuk ezeket az adatokat különböző felhasználói interakciókra? Erre kapunk választ a következő pontban.

 

Saját CustomerData osztály létrehozása és implementálása

 

Ahhoz, hogy a fenti block-unk és annak tartalma interaktívan módosuljon, szükségünk van egy saját CustomerData osztályra, mely a javascript-ben definiált sample osztályt szolgálja ki adatokkal.

Az osztály az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/CustomerData/Sample.php. A fájl tartalma:

 

<?php
 namespace Aion\Sample\CustomerData;
 use Magento\Customer\CustomerData\SectionSourceInterface;
 use Aion\Sample\Helper\Data as DataHelper;
 /**
  * Sample section
  */
 class Sample implements SectionSourceInterface
 {
     /**
      * @var DataHelper
      *
     protected $_helper;
 
     /**
      * @param DataHelper $dataHelper
      */
     public function __construct(
         DataHelper $dataHelper
     ) {
         $this->_helper = $dataHelper;
     }
 
     /**
      * {@inheritdoc}
      */
     public function getSectionData()
     {
         $sampleData = $this->_getSampleData();

         return $sampleData;
     }
 
     /**
      * First sample data example
      *
      * @return array
      */
     protected function _getSampleData()
     {
         $sampleData = [
             'info' => __('You are logged out.')
         ];
         $isLoggedIn = $this->_helper->getIsLoggedIn();
         if ($isLoggedIn) {
             $sampleData = [
                 'info' => __('You are logged in as: %1', $this->_helper->getCustomerFullName())
             ];
         }
 
         $cartItemsCount = $this->_helper->getCartItemCount();
         $sampleData = array_merge(
             $sampleData,
             [
                 'cart_items_text' => __('You have %1 item(s) in your cart', $cartItemsCount),
                 'cart_count' => (int)$cartItemsCount,
                 'hint' => __('(Refresh automatically after cart modification)')
             ]
         );
 
         return $sampleData;
     }
 }

 

Az osztályban a getSectionData() függvény szolgálja ki adatokkal a javascript-ben definiált sample osztályt. Itt fontos megjegyezni, hogy a két osztályt célszerű azonos néven elnevezni a PHP és Javascript kódban.

A _getSampleData egy tömbbel tér vissza, melynek kulcsai megegyeznek a javascript kódban hasznát értékekkel. Itt implementálhatjuk a szükséges üzleti logikát. A példa kedvéért itt csak a customer teljes nevének átadása és kosár elemek számolása történik meg.

Szükséges még definiálni a CustomerData osztályt is, hogy a Magento 2.0 rendszer „tudjon” róla. Ezt a di.xml fájlban kell megadnunk, ami az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/etc/frontend/di.xml. A fájl tartalma:

 

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
     <type name="Magento\Customer\CustomerData\SectionPoolInterface">
         <arguments>
             <argument name="sectionSourceMap" xsi:type="array">
                 <item name="sample" xsi:type="string">Aion\Sample\CustomerData\Sample</item>
             </argument>
         </arguments>
     </type>
 </config>

 

A következő fontos lépés, hogy a Sample osztályban definiált getSectionData() függvény mikor fusson le, milyen felhasználói interakcióra. Ehhez szükséges egy xml fájlban megadni ezen controller-ek listáját.

 

Ezt a sections.xml fájlban kell definiálnunk, ami az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/etc/frontend/sections.xml. A fájl tartalma:

 

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
     <action name="checkout/cart/add">
         <section name="sample"/>
     </action>
     <action name="checkout/cart/delete">
         <section name="sample"/>
     </action>
     <action name="checkout/cart/updatePost">
         <section name="sample"/>
     </action>
     <action name="checkout/cart/updateItemOptions">
         <section name="sample"/>
     </action>
     <action name="checkout/sidebar/removeItem">
         <section name="sample"/>
     </action>
     <action name="checkout/sidebar/updateItemQty">
         <section name="sample"/>
     </action>
 </config>

 

Az xml-ben látható, milyen controller action-öket definiáltunk. Ezek a termék kosárba helyezése, törlése, termék számának frissítése stb.

De mit is jelent pontosan ez?

Miután elkészültünk a fenti Sample osztállyal, az említett getSectionData() függvény le fog futni ezen controller action-ök futása esetén, és a frontend-en megjelenő block-unk automatikusan ajax-szal frissülni fog a getSectionData() függvény által visszaadott adatokkal. Mindez anélkül történik, hogy bármilyen ajax függvényt és kezelést definiáltunk, írtunk volna a javascript fájlunkban.

 

Bejelentkezett felhasználóval így néz ki a block-unk miután egy tetszőleges terméket a kosárba helyeztünk:

 

magento 2 modul fejlesztés kosár

 

 

Az ajax hívásban visszakapott objektum tartalma:

 

magento 2 modul fejlesztés ajax tartalom

 

 

 

Knockout JS használata HTML template file-ként

 

Az előző példában a phtml fájlban használtuk közvetlenül a Knockout JS-t. A második esetben is ezt fogjuk alkalmazni, azonban egy külön html template fájlt használunk az adatok megjelenítésére.

Ehhez első lépésben egy második phtml példa fájlt hozunk létre. A fájl a modulunkban az app/code/Aion/Sample/view/frontend/templates/second-sidebar.phtml. A fájl tartalma:

 

<?php
 $sampleHelper = $block->getExtensionHelper()
 ?>
 <?php if ($sampleHelper->isEnabled()) : ?>
     <div class="block block-compare block-aion-sample" data-bind="scope: 'sample'">
         <div class="block-title">
             <strong><?php /* @escapeNotVerified */ echo __('Aion Second Sample Block'); ?></strong>
         </div>
         <div class="block-content">
             <!-- ko template: getTemplate() -->
             <!-- /ko -->
         </div>
     </div>
     <script type="text/x-magento-init">
     {
         "*": {
             "Magento_Ui/js/core/app": {
                 "components": {
                     "sample": {
                         "component": "Aion_Sample/js/view/sample-sidebar",
                         "initSampleData": "<?php echo addslashes(json_encode($block->getInitSecondItems())) ?>"
                     }
                 }
             }
         }
     }
     </script>
 <?php endif; ?>

 

Az első példában bemutatott phtml fájlhoz képest a különbség jól látható. A tartalmi részben kerül implementálásra a html template behívása:

<!– ko template: getTemplate() –>

<!– /ko –>

 

Itt fontos visszatérni a cikk elején bemutatott sample-sidebar.js fájlra és figyelembe venni a //Second sample kód részeket, mert a második példánkat ezek kezelik. Emellett az 1. pontban részletezett default.xml fájlban a második block-ot használjuk csak:

<block class=”Aion\Sample\Block\Sample” name=”aion.sample.knockout.sidebar.second” template=”Aion_Sample::second-sidebar.phtml” after=”wishlist_sidebar”/>

Az elsőt kikommentezzük.

 

A következő lépésben létrehozzuk a HTML fájlt, ami az app/code/Aion/Sample/view/frontend/web/template/second-sidebar.html. A fájl tartalma:

 

<!-- ko if: displayContent() -->
     <p data-bind="text: someText"></p>
 
     <h4>Items Form Block Class</h4>
     <ul data-bind="foreach: sampleItems">
         <li>
             <span data-bind="text: $data"> </span>
         </li>
     </ul>
 
     <h4>Months</h4>
     <ul data-bind="foreach: months">
         <li>
             <span data-bind="text: $data"> </span>
         </li>
     </ul>
 
     <h4>Categories</h4>
     <ol data-bind="foreach: { data: categories, as: 'category' }">
         <li>
             <ul data-bind="foreach: { data: items, as: 'item' }">
                 <li>
                     <span data-bind="text: category.name"></span>:
                     <span data-bind="text: item"></span>
                 </li>
             </ul>
         </li>
     </ol>
 
     <h4>My Items</h4>
     <ul>
         <!-- ko foreach: myItems -->
         <li>Item name: <span data-bind="text: $data"></span></li>
         <!-- /ko -->
     </ul>
 
 <!-- /ko -->
 <!-- ko ifnot: displayContent() -->
     <p class="empty-text" data-bind="text: $t('Content is empty.')"></p>
 <!-- /ko -->

 

A sample-sidebar.js-t elemezve nézzük át a HTML template fájl működését. Elsőként definiálva maga a template fájl és egy true érték, mely az if feltételben szerepel. Természetesen ezt a szükséges üzleti logika szerint lehet módosítani.

 

// Second example

defaults: {

template: ‘Aion_Sample/second-sidebar’

},

displayContent: ko.observable(true),

 

A példa adatokat szolgáló függvények automatikusan lefutnak az inicializálás során:

 

// Second example

this.someText = $t(‘Sample content with template.’);

// Second example. foreach examples

this._showItems();

// Second example, foreach example

this._showMonths();

// Second example, other foreach example

this._showCategories();

// Second example and another foreach example

this._showMyItems();

 

Ezek közül ‒ a példa céljából ‒ csak egyetlen adatai érkeznek a block osztályból (app/code/Aion/Sample/Block/Sample.php). Az átadása a phtml fájlban történik:

 

“initSampleData”: “<?php echo addslashes(json_encode($block->getInitSecondItems())) ?>”

 

A getInitSecondItems() függvény a helper osztályban van megvalósítva:

 

/**
  * Get sample product names
  *
  * @return array
  */
 public function getSampleProductNames()
 {
     $sampleData = [];
     /* @var $product Product */
     $product = $this->_productFactory->create();
     /* @var $collection Collection */
     $collection = $product->getCollection();
     $collection->setVisibility($this->_catalogProductVisibility->getVisibleInCatalogIds());
     $collection->addStoreFilter()->addAttributeToSelect(
         ['name']
     );
     $collection->getSelect()->orderRand('e.entity_id');
     $collection->setPageSize(
         5
     )->setCurPage(
         1
     )->toArray(['name']);
 
     /* @var $item Product */
     foreach ($collection as $item) {
         $sampleData[] = $item->getName();
     }
 
     return $sampleData;
 }

 

A látható termékek közül véletlenszerűen kiválaszt ötöt és ezek neveit egy tömbként adja át.

 

A sample-sidebar.js fájlban inicializált többi függvény egyszerű példa adatokat hoz létre, hogy a HTML template fájlban ezeken végig iterálva segítse a működés megértését. A második példa block-unk mindezek után így jelenik meg a forntend-en:

 

magento 2 modul fejlesztés frontend

 

ÖsszegzésA cikkben megpróbáltuk bemutatni a Knockout JS használatát egyedi modul fejlesztéshez. A Magento 2.0-ban nagyon sok helyen van alkalmazva customer, order, cart, wishlist és egyéb adatok megjelenítése céljából a frontenden.

 

Magento 2 modul fejlesztés lépésről lépésre – 3. rész (Observer-ek)

Ebben a cikkben az alábbiakról fogok írni:

  • Alap példa modul felépítése
  • Observer-ek létrehozása és implementálása

 

1) Alap példa modul felépítése

 

Az előző cikkekben (1. rész, 2. rész) megismerkedtünk egy példa Magento 2.0 modul elkészítésével, a hozzá tartozó adatbázis táblák, admin táblázat (grid), a modulhoz tartozó adatok létrehozásával, editálásával, mentésével és törlésével. Most egy másik egyszerű Magento 2.0 modulban az Observer-ek működésével foglalkozunk.

Ehhez első lépésben elkészítünk egy alap példa modult. Mivel korábbi cikkünk erre már kitért, most csak a modul felépítése kerül bemutatásra.

 

magento 2 modul szerkezet

 

2) Observer-ek létrehozása és implementálása

 

A Magento 2.0 példa modulban két Observer-t hozunk létre, melyeket két külön eseményre „kötünk” rá. A Magento 1.x modulok esetében egy Observer osztályban kerültek megvalósításra a különböző események során megvalósítandó függvények és azokban történő üzleti logikák. A Magento 2.0-ban minden egyes eseményhez külön saját Observer osztályt kell létrehozni, melyekben az execute(…) függvényben kerül az üzleti logika megvalósításra.

Mielőtt az Observer osztály létrehozásra kerül, definiálni kell, hogy melyik eseményre szeretnénk a saját üzleti logikánkat alkalmazni. Itt fontos eldönteni, hogy a frontend vagy az admin oldalon (adminhtml) szeretnénk használni, így a definíciós xml fájlt a megfelelő helyen kell elhelyezni.

Globálisan is el lehet helyezni, de célszerű ezt mindig külön választani. Első példában egy frontend oldali eseményre, az alap Magento 2.0 contact form (kapcsolat) elküldése után szeretnénk az elküldött adatokat „elkapni” a saját Observer osztályunkkal.

Ehhez szükségünk lesz egy events.xml fájlra, ami az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/etc/frontend/events.xml. A fájl tartalma:

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_postdispatch_contact_index_post">
        <observer name="aion_sample_post_capture" instance="Aion\Sample\Observer\CapturePost" />
    </event>
</config>

A fájl felépítése nagyon egyszerű. Az event tag-ben lévő name paraméterben kerül meghatározásra, hogy melyik eseményt szeretnénk „elkapni”.

Az esetünkben a Magento 2.0 alap Contact moduljában lévő post controller utáni esemény. Az event tag-en belül pedig definiáljuk az observer tag-ben a saját Observer osztályunkat, ami majd meghívásra kerül és egyedi név paramétert is adunk neki. Az event tag-ben egymás alatt több saját Observer-t is definiálhatunk ugyanezen eseményhez, illetve az xml fájlban több event tag-et is megadhatunk, ha más eseményekhez is szeretnénk további saját Observer-t használni.

Ezt követően a saját Observer osztályunkat kell létrehozni és megvalósítani benne a szükséges üzleti logikát. A fájl az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/Observer/CapturePost.php. A fájl tartalma:

<?php
namespace Aion\Sample\Observer;

use Magento\Framework\Event\ObserverInterface;
use Aion\Sample\Helper\Data as DataHelper;
use Psr\Log\LoggerInterface;
use Magento\Framework\Event\Observer;
use Magento\Customer\Model\Customer;
use Magento\Framework\Exception\LocalizedException;

class CapturePost implements ObserverInterface
{
    /**
     * Aion Sample helper
     *
     * @var DataHelper
     */
    protected $_helper;

    /**
     * @var LoggerInterface
     */
    protected $_logger;

    /**
     * Capture Post Observer constructor
     *
     * @param DataHelper $helper
     * @param LoggerInterface $logger
     */
    public function __construct(
        DataHelper $helper,
        LoggerInterface $logger
    ) {
        $this->_helper = $helper;
        $this->_logger = $logger;
    }

    /**
     * Sample post capture event handler
     *
     * @param Observer $observer
     * @return self
     */
    public function execute(Observer $observer)
    {
        if ($this->_helper->isEnabled()) {

            $controller = $observer->getEvent()->getControllerAction();
            $post = $controller->getRequest()->getPostValue();

            if ($post) {

                try {

                    $this->_logger->debug('CapturePostObserver');
                    $this->_logger->log(100, print_r($post, true));

                    // comment out to check data
                    //\Zend_Debug::dump($post);
                    //die();

                    // do some logic

                } catch (LocalizedException $e) {
                    $this->_logger->error($e->getMessage());
                } catch (\Exception $e) {
                    $this->_logger->critical($e);
                }

            }

        }

        return $this;
    }
}

Amennyiben a fent említett events.xml fájlban definiált esemény megtörténik, a CapturePost osztályban lévő execute függvény hajtódik végre. A függvény első lépésben megvizsgálja, hogy a saját modulunk engedélyezve van-e. Abban az esetben, ha engedélyezve van, az említett Magento 2.0 alap Contact form által elposztolt adatokat „elkapja”. Az egyszerűség kedvéért a példában csak logoljuk a tömböt a debug.log file-ban. Az így megkapott adatokat felhasználva megírhatjuk a saját üzleti logikánkat.

A második példában egy admin oldali eseménynél, az alap Magento 2.0 felhasználó mentés után szeretnénk az felhasználó (customer) objektumot és adatokat „elkapni” a saját Observer osztályunkkal.

Ehhez szükségünk lesz egy events.xml fájlra, ami az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/etc/adminhtml/events.xml. A fájl tartalma:

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_postdispatch_contact_index_post">
        <observer name="aion_sample_post_capture" instance="Aion\Sample\Observer\CaptureCustomer" />
    </event>
</config>

 

 

 

A fájl felépítése ugyanaz, mint az előző példában említett events.xml esetében, csak ezúttal az adminhtml könyvtár van elhelyezve, így a definiált CaptureCustomer osztály csak az admin scope-ban fog meghívódni a felhasználó mentés utáni eseményre (customer_save_commit_after).

 

Ezt követően az előző példához hasonlóan a saját Observer osztályunkat kell létrehozni és megvalósítani benne a szükséges üzleti logikát. A fájl az alábbi helyen található a példa modulunkban: app/code/Aion/Sample/Observer/CaptureCustomer.php. A fájl tartalma:

 

 

<?php
namespace Aion\Sample\Observer;

use Magento\Framework\Event\ObserverInterface;
use Aion\Sample\Helper\Data as DataHelper;
use Psr\Log\LoggerInterface;
use Magento\Framework\Event\Observer;
use Magento\Customer\Model\Customer;
use Magento\Framework\Exception\LocalizedException;

class CaptureCustomer implements ObserverInterface
{
    /**
     * Aion Sample helper
     *
     * @var DataHelper
     */
    protected $_helper;

    /**
     * @var LoggerInterface
     */
    protected $_logger;

    /**
     * Capture Customer Observer constructor
     *
     * @param DataHelper $helper
     * @param LoggerInterface $logger
     */
    public function __construct(
        DataHelper $helper,
        LoggerInterface $logger
    ) {
        $this->_helper = $helper;
        $this->_logger = $logger;
    }

    /**
     * Sample customer capture event handler
     *
     * @param Observer $observer
     * @return self
     */
    public function execute(Observer $observer)
    {
        if ($this->_helper->isEnabled()) {

            /* @var Customer $customer */
            $customer = $observer->getEvent()->getCustomer();

            if (!is_null($customer) && $customer->getEntityId()) {

                try {

                    $this->_logger->debug('CaptureCustomerObserver');
                    $this->_logger->log(100, print_r($customer->getData(), true));
                    // comment out to check data
                    //\Zend_Debug::dump($customer->getData());
                    //die();

                    // do some logic

                } catch (LocalizedException $e) {
                    $this->_logger->error($e->getMessage());
                } catch (\Exception $e) {
                    $this->_logger->critical($e);
                }

            }

        }

        return $this;
    }
}

 

Amennyiben a fent említett második events.xml file-ban definiált esemény megtörténik, a CaptureCustomer osztályban lévő execute függvény hajtódik végre. A függvény első lépésben megvizsgálja, hogy a saját modulunk engedélyezve van-e.

Abban az esetben, ha engedélyezve van, az említett Magento 2.0 admin felhasználó mentés után „elkapja” a customer objektumot. Az egyszerűség kedvéért a példában csak logoljuk az objektum adatait a debug.log file-ban. Az így megkapott objektumot és adatokat felhasználva megírhatjuk a saját üzleti logikánkat.

 

Összegzés

A cikkben két példával próbáltuk illusztrálni a Magento 2.0 rendszerben, hogyan kell saját egyedi modulunkban Observer-eket definiálni és megvalósítani különböző eseményekre a frontend és az admin oldalon.

 

Kódaudit és kódjavítási szempontok Magento projekteknél

Első lépés a Magento kódaudit során

Érdemes megnézni, történt-e valamilyen hard-kódolás a projektben, találunk-e benne olyan módosításokat, amelyek a core fájlokban lettek kivitelezve, nem pedig config-ban újraírva, vagy community/local codepool-ba áthelyezve, majd ott módosítva. Ehhez arra van szükségünk, hogy legyen egy ugyanolyan típusú (community/enterprise) Magento projektünk (a verziószám is egyezzen), amivel össze tudjuk hasonlítani.

 

Ehhez PHPStorm-ot fogunk használni, de egyéb programokkal is nagyon szépen kivitelezhető az összehasonlítás. Kattintsunk az app/code/core könyvtárra, majd jobb klikk rajta, „Compare With…” (Ctrl + D), majd válasszuk ki a „társ-környezet”-ben ugyanezt a mappát.

 

Miután elfogadtuk (OK), felugrik egy ablak a változásokkal, itt nyugodtan kapcsoljuk ki a „Show new files on left side”, illetve a „Show new files on right side” opciókat, csak összezavarna bennünket. Ezek után, ha minden igaz, csak a „Show difference” lehetőség marad aktív, ami kifejezetten a különbségek listázására való.

Sajnos olyan opciót nem találtam, ami a kommenteket nem veszi figyelembe, így bár a kódrészek megegyeznek, a kommentek miatt több fájlt is feldob, mint különbséget. Ettől eltekintve esetemben nincs különbség a 2 projekt között. Ha ez a te esetedben nem így van, tehát különbségek vannak a rendszerben, azokat a fájlokat, amelyek eltérnek az eredetitől, vissza kell állítani, és a módosításokat át kell helyezni.

tips Ezt többféleképpen is megtehetjük :

 

  1. Core fájl átmásolása az app/code/core/…/File.php elérésről, az app/code/local/…/File.php helyre, majd az eredeti fájl revertálása annak alaphelyzetébe

 

  1. A fájl config-ból való felülírása egy a saját modulunk fájljával, az eredeti fájlt ebben az esetben is alaphelyzetbe kell állítanunk, és azt mint ős-osztályt kiterjeszteni belőle

 

  1. Harmadik lehetőségként Observer-rel megvalósítani a működésbeli különbségeket

 

A fenti listából az első megoldást tartom a leggyorsabbnak, míg az utolsót a legszebbnek.

 

Amennyiben ezek megtörténtek ‒ tehát a capp/code/core fájlok az eredeti állapotukba, az új működések pedig valamilyen módon kiszervezésre kerültek ‒, a következő lépés az app/design/[frontend/adminhtml] mappa(k) tartalmának összehasonlítása. Sajnos gyakran előfordul, hogy a fejlesztő nem hoz létre saját template vagy layout fájlt, hanem a base/default/[template/layout] mappá(k)ban szereplő eredeti fájlokat módosítja.

 

Ennek javítása is hasonlóképpen történik, mint a kód esetében. A módosított fájlokat átmásoljuk a saját témánk alatt ugyanabban a struktúrában, az eredeti fájlokat pedig eredeti állapotukra revertáljuk. pl. az app/design/frontend/base/default/template/catalog/product/list.phtml-t másoljuk az app/design/frontend/rwd/theme/template/catalog/product/list.phtml elérésre, az eredetit pedig visszaállítjuk.

Layout fájlok esetében elég csak a változó részt átmásolni, nem szükséges az egész layout fájlt egy-egy rész miatt mozgatni, illetve még szebb megoldás, ha reference-szel hivatkozunk egy definiált Block-ra.

 

Template-ek esetében is érdemes felmérni annak lehetőségét, hogy tudjuk-e layout-ból számunkra megfelelő módon változtatni, módosítani. Ha layoutból módosítva azonban nem a megfelelő helyen jelennek meg a kérdéses új elemek/blokkok/template-k, a fent említett módszer (template mozgatása, változtatása) biztos megoldást jelent.

 

Tegyük fel, hogy ezeken a helyeken is minden rendben volt, a template és layout fájlok is ott kerültek módosításra, ahol ennek történnie kell (akkor ez egy nagyon szép projekt, valószínűleg a továbbiakban sem lesz vele gond). A meglévő modulok illetve template fájlok minőségét kell ellenőrizni, ezeket az alábbi szempontok alapján tudjuk megtenni, melyekre egyesével kitérünk:

 

  • Kódredundancia – kódismétlés
  • Kódrelevancia – bizonyos kódok megfelelő helyen történő tárolása
  • Installer Scriptek – minőség és megbízhatóság
  • Template fájlok – objektumhívások minimalizálása
  • Block / Controller ellenőrzés – terhelés, megvalósítás

 

 

Kódredundancia – kódismétlés

 

A kódredundancia: alatt az értendő, mikor egy adott modulon ‒ vagy akár több összefüggő modulon keresztül ‒ ugyanazt a működést valósítjuk meg, akár ugyan azzal a módszerrel, de több különböző helyen. Ha a kódban ilyet találunk, biztosan rossz helyen szerepelnek ezek a kódrészek, hiszen ezeknek optimális esetben egy helyen kell lennie, és onnan kerülnek meghívásra.

Sajnos ezt nem olyan könnyű kiszúrni, hiszen a kód nem egzakt, többféleképpen is nekifuthatunk valaminek az ellenőrzésének, így ennek a felmérése, megtalálása több időt vehet el, mint a végén az az idő, amelyet a javítására kell fordítani. Az alapvető szempont, hogy legjobb már az elején, a fejlesztés indításánál, felkészíteni az egységes működésre ezeket a folyamatokat, és ennek szellemében létrehozni a különböző megoldásokat.

 

Kódrelevancia – bizonyos kódok megfelelő helyen történő tárolása

 

Vannak kódok, melyeknek egyértelmű helyeik vannak, ilyen pl. egy új modul aloldala, action-je, aminek egyértelműen controller-be kell kerülnie, hiszen egyéb esetben nem működik. Vannak kódok azonban, amelyek funkciótól függően lehetnek Block-ban, vagy Helper-ben is, sőt, akár még Model-be is kerülhetne, de  ezeknek is megvan a pontos helye. Az általános működéshez kapcsolódó kódok azonban nagy valószínűséggel Helper-be kell, hogy kerüljenek, a keresztfunkcionalitás segítése érdekében. Jellemzően ilyenek az egy-egy modul állapotát ellenőrző kisebb metódusok, és/vagy amelyek közvetve vagy közvetlenül, de a config értékekkel dolgoznak.

 

Ezen felül kerülhetnek ide még az aktuális end user-hez kapcsolódó, de alaphelyzetben még le nem fejlesztett ellenőrzések, mint pl. egy adott típus ellenőrzése egy kiterjesztettebb regisztráció után, stb. $helper->isStudent(); $helper->isTeacher() stb. (Bár ezeket szintén akár observer-rel is meg lehet oldani.)

 

Ide lehet sorolni még bizonyos a Model-ekhez kapcsolódó „működéseket”, melyek néha eltévednek a megvalósítás közben. Jó példának tartom ide a Model exportálandó mezőit, illetve annak CSV header-eit, aminek nem helper-ben vagy block-ban a helye, hiszen bárhol ahol a Model meghívásra kerül, szükség lehet erre, aminek egyszerűbb és logikusabb módja az adott Model-ben tárolni.

Ide raknám még a Model-hez az esetleges parent-child elemek lekérését, tehát ha az egyik adott Model-nek van egy 1-* kapcsolata egy másik Model-el, azt esetleg egy $model->getChildSomethings(); metódussal a „fő” Model-ben elhelyezhető.

cikkgrafika-koderelevancia

Installer Scriptek – minőség és megbízhatóság

 

Az installer script-ek írása közben gyakran megfeledkezünk még mi magunk is arról, hogy valamilyen varázslatos és megmagyarázhatatlan módon (valaki töröl egy jellemzőt, mezőt, értéket, majd újra futtatja a script-et), időnként duplán futnak le, és így nem várt hibába ütközünk.

 

Ennek kiküszöbölése nem annyira időbeli, mint hozzáállásbeli erőfeszítést igényel. Bár valószínűleg saját script-ünk futtatásakor a saját környezetünk adataira támaszkodva készítjük el azt, érdemes ezeket mindenre felkészítve, már eleve egy ellenőrzéssel indítani.

Ha jellemzőt adunk hozzá, akkor a jellemzőt keressük először, és a hozzáadását kössük feltételhez. Tábla mezőinek manipulálásakor is érdemes ellenőrizni annak aktuális állapotát. A $installer->endSetup(); kódot, csak a 100%-ig biztos lefutáshoz illesztjük be, ha try-catch-be rakjuk az installer működését, az endSetup() ne ezen kívül, hanem a try végében helyezkedjen el, így biztosítva, hogy csak a helyes működéssel lép verziószámot modulunk.

 

Template fájlok – objektumhívások minimalizálása

 

A template fájlok (.phtml) írása során is igyekeznünk kell annak azonnali áttekinthetőségére, illetve a kód újrahasznosíthatóságára. Mit jelent ez?

 

  • Nem égetünk bele értékeket
  • Nem valósítunk meg benne működést
  • Nem hívunk a szükségesnél több metódust benne

 

Helyette:

 

  • Az értékeket/beállításokat lehetőleg már (a frontend-es kolléga támogatását elősegítve) layout szinten megadhatónak fejleszteni.
  • Mindennemű működést, ami a lekéréseken felül kerül hívásra, a Block-okban megvalósítani
  • A template-ek bizonyos szintű összetettségétől függően (pl. 2 különböző típus elágazásánál) külön template-ekbe szervezni.

 

Idetartozónak tartom még, bár valójában ez minden részében igaz a fejlesztéseknek, hogy egy-egy értéket (0, 1, 2) soha nem értékével azonosítunk, ezeket érdemes, sőt kötelező valamilyen konstansba helyezni, és így beszédes változónévvel azonnal áttekinthetővé tenni annak értékét. Erre is nagyon jó példák találhatóak a Core Magento-ban, termék Status értékek, xml config path-ek, valamilyen minimum/maximum értékek meghatározása.

cikkgrafika-templates

Azonfelül, hogy ezek sokkal áttekinthetőbbek, beszédesebbek is így, ha mindenhol ezt az értéket használjuk, arra keresni is sokkal egyszerűbb (kevesebb találat), illetve egy helyen tudjuk módosítani adott esetben.

 

Block / Controller ellenőrzés – terhelés, megvalósítás

 

A block-ok és controller-ek ellenőrzésénél két dolgot kell figyelembe venni, és ez a két dolog elég szorosan összefügg. A megvalósítás mikéntje, és a terhelés, amit ki kell állnia. Minél jobb a megvalósítás, annál kisebb a terhelés.

Amennyiben egy template fájlból a block getCollection() metódusa több alkalommal is hívásra kerül, azt jó megoldás cache-elni a block-ban, így valódi adatbázis művelet csak elsőre lesz, minden további csak a cache-elt objektumlistáig jut. Erre találunk egyébként core példákat is, amelyeket minden további nélkül lehet útmutatásként használni.

 

A controllerek esetében érdemes az egyes action-ök méretére egy pillantást vetni. Nem kívánok itt sem fontméretet sem pedig a sorok számát megadni, hogy mekkora terjedelemig megfelelő egy action, de abban azt hiszem, megegyezhetünk, hogy a szemnek kényelmesen áttekinthetőnek kell azt találnia, mind formai mind mennyiségi szempontból.

Amit még a controllerek-hez hozzátennék, hogy véleményem szerint az ezekben elhelyezett block példányosítások sem szükségszerűek, szintén meg lehet oldani a block-on belül. Ezzel máris csökkentjük annak méretét.

 

Összegzés

Ez mennyiségileg nem olyan sok dolog, hiszen mindössze 5 részletesebb és 2(1) ezektől különálló lehetséges problémafaktort tekintettünk át, de ha azt vesszük figyelembe, hogy egy-egy projekten akár nagyobb számú (értsd x > 4) fejlesztő is dolgozhat egymás mellett, modulonként akár egyszerre tízes nagyságrendű fájlokat hoznak létre/módosítanak, már nem is olyan kevés.

Ha minden ilyen fájlban csak egy ilyen apró hiba van, már az is indokolhat egy kisebb refaktorálást a projekt élesítése előtt/után. Illetve a témánkat tekintve, ezeken a pontokon végighaladva, egy részletesebb képet kapunk arról, hogy az új projektünk mennyi, és milyen problémákkal rendelkezik, melyeket meg kell oldanunk.

 

Szükséged van további segítségre? Keress minket azonnal, vagy olvass többet kódaudit szolgáltatásunkról.

 

Problémák a Magento RWD sablonnal és hogyan sikerül ezeket megoldanunk

Bevezetés

Aki már foglalkozott Magento frontend fejlesztéssel, annak nyilván nem kell bemutatnunk az RWD (Responsive Web Design) theme-et. Ez a Magento alapcsomaggal utazó reszponzív template, amellyel már mobile-ready webshopokat építhetünk fel.

Azért írom, hogy mobile-ready, mert nem mobile-first. A mobile-first ugyanis elsődlegesen a mobileszközökön való kifogástalan működést célozza meg, míg a mobile-ready alapvetően desktop funkciójú mobilos „áthallással”.

Projektjeink kapcsán megrendelőik (jogosan) egyre többször azzal a kéréssel fordulnak hozzánk, hogy webshopjukat a desktop nézet mellett a mobilra is 100%-ig optimalizáljuk UI/UX szempontból is.

A 21. század egyik nagy vívmánya az okostelefon, és ezzel együtt az internetezési szokások gyökeres átalakulása. A rohanó világban egyre többen okostelefonjukat, tabletjüket használjak a gyors információszerzés mellett a webes vásárlásokhoz is. Emiatt kiemelten fontos, hogy a mobilon vásárlást gyorsan elvégezhessük, a dizájn pedig letisztult, egyszerűen áttekinthető legyen.

Erre pedig mondjuk ki őszintén, csak bizonyos mértékig használható az RWD theme. Hogy miért is, arra a cikkben részletesebben ki fogok térni. Több projektünk után végül úgy döntöttünk, hogy bár az RWD alapjain, de egy saját template-et építünk fel a Bootstrap framework segítségével.

 

Megvalósítás

Melyek tehát azok a pontok, amelyek alapján az RWD nem megfelelő választás egy 21. századi, mobile-first webshop kialakításához?

 

  • Mobile-ready, nem mobile-first (elsődlegesen a desktop nézetet támogatja)
  • Elavult grid rendszer (az RWD egy jó pár éves, saját fejlesztésű grid rendszert használ, amivel nehézkesen valósíthatók meg egyedi mobil felületek – a NILA ezzel szemben az egyik legkorszerűbb frontend framework-ot, a Bootstrap-et használja – 12 oszlopos grid rendszere, a flex támogatással a legjobb választás gyors fejlesztéshez)
  • Nem moduláris (Nincs lehetőség az aloldalak, layoutok külön módosítására, minden egy CSS fájlból van kezelve)
  • Nincs OOP CSS (Mivel csak egy fordított CSS fájlt tartalmaz az RWD sablon, ezért nehézkesen módosíthatók akár csak az alapbeállítások is – szín, betűtípus stb.)
  • Gyenge böngésző támogatottság (nincs kifejezetten OSX/iOS támogatás)

 

A NILA sablon dizájnja

Grafikusunk az RWD demo alapján alakította ki az Aion NILA sablon megjelenését. Próbáltuk még letisztultabbá és áttekinthetőbbé tenni, valamint, ahogy már említettem, a szemlélet mobile-first alapú. Ez azt jelenti, hogy mind dizájnban, mind megvalósításban lentről építkezünk felfelé. Színvilágban a kékes-szürke irányt választottuk, ettől lett a végeredmény igazán minimalista.

 

Új skin létrehozása

Az első lépésben létrehoztunk egy új skint az RWD csomag alatt. Azért nem egy új csomagot használtunk, mert a NILA template struktúrája az RWD-re támaszkodik, így gyorsabban és egyszerűbben tudtunk haladni a fejlesztéssel.

 

rwd vs nila sablon struktúra

 

 

A gyakorlatban ez úgy nézett ki, hogy a számunkra szükséges template-eket, layoutokat override-oltuk a NILA skin alól, a struktúra többi részét pedig az RWD alól kezeljük a template jelenlegi verziójában.

Ahogy említettem, a megvalósításhoz frontend oldalról a Bootstrap framework legfrissebb verzióját használtuk (3.3.6), a CSS-t pedig LESS-szel valósítottuk meg az objektum orientáltság függvényében. A NILA csomagolt verziója csak a fordított CSS fájlokat fogja tartalmazni.

Frontend oldalról mindegyik oldal és aloldal új csínt kapott, egységes CMS megjelenítést hoztunk létre, valamint kiemelt figyelmet fektettünk az e-mail template-ek, valamint a nyelvesítés megvalósítására is (hu_HU)

 

Mélyvíz – lássuk a kódszintű felépítést!

 

Ugorjunk fejest a mélyvízbe. A teljesség igénye nélkül most bemutatom a NILA felépítését kód szempontból is.

 

Könyvtárszerkezet

 

NILA theme: app/design/frontend/rwd/nila

 

NILA skin:: skin/frontend/rwd/nila

 

A skin mappánk több almappából épül fel.

 

  • aion: a NILA skin saját CSS / JS fájlok, amelyek az oldal megjelenését befolyásolják
  • css: email-inline.less az email template-ekhez használt megjelenés
  • images: alapértelmezett RWD template képek
  • img: a NILA témához tartozó képek
  • vendor: third-party könyvtárak és modulok mappája (Bootstrap, Fontawesome, Owl.Carousel)

 

 

Grid rendszer

Az RWD sablon rendszere egy saját fejlesztésű grid rendszeren alapul, amely csak korlátozottan használható mobile-first oldalak fejlesztéséhez.

 

Példa:

 


@media only screen and (min-width: 480px) {
  .customer-account-login .col2-set .col-1,
  .customer-account-login .col2-set .col-2 {
    padding-top: 0;
    margin-top: 20px;
  }
  .customer-account-login .col2-set .col-1 {
    padding-right: 20px;
  }
  .customer-account-login .col2-set .col-2 {
    padding-left: 20px;
    border-left: 1px solid #ededed;
  }
}
@media only screen and (min-width: 770px) {
  .customer-account-login .col2-set .col-1 {
    padding-right: 0;
  }
  .customer-account-login .col2-set .col-2 {
    padding-left: 60px;
    border-left: 1px solid #ededed;
  }
}
@media only screen and (max-width: 479px) {
  .customer-account-login .col2-set .col-1 {
    padding-bottom: 30px;
  }
  .customer-account-login .col2-set .col-2 {
    padding-top: 30px;
    border-top: 1px solid #ededed;
  }
}

Ahogy láthatjuk, a grid rendszer mobil töréspontok deklarálása nem az elfogadott töréspontokhoz igazodik, hanem egyedi pontokat hoz létre: 479, 770, de a kódot átnézve további idegen töréspontokra is találhatunk:


@media only screen and (max-width: 535px) {...}
@media only screen and (max-width: 525px) {...}
 

 

A NILA grid rendszeréhez a Bootstrap framework-öt választottuk, amely mobile-first szemlélettel készült, és igazodik a szabványos töréspontokhoz, és ezzel az elterjedt felbontások támogatásához:

(http://getbootstrap.com/css/#grid)

 

 


/* Extra small devices (phones, less than 768px) */
/* No media query since this is the default in Bootstrap */
/* Small devices (tablets, 768px and up) */
@media (min-width: @screen-sm-min) { ... }
/* Medium devices (desktops, 992px and up) */
@media (min-width: @screen-md-min) { ... }
/* Large devices (large desktops, 1200px and up) */
@media (min-width: @screen-lg-min) { ... }

 

 

rwd vs nila grid

 

 

Less fájlok

Template-ünket úgy építettük fel, hogy az minél modulárisabb és könnyen módosítható legyen. Minden oldal, CMS oldal saját LESS fájlt kapott, így a template-et moduláris szinten tudjuk módosítani, valamint új projektek eseten nem szükséges az egész template-et felhasználni, csak a módosítandó layoutokat.

A template egységes elemei, így például a fejléc, láblééc, és a gombok megjelenése szintén egy különálló LESS fájlba kerültek, valamint létrehoztunk egy BASE.less fájlt a változók, funkciók, mixinek tárolására.

 

rwd vs nila less fájl

 

A frontendre csak a nila.css fájl kerül ki, ez pedig a fordítás előtt így épül fel a moduláris less fájlokból:

  • Base.less
  • Deafult.less
  • Module.less

 

 

rwd vs nila könyvtár

 

Új oldal esetén csak hozzá kell fűznünk a module_neve.less fájlt a nila.less-hez, és fordítás után már a nila.css tartalmazni fogja az új vagy módosított megjelenést.

 

Javascript

A NILA sablon JS oldalról nem tartalmaz különösebb módosítást az RWD-hez képest, a Bootstrap javascript plugin-jai mellett csupán az OwlCarousel.js-t használtuk fel a főoldali újdonságok slider-hez.

 


   jQuery("#home-products-grid").owlCarousel({
        autoPlay: false,
        items : 5,
        itemsDesktop : [1199,3],
        itemsDesktopSmall : [979,3],
        navigation: true
    });

 

Ahogy láthatjuk, a slider-ben alapesetben 5 terméket jelenítünk meg, ezután pedig a további termékek slide-olással tekinthetők meg. Ha más számú terméket szeretnénk megjeleníteni, azt megtehetjük admin felületről, az alábbi sor módosításával, valamint a javasript „items” értékének módosításával:

 


   $content = '{{widget type="catalog/product_widget_new" display_type="new_products" products_count="5" template="catalog/product/widget/new/content/new_grid.phtml"}}';

 

Template override

 

Mivel a NILA jelenlegi verziója az RWD csomagon alapszik, ezért csak azokat a template-eket / layout fájlokat módosítottuk, amelyekre az egyedi megjelenéshez szükségünk volt. A fejlesztések későbbi szakaszaiban a NILA ki fog válni az RWD csomag alól, és különálló csomagként fog funkcionálni.

 

  • CMS
  • Home
  • Category
  • Product
  • Cart
  • Checkout
  • Wishlist
  • Dashboard
  • Account

 

A NILA sablon egyik legnagyobb előnye tehát a moduláris felépítés. Míg az RWD téma módosítása nehézkes, a NILA template-et percek alatt testre tudjuk szabni a base.less es default.less fájlok módosításával.

 

 

További mobil optimalizációk

Mint említettem, template-ünket mobile-first szemléletben építettük fel, a cél a minél egyszerűbb használhatóság megvalósítása volt mobil eszközökön is. Mivel több elem nem, vagy csak nehézkesen használható mobil nézetben (pl. táblázatok, kosár, checkout, érintési felületek), ezért egy egyedi modul segítségével azonosítani tudjuk a felhasználó eszközét, és ennek megfelelően mobil és desktop blokkokat betölteni.

 

Modulunk alapját a széles körben ismert MobileDetect PHP könyvtár adta.

 


<?xml version="1.0"?>
<config>
    <modules>
        <Aion_MobileDetect>
            <version>0.1.0</version>
        </Aion_MobileDetect>
    </modules>
    <global>
        <helpers>
            <aion_mobiledetect>
                <class>Aion_MobileDetect_Helper</class>
            </aion_mobiledetect>
        </helpers>
    </global>
</config>

 

Mobil detektálása:

 


public function isMobile($userAgent = null, $httpHeaders = null)
{
        if ($httpHeaders) {
            $this->setHttpHeaders($httpHeaders);
        }
        if ($userAgent) {
            $this->setUserAgent($userAgent);
        }
        // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
        if ($this->getUserAgent() === 'Amazon CloudFront') {
            $cfHeaders = $this->getCfHeaders();
            if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') {
                return true;
            }
        }
        $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
        if ($this->checkHttpHeadersForMobile()) {
            return true;
        } else {
            return $this->matchDetectionRulesAgainstUA();
        }
}

 

Függvényünket bármelyik templateünkben a következő módon hívhatjuk meg:

 


$helper = Mage::helper('aion_mobiledetect/data');
if($helper->isMobile())
{
  echo “is mobile”;
} 

else 
{
  echo “is not mobile”;
}

 

Ez a megvalósítás lehetőséget ad számunkra, hogy a reszponzív nézetek mellett mobilra egyedi blokkokat is betölthessünk, amelynek teljesen eltérő a szerkezete a desktop felépítéstől. Ezeket a blokkokat a böngészőnk csak akkor fogja letölteni, ha az adott eszközről használjuk az oldalt. Ezzel a módszerrel elkerülhetjük az elemek felesleges betöltését.

 

Safari / iOS támogatás

Az alap RWD téma egy másik nagy hibája, hogy gyenge a böngésző támogatottsága. Megrendelőink egyik igénye, a Windows-os böngészők támogatása mellett (IE10+, Chrome, Firefox, Opera) az OSX-en és iOS-en való Safari böngészőket is támogassuk.

Mivel sajnos a Safari alapértelmezetten több érteket másképp kezel, mint a Chrome, így az általános less fájlok egyszerű módosítása nem oldotta volna meg a problémát.

Egy egyszerű példánál maradva, a Safari a “display: flex” értéket is másképpen kezeli, mint a Chrome vagy Firefox böngészők, ezért a következő módosítást kellett eszközölnünk:

 


.aion-dashboard-wishlist {
 .cart-item {
 display: -webkit-flex;
 -webkit-flex: 1;
 -webkit-box-flex: 1;
 }
}

 

[ Megjegyzés: Safari böngésző esetén további problémát jelent a form-ok formázása, mivel mind az OSX mind az iOS a native form elemeket jelenít meg. Designereinkkel egyeztetve végül úgy döntöttünk, hogy az egyedi / Bootsrap form elemek helyett OSX/iOS renszerek alatt meghagyjuk a form elemek native megjelenését a jobb UX élmény érdekébben. ]

 

A megoldás a fentebb már említett MobileDetect modul volt, melyet kiegészítettünk egy Safari detektálással is:

 


/**
* This method checks if browser is Safari / Desktop
* @return bool
*/
public function isBrowserSafari()
{
    $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : "";
        if (stripos($agent, 'Safari')
            && stripos($agent, 'iPhone') === false
            && stripos($agent, 'iPod') === false
            && stripos($agent, 'Chrome') === false) {
            $this->setBrowser(self::BROWSER_SAFARI);
            return true;
        }

     return false;
}

 

Ezt az alábbi módon használhatjuk fel:

 


$helper = Mage::helper('aion_mobiledetect/data');

if($helper->isBrowserSafari()) 
{
    $body_class = "__browser_safari";
} 

else
{
    $body_class = "__browser_other";
}

 

Ennek a segítségével lehetőségünk nyílt kifejezetten csak OSX/Safari böngészőkre optimalizált CSS módosításokat végezni, amely módosítások nem befolyásolják a Windows-os böngészők megjelenítését sem.

 


/** This less file support OSX/Safari browser compatibility!*/
@import "base";
.__browser_safari {
 … egyedi customizaciok
}

 

Összegzés

 

A NILA sablon az RWD-hez képest nagyon sok javítást és egyedi megoldást hoz, amivel a Magento webáruházunk igazán sikeres lehet. A template-ünket úgy alakítottuk ki, hogy bármilyen webáruhazat gyorsan és könnyen egyedire szabhassunk használatával.

A NILA sablont jelenleg még fejlesztjük és házon belüli kisebb projektekben teszteljük, de hamarosan dobozos formában is elérhető lesz a nagyközönség számára is. Erről pedig természetesen majd itt a blogon értesülhetsz először!

 

Magento (1.9) EAV a gyakorlatban (frontend)

A Magento alatt ez a következőképpen néz ki: 

  • entity tábla (meghatározza az entity-t)
  • attribute tábla (meghatározza a tulajdonságot, annak típusát, egyéb opciókat, pl.: source model, type, input, label)
  • value tábla (ez valójában típusonként szét van választva, többek között az indexelhetőség, keresés miatt pl.: catalog_product_entity_int, catalog_product_entity_varchar stb.)

A tulajdonságokat tárolhatnánk a fő-táblában is, nem?

Az EAV adatmodellben az elemekhez való új tulajdonságok felvitele során nem kell az eredeti entity táblát módosítani, így egyrészt elkerülhetők a túl nagy táblák, ezzel a lekérdezések sebessége is gyorsabb lesz, másrészt pedig a listáknál a felesleges adatok nem jelennek meg, csak amelyeket mi hozzáadunk a collection-höz. A cikk során egy modult fogunk készíteni, admin és frontend felülettel, EAV megoldással.

Miután a webáruházunkat feltelepítettük a szerverre, és konfiguráltuk azt (base url, database name, database user stb.), minden megjelenik rendeltetésszerűen, elkezdjük a fejlesztést.

Modulunk definilásához, az app/etc/modules könyvtárban kell létrehozni egy a module nevével megjelölt xml fájlt. Az én esetemben ez az Aion_Items.xml, a codePool pedig local, de a community codePool-ban is elhelyezhetnénk.

Az xml a következőképpen néz ki:

 

<?xml version="1.0"?>
<config>
    <modules>
        <Aion_Items>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Core/>
            </depends>
        </Aion_Items>
    </modules>
</config>

 

Ez még nem elég, a module még cache-ürítés után sem fog megjelenni, az admin-felület modul-listájában sem. A következő lépés, hogy az xml-ben definiált modult, a codePool-ban megadott könyvtárban létrehozzuk. Ez ebben az esetben, az app/code mappában jelent egy local könyvtárat (amennyiben még nem létezik), azon belül egy Aion/Items mappaszerkezetet. Tehát a végső elérésünk ebben az esetben app/code/local/Aion/Items.

module_path

 

A következő lépésekben a fő irányadók az általános modulkészítés szabályai, pár eltéréssel. Ha nem jut eszedbe éppen valami, nem szégyen puskázni a Magento core modulok tartalmából :)

Hozzuk létre a modul config.xml fájlt. Haladjunk lépésről lépésre:

 

<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <modules>
        <Aion_Items>
            <version>0.0.1</version>
        </Aion_Items>
    </modules>
</config>

 

Definiáljuk a modellek, resource modellek elérhetőségét, illetve az entity táblá(ka)t a modulunknak. Folytatólagosan a </config> node elé helyezzük el a következőket, közvetlenül a </modules> node után:

 

<global>
    <models>
        <aion_items>
            <class>Aion_Items_Model</class>
            <resourceModel>aion_items_resource</resourceModel>
        </aion_items>
        <aion_items_resource>
            <class>Aion_Items_Model_Resource</class>
            <entities>
                <article>
                    <table>aion_items_article</table>
                </article>

 

Nem zártuk még le az <entities> node-ot, továbbra is ezen belül maradunk, és meghatározzuk a többi, EAV adattáblát, típusonként:

 

            <article_datetime>
                <table>aion_items_article_datetime</table>
            </article_datetime>
            <article_decimal>
                <table>aion_items_article_decimal</table>
            </article_decimal>
            <article_int>
                <table>aion_items_article_int</table>
            </article_int>
            <article_text>
                <table>aion_items_article_text</table>
            </article_text>
            <article_varchar>
                <table>aion_items_article_varchar</table>
            </article_varchar>
            <article_char>
                <table>aion_items_article_char</table>
            </article_char>
        </entities>
    </aion_items_resource>
</models>

 

Majd pedig a helper-ek, block-ok elérése, definiálása következik:

 

<helpers>
    <aion_items>
        <class>Aion_Items_Helper</class>
    </aion_items>
</helpers>
<blocks>
    <aion_items>
        <class>Aion_Items_Block</class>
    </aion_items>
</blocks>

 

Most, hogy a tábláink létre is jöjjenek, szükség lesz az erőforrások megadására, ami az installer és adatbázis-kapcsolat meghatározását jelenti, folytatólagosan a </blocks> alá tehetjük, de az számít, hogy ezek egy szinten legyenek.

 

        <resources>
            <aion_items_setup>
                <setup>
                    <module>Aion_Items</module>
                    <class>Aion_Items_Model_Resource_Setup</class>
                </setup>
            </aion_items_setup>
        </resources>
    </global>
</config>

 

Láthatóan le is zártam a node-okat, a következő lépések az alap helper (ez nagyon fontos(!), e nélkül nem fog működni a modulunk), majd a modellek létrehozása lesz. Az xml-ben megadottak szerinti helyen kell ezeket létrehozni. A modelleket tehát az Aion/Items/Model, a helper-t pedig az Aion/Items/Helper mappában.

A modulhoz tartozó default helper a Data nevet viseli minden esetben, a

Mage::getHelper(‘aion_items’) ezt próbálja meg példányosítani amely egyenértékű a Mage::getHelper(‘aion_items/data’) hívással.

Helperünk tehát az Aion_Items_Helper_Data osztálynevet, Data fájlnevet viseli, és a Mage_Core_Helper_Abstract osztályból származtatjuk.

Hozzuk létre a modelleket, és resource modelleket!

Az <entities> alatt az article-t határoztuk meg, így legyen a modellünk is ez, hozzuk létre az

  • Aion_Items_Model_Article
  • Aion_Items_Model_Resource_Article
  • Aion_Items_Model_Resource_Article_Collection osztályokat.

Mivel EAV adatmodell mellett döntöttünk, így nem a szokásos Mage_Core_Model_Resource_Abstract, és Mage_Core_Model_Resource_Db_Collection_Abstract osztályokból származtatjuk ezeket, hanem az eddigiek sorrendjében a következő osztályokból:

  • Mage_Eav_Model_Entity_Abstract
  • Mage_Eav_Model_Entity_Collection_Abstract

A resource model-ben van még egy kis változás:

 

class Aion_Items_Model_Resource_Article extends Mage_Eav_Model_Entity_Abstract
{
const ENTITY = ‘aion_items_article’;

public function __construct()
{
$this->setType(self::ENTITY)
->setConnection(‘core_read’, ‘core_write’);
}
}

 

Nem véletlenül maradt ki a felsorolásból az első modell (Aion_Items_Model_Article). Ezt továbbra is a Mage_Core_Model_Abstract osztályból származtatjuk, nincs változás. Ha megvannak a modellek, még az installer osztályt kell létrehozni. Ezt már szintén megadtuk a modul alap-konfigurációs fájljában (Aion_Items_Model_Resource_Setup). Hozzuk létre a megfelelő helyen, tartalma pedig legyen a következő:

 

class Aion_Items_Model_Resource_Setup extends Mage_Eav_Model_Entity_Setup
{
    public function getDefaultEntities()
    {
        $entityAttributes = array(
            Aion_Items_Model_Resource_Article::ENTITY => array(
                'entity_model' => 'aion_items/article',
                'attribute_model' => '',
                'table' => 'aion_items/article',
                'attributes' => array(
                    'name' => array(
                        'type' => 'varchar',
                        'label' => 'Name',
                        'input' => 'text',
                        'global' => 0,
                        //this set the attribute to store entity data separated to every store not globally
                        'visible' => true,
                        'required' => true,
                        'user_defined' => true,
                        'visible_on_front' => true
                    ),
                    'customer_id' => array(
                        'type' => 'integer',
                        'label' => 'Customer',
                        'input' => 'select',
                        'global' => 1,
                        'visible' => false,
                        'required' => true,
                        'user_defined' => true,
                        'visible_on_front' => false,
                        'source' => 'aion_items/article_attribute_source_customer'
                    ),
                ),
            )
        );

        return $entityAttributes;
    }
}

 

Ezeket a tulajdonságokat fogja létrehozni a telepítő lefutáskor az entity típushoz. A fenti tulajdonság opciókon felül, természetesen van más lehetőség is, de mivel ezek jelen esetben nem térnek el default értékeitől, nem szükséges megadni.

A customer_id tulajdonságnál látható, hogy megadtuk a source opciót, így ehhez szükségünk lesz egy source modellre. Hozzuk létre tehát a megadott helyen és néven, az app/code/local/Aion/Items/Model/Article/Attribute/Source mappában a Customer.php fájlt, tartalma pedig legyen a következő:

 

class Aion_Items_Model_Article_Attribute_Source_Customer extends Mage_Eav_Model_Entity_Attribute_Source_Table
{
    public function getAllOptions()
    {
        if (!$this->_options) {
            $customers = Mage::getResourceModel('customer/customer_collection')
                ->addAttributeToSort('lastname', 'ASC')
                ->addAttributeToSort('firstname', 'ASC');
            foreach ($customers as $customer) {
                $name = [$customer->getFirstname(), $customer->getLastname()];
                $this->_options[] = ['value' => $customer->getId(), 'label' => join(' ', $name)];
            }
        }
        return $this->_options;
    }
}

 

Ahhoz, hogy ezek után létrehozzuk a táblánkat, már csupán az installerünk kell létrehozni. Ezt a saját modulunk alatti sql, azon belül pedig a <resources> node alatt definiált mappában kell megtenni. Mivel ebben az esetben ez az <aion_items_setup>, így a mappa is  aion_items_setup lesz.

A modulunk config.xml fájljában korábban megadtuk a verziót, <version> node-ban, ez lesz az installer-ünk verziószáma. Hozzunk létre tehát egy install-0.0.1.php fájlt az app/code/local/Aion/Items/sql/aion_items_setup mappában.

Ennek a tartalma a következő:

 

try {
    $this->startSetup();
    $this->createEntityTables('aion_items/article');
    $this->addEntityType(Aion_Items_Model_Resource_Article::ENTITY, [
        'entity_model' => 'aion_items/article',
        'attribute_model' => '',
        'table' => 'aion_items/article',
        'increment_model' => '',
        'increment_per_store' => '0'
    ]);

    $this->installEntities();
    $this->endSetup();
} catch (Exception $e) {
    Mage::logException($e);
}

 

Ha ezzel megvagyunk, készen áll a modul a telepítésre. Mielőtt azonban lefuttatnánk, nézzük meg a mappa- és fájlszerkezetünket, mely a következőképpen néz ki:

 

files_in_module_1

 

 

Hogy modulunk installer-e lefusson, az admin felületen System -> Cache management menüpont alatt, ürítsük a cache-t. Amennyiben sikeresen lefutott az installer, a következő táblákat kell látnunk az alap táblákon felül az adatbáziskban.

 

eav_tables

 

 

Hogy biztosra menjünk, kapcsoljuk be a logolást az admin-felületen az installer futtatása előtt, illetve utána nézzük meg a var/log mappát, exception.log vagy system.log fájlok találhatóak-e benne. Ezenfelül az eav_attribute táblában az attribute_id szerint csökkenőbe rendezve láthatjuk, hogy a customer_id, és name jellemzőink létrejöttek-e, illetve mellette az entity_id mezőben láthatjuk, hányas ID-t kapta az új entity típusunk. Rákattintva meg is tekinthetjük azt.

Ha eddig minden rendben zajlott, csináljunk egy frontend oldalt a modulunknak, hogy letesztelhessük, minden helyesen működik-e. A <global> node alatt, de még a </config> node előtt helyezzük el a következő kód-blokkot:

 

<frontend>
    <routers>
        <aion_items>
            <use>standard</use>
            <args>
                <module>Aion_Items</module>
                <frontName>aionitems</frontName>
            </args>
        </aion_items>
    </routers>
</frontend>

 

A frontend oldali megjelenítéshez szükségünk van még layout, controller, block, és template fájlra. Ugyan ezen <frontend> node alá helyezzük el a layout fájl definiálását:

 

<layout>
    <updates>
        <aion_items>
            <file>aion/items.xml</file>
        </aion_items>
    </updates>
</layout>

 

Ezek után a fájlt hozzuk létre annak helyén (app/design/frontend/rwd/default/layout). Fontos, hogy a modulunkhoz tartozó alap template fájlokat mindig a témához tartozó default alatti layout könyvtárban hozzuk létre, hogy a későbbi módosításkor annak másolatán, ne pedig az eredeti fájlon hajtsanak végre módosításokat. Ugyanez érvényes a template fájlokra is.

 

<?xml version="1.0"?>
<layout version="0.1.0">
    <aion_items_index_index translate="label">
        <label>Aion Items</label>
        <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
        </reference>
        <reference name="content">
            <block type="aion_items/list" name="aion.items.list" as="aion_items_list" template="aion/items/index.phtml"/>
        </reference>
    </aion_items_index_index>
</layout>

 

Ha ez is megvan, jön a template fájl és a block. Template fájlnak az xml-ben az aion/items/index.phtml-t jelöltük meg, így egy szinttel fentebb, az app/design/frontend/rwd/default/template/aion/items mappában helyezzük el az index.phtml fájlt, majd az app/code/local/Acion/Items/Block könyvtárban helyezzünk el egy List.php fájlt amelynek tartalma a következő legyen:

 

class Aion_Items_Block_List extends Mage_Core_Block_Template
{
    /**
     * @return \Aion_Items_Model_Resource_Article_Collection
     * @throws \Mage_Core_Exception
     */
    public function getArticleCollection()
    {
        $articles = Mage::getModel('aion_items/article')->getCollection()
            ->addAttributeToSelect('*');

        return $articles;
    }
}

 

Most térjünk vissza az index.phtml template fájlra, és egyelőre legyen a következő a tartalma:

/** @var Aion_Items_Block_List $this */
$articles = $this->getArticleCollection();
Zend_Debug::dump($articles->getData(),'articles');

 

Hogy megjelenjen a collection tartalma, már csak egy controller-re van szükségünk, hozzuk létre az IndexController.php fájlt az app/code/local/Aion/Items/controllers mappában, az alábbi tartalommal:

 

class Aion_Items_IndexController extends Mage_Core_Controller_Front_Action
{
    /**
     * @return $this
     */
    public function indexAction()
    {
        $this->loadLayout();
        $this->renderLayout();

        return $this;
    }
}

 

Ezután ismét ürítsük a cache-t az admin-felületről, és a frontenden hívjuk meg a modulunkhoz tartozó url-t (a példabeli esetben ez a /aionitems/ ami egyenértékű a /aionitems/index/index/ hívással). Ha minden jól ment, akkor valami hasonlót kell látnod:

 

frontend_display

 

 

Ez eddig szuper, de semmi sem jelenik meg lényegében, hiszen nincs semmilyen adat a táblában. Hogy szemléletesebb legyen a példa, írjunk még egy data-installer-t, hogy láthassuk, működnek-e a jellemzőink is megfelelően.

Az egyik előző képen látható volt egy data mappa, ennek a mappának pontosan ez a szerepe, a nem rendszer-szintű módosításokat ezeken keresztül tudjuk megoldani. Szerkezetben az sql könyvtárhoz kapcsolódik, így ezen belül is szükség van egy aion_items_setup almappára.

A „sima” installer-script-hez képest még annyi eltérés van a működésben, hogy az ezen struktúra alatt lévő fájlokat a Magento egy data- előtaggal keresi.

Tehát az app/code/local/Aion/Items/data/aion_items_setup mappában hozzunk létre egy (mivel már az install-0.0.1.php lefutott) data-upgrade-0.0.1-0.0.2.php nevű fájlt, és az app/code/local/Aion/Items/sql/ mappában szintén egy upgrade-0.0.1-0.0.2.php nevű fájlt. Ez utóbbiban csak megjelöljük, mi történik és hol. Tehát az upgrade-0.0.1-0.0.2.php a következőt tartalmazza:

 

/** @var Aion_Items_Model_Resource_Setup $this */
try {
    $this->startSetup();
    //app\code\local\Aion\Items\data\aion_items_setup\data-upgrade-0.0.1-0.0.2.php
    $this->endSetup();
} catch (Exception $e) {
    Mage::logException($e);
}

 

Az app/code/local/Aion/Items/data/aion_items_setup/data-upgrade-0.0.1-0.0.2.php pedig a következőket tartalmazza:

 

/** @var Aion_Items_Model_Resource_Setup $this */
try {
    $defaultStoreId = Mage::app()->getDefaultStoreView()->getId();
    $attributeSet = Mage::getResourceModel('eav/entity_attribute_set_collection')
        ->addFieldToFilter(
            'entity_type_id',
            Mage::getModel('eav/entity')
                ->setType(Aion_Items_Model_Resource_Article::ENTITY)
                ->getTypeId()
        )->addFieldToFilter(
            'attribute_set_name',
            'Default'
        )->getFirstItem();
    $articles = [
        [
            'store_id' => $defaultStoreId,
            'name' => 'Article name 1',
            'attribute_set_id' => $attributeSet->getId(),
        ],
        [
            'store_id' => $defaultStoreId,
            'name' => 'Article name 2',
            'attribute_set_id' => $attributeSet->getId(),
        ]
    ];
    foreach ($articles as $article) {
        Mage::getModel('aion_items/article')->setData($article)->save();
    }
} catch (Exception $e) {
    Mage::logException($e);
}

 

Ez még nem elég. Ha frissítünk, nem fut le az új installer, de már le sem kell írnom, hogy a cache-t ürítsük :) Ezenfelül pedig ugye még a modulhoz tartozó config.xml fájlban a <version> node alatt szereplő 0.0.1-et növeljük 0.0.2-re, majd frissítsük az oldalt. Ha minden rendben ment (és reméljük, hogy igen), akkor a következőt kell látnod az adatbázisban:

 

data_installed

 

 

Az aion_items_article_varchar táblában pedig külön szerepelnek a nevek az entitásokhoz tartozóan.

 

data_eav_installed

 

Ha minden rendben ment, a frontenden a frissítést követően a következőt láthatjuk:

 

frontend_display_data

 

Összegzés

Azt hiszem, nem mondok nagy butaságot ha kijelentem, hogy az EAV egy nagyon hasznos ugyanakkor  komplex dolog, amire az esetek nagy részében nincs szükség. A többnyire kis, illetve közepes fejlesztések ‒ mivel általában eleve több, egymáshoz kapcsolódó tábláról van szó ‒ nem indokolják ezt a szerkezeti felépítést.

Érdemes azonban ezt már az elején lefektetni, mivel ‒ ahogy a Magento maga is teszi saját ezen struktúrában tárolt adataival ‒ ezeket lehet egy generált, a szükséges adatokat megjelenítő összesítő táblában tárolni (flat). Igen időigényes és költséges lenne egy már meglévő, nagy számú komoly táblaszerkezetet EAV struktúrába átültetni.

 

Külső adatbázisok elérése és egyedi raktárkészletek kezelése Magento-ban

Miről is lesz szó a cikkben?

  • Mi is az az FMCG?
  • Általánosságban pár szó az adatbázisokról
  • Adatbázisok és a Magento
  • Adatbázis típusok és felhasználásuk az FMCG-hez
  • Készlet változások kezelése a Magentoban, kérdések és javaslatok
  • Middleware: Köztes rétegek, MOM rendszerek

Mi is az az FMCG?

Rövid defíníció:

Fast-moving consumer goods vagy consumer packaged goods (CPG), azaz gyorsan forgó fogyasztási cikkek.

Azokat az árucikkeket értjük ez alatt, amelyek viszonylag gyakran, napi, heti vagy havi rendszerességgel újra megvásárlásra kerülnek és viszonylag alacsony árúak.

Ide tartozik például a borotva, papír zsebkendő vagy kisbabások esetén a nedves törlőkendő és a pelenka, de lehet szó a kötszerekről vagy a ragtapaszról is.

 

 Adatbázisok

Rövid defíníció:

Az adatbázisok azonos minőségű, strukturált információk összessége, amelyet tárolásra, szerkesztésre és lekérdezésre alkalmas adatbázis-kezelő alkalmazás kezel. Az adatbázisok célja az adatok megbízható, hosszú távú tárolása és viszonylag gyors visszakeresés biztosítása.

Az adatbázisokat két nagy csoportba érdemes bontani, a logikai és a fizikai adatbázisokra. A logikai adatbázisokat felépítésük, működésük és sajátosságaik alapján szokás megkülönböztetni a fizikai adatbázisoktól. Adatmodellekkel reprezentáljuk őket és a korszerű adatbázisoknál a fizikai adatbázist több logikai adatbázison keresztül is elérhetjük, mintha egyfajta burkoló rétegeket képeznének a tárolt adatok elé.

A Magento adatmodelljei (model) és gyűjteményei (collection) pontosan egy ilyen logikai adatbázist képeznek le a fizikai adatbázis elé, hogy megkönnyítsék és érthetőbbé tegyék az adatok feldolgozását. Az adatmodellekről, gyűjteményekről részletesebben olvashatsz ebben a cikkünkben: Magento 2 modul fejlesztés lépésről lépésre – 1. rész

 

magento külső adatbázis, modellek közti összefüggés

Fogalmi, logikai és fizikai modell összefüggése

 

Adatbázisok és Magento

A webáruházak és manapság minden alkalmazás egyik legfontosabb része az adatbázis, melyek üzemeltetése, karbantartása és fejlesztése hatalmas összegekbe kerül. Az adatbázisok lehetnek elosztottak is, mivel a Magento webshop logikai adatbázisa beburkolja a kapcsolatot, így csökkenthetjük a költségeinket és a megfelelő adatokat a megfelelő helyeken kezelhetjük.

A Magento emellett képes egyszerre több különböző adatbázist is kezelni, melyekhez a PDO-t használja, így Cubrid, FreeTDS / Microsoft SQL Server / Sybase, Firebird, IBM DB2, IBM Informix Dynamic Server, MySQL 3.x/4.x/5.x, Oracle Call Interface, ODBC v3 (IBM DB2, unixODBC és win32 ODBC), PostgreSQL, SQLite 3 és SQLite 2, Microsoft SQL Server / SQL Azure, 4D alapú kapcsolatokat könnyedén kiépíthetünk benne.

 

Többszörös adatbázis-kezelés

Ahhoz, hogy egyszerre több adatbázist is kezelni tudjon a Magento webáruházunk, csupán elegendő a modulunk config.xml konfigurációs állományba felvenni az új adatbázis elérhetőségének paramétereit (host, username, password, dbname), valamint a connection > use-ban meghatározni a kapcsolat azonosítóját.

Ezzel a kapcsolatnak már nincs szoftveres akadálya, ha a hálózaton keresztül a host elérhető, akkor a kapcsolat létrejön. A fejlesztőknek ezután már csak a logikai adatbázist (model, collection) kell létrehoznia, hogy az adatok áramlása zökkenőmentes legyen.

 

Adatbázisok: Állomány alapú források

A tapasztalatok azt mutatják, hogy a legtöbb esetben egyszerű (csv) vagy összetett (xml, json) forrás állományok állnak a felhasználók birtokában. Ezek az állományok tartalmazzák a teljes termékkínálatot, a felhasználói adatokat vagy akár a rendeléseket is. A Magento is lehetőséget biztosít ezen adatok exportálására, egészen könnyedén az adminisztrációs felületről.

 

magento külső adatbázis, skálázhatóság

 

Előnyei

  • Könnyen kezelhetőek
  • Könnyen módosíthatóak
  • Az ember számára viszonylag könnyen olvasható formátum
  • Exportálási lehetőség elérhető, nem indokol fejlesztést

 

Hátrányai

  • Szerkesztéskor nagy a hibalehetőség, amivel a teljes állomány szerkezete felbomolhat
  • Rekordok szerkesztése nehézkes
  • Az állományok kódlapjának beállítása adattorzulást okozhat
  • Importálásnál a teljes adatmennyiséget feldolgozzuk
  • Nem frissül automatikusan

 

Adatbázis-kezelő rendszerek

Az állomány alapú forrásokhoz képest itt annyi a különbség, hogy egy adatbázis-kezelő rendszeren keresztül érjük el adatainkat. Az adatbázis-kezelő áthidalja az állományok kezelése okozta hátrányokat, hiszen jól értelmezhető logikai adatmodelleket kínál erre. A fizikai adatfüggetlenség biztosítására az adatbázis-kezelő motortól független állományszervezési rendszereket dolgoztak ki, hogy a háttértár szervezése illetve eszköz függetlensége biztosítva legyen.

Az adatmodellek alapján megkülönböztethetünk relációs, objektumorientált, hálós, deduktív, objektumrelációs, deduktív relációs, deduktív objektumorientált adatbázis-kezelőket.

 

Háttértár szervezések

  • Optikai
  • Lyukszalagos
  • Mágnesszalagos
  • Merevlemezes
  • Memória-adatbázis

 

Előnyei

  • Felhasználói felület az adatokhoz
  • SQL általános nyelvből alakultak ki a lekérdező nyelvek
  • Funkcionalitás bővíthető
  • Elosztott rendszerek megvalósíthatóak

 

Hátrányai

  • Bonyolultak: Logikai, halmazkezelési ismeretek szükségesek
  • Lekérdező nyelvet ismerni kell
  • Nő az adattároláshoz és az adatbázis kezelőhöz szükséges tárterület szükséglet.

 

Adatbázisok: Szolgáltatás alapú források

A szolgáltatás alapú források alá tartoznak azok az adatbázis elérések, melyeket egy interfészen keresztül érhetünk el egy másik szerveren, mely akár a világ másik felén is lehet. Még a mai napig is leginkább SOAP protokollon keresztül vagy a fejlesztéseknek hála, valamilyen REST szolgáltatáson keresztül tudjuk az adatokat elérni és manipulálni.

A SOAP interfészen keresztül történő elérés legnagyobb hátránya, hogy az interfész bonyolult és részletes, szemben a REST interfésszel, mely sokkal egyszerűbb és kényelmesebb. A biztonság szempontjából a SOAP kliens volt korábban a megbízhatóbb, azonban az SSL kapcsolatokkal és egyéb titkosítási algoritmusokkal most már azonos megbízhatósági szintre került a két interfész.

A mobil alkalmazások fejlődési iránya azt mutatja, hogy szolgáltatás alapon érik el a távoli adatbázisokat, leginkább REST kliensként, mivel az adatbázisok méretei miatt ezek készüléken elhelyezése és feldolgozása hardver- és szoftverteljesítmény szempontjából sem lenne ideális.

 

Előnyei

  • Teljesítmény: Kisebb teljesítmény is elegendő az alkalmazás futtatásához
  • A REST alapú szolgáltatások interfésze egyszerű (HTTP kérések), jól érthető és kicsi erőforrásigényű a JSON alapú formátum könnyen kezelhető, akár már frontend szinten is.
  • A SOAP protokoll dokumentáltsága és hibajelzése kiforrottabb
  • Az általános biztonság SSL tanúsítványokkal megvásárolható

 

Hátrányai

  • A SOAP alapú szolgáltatások interfésze összetett, bonyolult, a fejlesztések drágák és az XML formátum miatt nehézkes a feldolgozása
  • A hálózati kommunikáció bizonytalanságai miatt lassú, elérhetetlen lehet
  • A hálózati kommunikáció miatt a biztonság nem 100%-os, további titkosítási algoritmusokra lehet szükség

 

 

magento külső adatbázis rest, soap

 

Adatbázisok: Külső alkalmazás források

A vállalatirányítási rendszerek adatbázisai nem különülnek el a külső adatbázisoktól, azonban mégis összetettebbek, nagyobbak (méret) lehetnek, mint más célirányosan összerakott adatbázisok. Mivel ezek az adatbázisok vállalatirányítási feladatokat látnak el, így folyamatosan frissülnek, változnak és bővülnek. Éppen ezért összetett interfészekkel rendelkeznek a külső rendszerek számára, melyek integrációja a közepestől a nagy bonyolultságú feladatig terjedhet.

Szerencsére a legtöbb ERP, CRM és PIM rendszer rendelkezik olyan modullal mely telepítése és minimális konfigurációja révén biztosítja a webáruházunkkal történő összekötést. Nagyon fontos, hogy ezen rendszerek között ajánlott az azonnali, kétirányú kommunikáció kialakítása, hogy a lehető legkevesebb emberi erőforrást kelljen az adminisztrációs munkára fordítani.

 

Előnyei

  • A kommunikáció lehet teljesen automatizált, így az adminisztrációs feladatok jelentősen csökkennek
  • Egy rendszert elegendő megtanulni kezelni és figyelni
  • A legismertebb rendszerekhez történő integráció gyors és zökkenőmentes
  • Fejlett felhasználói interfésszel rendelkeznek
  • Több protokollon vagy interfészen keresztül is képesek kommunikálni

 

Hátrányai

  • A rendszerek közötti kommunikáció keresztmetszete
  • A rendszerek közötti kommunikáció hiánya esetén adatvesztés
  • Kétirányú kapcsolat és/vagy aszinkronitás nélkül túl nagy emberi erőforrásra van szükség

 

Termék- és készletváltozások

Az FMCG esetén kritikus tényező a termék- és készletváltozások azonnali, legalább naprakész frissítése. Hiszen, ha egy új termék érkezik az áruházba, annak nem biztos, hogy fontos azonnal eladhatónak lennie a webáruházban, de ha elfogy egy termék készlete, akkor azt azonnal jelezni kell a vásárló felé vagy leadni a rendelést a beszállító, raktár vagy gyártó felé.

Ez a szinkronizáció ideális esetben kétirányú, azaz mindkét oldal képes jelezni a másik oldalnak, hogy az adatok megváltoztak és automatikusan az üzleti logikának megfelelően frissíteni az adatbázisokat. Ez még két rendszer esetén is bonyolult fejlesztést igényel mind a webáruház, mind az adatbáziskezelő alkalmazás részén, de vannak olyan esetek is, amikor egy ERP, egy PIM és több webáruház összekötése a feladat.

 

Mit lehet ilyenkor tenni?

 

Első és talán legfontosabb kérdés, hogy mekkora adatmennyiségeket szeretnénk mozgatni? A teljes termékkészletet, termékeket, megrendeléseket és vevői információkat frissíteni akarjuk? Elegendő időszakosan, várólistás (queue) megoldással az adott időszakban éppen aktuális változásokat frissíteni? Azonnal frissíteni kell minden változást a rendszerek adatbázisai között?

A fenti kérdések mind-mind kulcsfontosságúak, hogy meghatározzuk, milyen szintű integrációra van szükség. Egy sekély integrációnál lehet, hogy elegendő egy napi csv/xml állomány alapú importálás a külső rendszerből a webáruházba, akár ezt automatizálva futtatni. Közepes szintű bonyolultság a várakozó listás megoldás, ahol egyik vagy másik oldal is egy sor-szervert használ a frissítésre. A mély integrációnál pedig már akár köztes rétegben történik az adatok szinkronizációja.

Az alább felsoroljuk a különbségeket az egyes módszerek között, röviden ismertetve, hogy melyik mivel járhat és mennyire komplex a fejlesztési listában.

 

1.1. Teljes adatok cseréje

Az adat mennyiségek mozgatása és frissítése szempontjából a teljes adatok cseréje az úgynevezett fapados megoldás. A termékek, megrendelések mennyisége fontos szempont ebben az esetben, mivel több tízezer termék esetén az ilyen frissítés már akár percekig is eltarthat, ami kiesést vagy termék elérhetetlenséget jelenthet a webáruházban. Éppen emiatt csak abban az esetben javasoljuk ezt a megoldást, ha a termékek vagy készlet információk frissítése viszonylag rövid ideig tart vagy jól időzíthetően az áruház forgalmához az esetlegesen elhúzódó frissítés.

 

1.2. Részleges adatok csere

A részlegesadat-kommunikáció akkor jöhet szóba, ha többször az áruház működése alatt is frissíteni kell a termék-, készlet- vagy rendelési információkat. Az időzített megoldások mellett, melyek pontatlansága okozhat problémát az azonnali szinkronizáció is szóba jöhet, mivel a kisebb mennyiségű adatkommunikáció gyorsan végrehajtódik a rendszerben.

A készletkezelés és az FMCG típusú áruházak integrációs megoldásai pontosan ide tartoznak, mivel nem a teljes termék, csupán a darabszámok változnak.

 

2.1. Adatok áttöltésének iránya: egyirányú, kétirányú

Viszonylag egyszerű kérdés, azonban ha jobban átgondoljunk, további kérdéseket vet fel, ráadásul az integrációs költségek növekedése mellett az adatkommunikáció mennyiségét is jelentősen növelheti.

Egyirányú adatkommunikációról akkor beszélünk, ha van egy kiválasztott (master) rendszer – mondjuk egy ERP –, amelybe minden másik külső rendszer, azaz például a webáruházunk is beküldi az adatokat. A fő rendszer (ERP) pedig feldolgozza és tárolja őket, az ERP-t használó adminisztrátorok pedig a kapott adatok alapján irányítják a vállalati folyamatokat.

Kétirányú kommunikáció esetén mindkét rendszer kommunikál a másikkal és egymástól függően vagy függetlenül megadott interfészeken keresztül küldik el az adatokat. Itt már nincs alá- és fölérendelt szerep, csupán a prioritásokat kell megfelelően meghatározni vagy sorszerverekkel vezényelni a változások kezelését.

Az ERP integráció megtervezéséről ebben a cikkünkben olvashatsz: Magento ERP integráció: hogyan készítsük elő hibák nélkül

 

3.1. Adatok közvetett áttöltése

Az adatok áttöltését lehet közvetetten (manuális vagy ütemezett módon) vagy közvetlen (API interfészeken keresztül) frissítéssel megoldani. Az időszakos áttöltésnél szóba jöhet az emberi beavatkozás, aki az egyik rendszerből átemeli az adatokat a másik rendszerbe.

Ez történhet egyszerű export-import folyamatként, ahol az adatok egy állományba kerülnek mentésre (export), majd ezt az állományt a másik rendszer erre kialakított interfészén keresztül betölti az adatbázisba (import). Ez a folyamat természetesen automatizálható, ha az adott alkalmazás által kimentett adatokat a másik rendszer meghatározott időközönként (pl. cronjob) automatikusan betölti az adatbázisába.

Láthatjuk, hogy ez a módszer még az emberi tényező kivonása mellett is lassú, pontatlan és emiatt nem eredményes az FMCG szempontjából, azonban más esetekben, ahogy tapasztaltuk, elegendő lehet.

3.2. Közvetlen információcsere

Az adatok közvetett áttöltése nem éppen a legjobb megoldás a raktárkészletek kezelésére, hiszen a termékek darabszámának változását érdemes minél pontosabban szinkronizálni, így a közvetlen információcsere lehet a kézenfekvő megoldás. Ahhoz, hogy ez megvalósuljon, sokféle technológia áll a rendelkezésünkre, a Magento beépített XmlConnect, API (SOAP vagy REST) megoldásai mellett a legtöbb külső alkalmazáshoz már kész modulokat vásárolhatunk a Magento Connect-ből.

Kétségkívül az egyik legjobb megoldás, hiszen az adatok szinkronizálása azonnal, a változások bekövetkezésekor megindul, azonban, ha speciális külső alkalmazásunk van, melyhez még nincs konnektor (Magento modul), akkor az integrációs költségek jelentősen megugranak. Ne feledjük el, hogy az automatikus, azonnali megoldásokhoz az esetek nagyobb hányadában mélyintegrációra van szükség, mely a korábban leírtak szerint mind időben, mind fejlesztési költségekben nagy.

 

3.3. Automatikus vagy kézi szinkronizáció

Az előzőekben már szóba került, hogy emberi erőforrásokkal is megoldható az adatok szinkronizálása az alkalmazásaink között és ennek automatizálása is megoldható, azonban ezek az időszakos adatkommunikációk meglehetősen megnehezítik a készletek szinkronizációját. Automatikus szinkronizáció alatt itt azt az időzített feladatot értjük (pl.: cronjob), amikor a folyamatot a rendszer indítja, de helyette akár egy ember is meg tudja oldani. Ezek a jelentősen olcsóbb megoldások.

 

3.4. Aszinkron, azonnali megoldások

Az aszinkron megoldásokkal jelentősen gördülékenyebbé tehetjük a készlet- és adatszinkronizációt az alkalmazásaink között. A végtelenségig azonban még így sem lehet egyszerűsíteni a folyamatokat, hiszen az üzleti igények kötött függőségei miatt az aszinkronitás csak bizonyos feladatok vagy részfolyamatok esetén vezethet hasznos eredményre. Az azonnali adatkommunikáció pedig pontosan ugyanezen függőségek miatt nem valósítható meg 100%-osan.

A legjobb, legtisztább és egyben a legbonyolultabb megoldások közé tartozik, jelentős fejlesztési idővel és költségekkel, így ezt csak akkor érdemes választanunk, ha valóban indokolt a webáruházaink esetén.

 

Köztes réteg: Middleware, MOM

A köztes réteg (middleware), mint megoldás a készlet- és adatkommunikáció szinkronizációja az egyik leginkább fejlődő és jelenleg a legmodernebb technológiai megoldás, mind hardver, mind szoftver téren. Egy olyan megoldásról (szoftver és hardver) beszélünk, mely az alkalmazásaink közé ékelődve külső beavatkozás nélkül, az előre meghatározott üzleti logika alapján megvalósítja az adatkommunikációt.

 

magento külső adatbázis middleware

 

Tulajdonképpen egy félig intelligens rendszer, melyen keresztül az adatok áramlanak és eljutnak egyik alkalmazásunkból a másikba, attól függően, hogy éppen mely üzleti folyamat, mely részén tartanak.

Tekinthetünk úgy rá, mint egy hatalmas labirintusra, melynek egyes ki- és bejáratainál az alkalmazásaink találhatóak és az adatok a labirintuson keresztül jutnak el a másik alkalmazás kapujához, hogy közben a falakon lévő szabályokat követik. Az áthaladás közben az adatok átalakulnak a kívánt formátumba és a fogadó félnek megfelelő adatstruktúrát veszik fel, így nincs szükség alkalmazásainkban az adatok transzformálására.

Ezek a köztes szoftverek külön szerverekből állnak, olyan kiegészítő technológiákkal, mint az Üzenetorientált köztesréteg (Message Oriented Middleware), Redis memória alapú gyorsítótár és egyéb szoftveres és hardveres megoldások a köztes réteg támogatására. A köztes rétegek ma már a felhőben helyezkednek el, memória-alapú szervereken, melyek API interfészei a legtöbb webáruházhoz illeszkednek. A piacon már elérhetőek kész megoldások, melyekkel könnyedén integrálhatjuk rendszereinket és összehangolhatjuk a folyamatainkat az egyes rendszerekben.

Ezek a megoldások az általános üzleti folyamatokra épülnek, és többé-kevésbé személyre szabhatóak, azaz jól illeszkednek az általános, nem speciális üzleti igényeket kiszolgáló webáruházakhoz. Vegyük azonban figyelembe, hogy ha az üzleti folyamataink speciálisak és eltérnek az adott alkalmazás általános üzleti folyamataitól, akkor az integráció is egyedileg, személyre szabottan fog ideálisan működni.

 

magento external databases connection fmcg infographics

Konklúzió

Az FMCG kezelésére rengeteg megoldás létezik és ezekből a számunkra megfelelő megoldásokat kiválasztva egy olyan optimális rendszert építhetünk fel, mely kiszolgálja Magento webáruházunkat. A döntés szempontjából fontos kritériumokat a fentiek alapján meg tudjuk határozni, így ki tudjuk választani a kézenfekvő megoldást.

Ne feledjük el azonban, hogy a hosszú távú célok és az adott piaci szegmens ismerete nélkül, ha a legegyszerűbb és (nem biztos, hogy) a legolcsóbb megoldás választjuk, könnyen megeshet, hogy az integrációs költségeket többször is meg kell majd fizetnünk.

Ha bizonytalan a döntésben, írjon nekünk vagy hagyjon kommentet, és segítünk kiválasztani a megfelelő technológiát és megoldást, ezzel jelentős költségeket megtakarítva cégének.

 

Magento javítócsomagok, patch fájlok – miért fontosak?

Miről lesz szó a cikkben?

  • Mik azok a patch-ek? Milyen fajtáik vannak?
  • Miért fontosak a javítócsomagok?
  • Magento javítócsomagok és fontosságuk
  • Foltok vagy verzió frissítés?
  • Hogyan kell telepíteni Magento 1 és Magento 2 alatt a javítócsomagokat?
  • Javítócsomagok ellenőrzése
  • Telepítsük vagy ne telepítsük?
  • Konklúzió

 

Mik azok a patch-ek (foltok)?

Javítócsomagok: Egy-egy szoftver fejlesztése során gyakran előfordul, hogy a fejlesztőknek soron kívül kell módosításokat eszközölniük. Ilyenkor a szoftvefejlesztők különféle szoftver frissítések segítségével javítják a program kiadása utáni hibákat, hiányzó adatokat, biztonsági réseket, azaz a bug-okat.

 

A javítócsomagok (service packs) tartalmazzák a javított állományok teljes egészét, míg a nyílt forráskódú szoftverek esetén a foltokban (patch) csak az eltéréseket leíró állományokat teszik közzé. A Magento hivatalosan foltokat ad ki a hibák javítására.

 

 

Magento patches emblema

 

A foltok (patch-ek) előnye, hogy valóban csak a változtatásra szoruló kód sorokat módosítják, és egyszerre több, régebbi szoftver verzióval is kompatibilisek lehetnek, hátrányuk viszont, hogy némi plusz szakértelem és gyakorlat szükséges az alkalmazásukhoz.

Éppen emiatt a különbség miatt a javítócsomagok mérete nagyobb lehet, mint az eredeti alkalmazás állományaié, szemben a folttal, ami csak a különbségeket tartalmazza, melyek esetében olyan futtatható állományokról van szó, amelyek automatikusan módosítják az alkalmazás állományait.

Elengedhetetlen feltétel még, hogy a folt és a javítócsomag is csak a megadott verziójú alkalmazáshoz használható, ezt általában feltüntetik a csomag nevében és leírásában is.

 

Miért fontosak a foltok (patch-ek)?

A foltokkal és a  javítócsomagokkal elsősorban az elkészült alkalmazások hibáit, adat hiányait vagy biztonsági réseit javítjuk. Éppen ezért kiemelten fontos, hogy figyelemmel kísérjük az egyes alkalmazások újabb javítócsomagjainak megjelenését, hírlevél, RSS hírcsatorna, közösségi média vagy az alkalmazásba épített értesítő felületen (pl.: adminisztrációs oldal) keresztül. A szoftverfejlesztésben a foltok és  javítócsomagok lehetnek nem hivatalos (unofficial) forrásúak, biztonsági típusúak (security) és kiemelten fontos (hot) javítások.

magento patch folt illusztráció

tips FONTOS: Mindenképpen kötelezően ajánlott telepíteni a biztonsági javításokat, mivel ezek az alkalmazás sebezhetőségének hibáit hivatottak javítani. Ha egy biztonsági javítás megjelenik az alkalmazásunkhoz, akkor azt a lehető leggyorsabban telepíteni kell. Fontos megjegyezni, hogy ezeket a biztonsági javításokat csak megbízható (official) forrásból telepítsük, mivel csökkentenénk az alkalmazás biztonságát más forrásokból származó kártékony foltozással.

A hot (dinamikus szoftver fejlesztés) típusú javításokat az alkalmazás futása közben is telepíthetjük, mivel nem okoznak rendszer hibákat, újraindulást vagy rendszerleállást.

A nem hivatalos forrásból származó javítások, ahogy a nevük is mutatja, nem kereskedelmi javításai egy kereskedelmi alkalmazásnak, amit egy harmadik félen keresztül az eredeti fejlesztő adott ki.

 

magento patches security center biztonság

 

Milyen javítócsomagok jöttek ki és miért fontosak?

A Magento – és általában a legtöbb nagy közösséggel és felhasználói táborral rendelkező e-kereskedelmi szoftvergyártó – értesíti a felhasználóit, ha újabb frissítés vagy verzió került kiadásra. A Magento esetén hírlevél formájában a regisztrált fiókunkon keresztül, valamint az adminisztrációs felületre belépve egy figyelmeztető üzenet formájában is értesülünk ezen megjelenésekről.

 

magento patches message box magento1 üzenet

Figyelmeztető üzenetek Magento 1 adminisztrációs felületen

 

magento patches rendszer üzenet, magento2

Magento 2 adminisztrációs felületen a figyelmeztető üzenetek megjelenése

 

A Community Edition javítócsomagokat a Magento hivatalos oldaláról tölthetjük le a következő lépéseket végrehajtva:

  1. Jelentkezzünk be fiókunkkal a magentocommerce.com/download linken.
  2. Az oldal jobb felső részében kattintsunk a My Account Ha nincs még fiókunk, hozzunk egyet létre a regisztrációval – ez a lépés teljesen ingyenes.
  3. A Magento Community Edition Patches részben válasszuk ki az általunk telepíteni kívánt patch-et.
  4. A listában a patch mellett válasszuk ki a saját CE verzió
  5. Kattintsuk a Download-ra.
  6. Ha készen vagyunk a letöltéssel, következhet a telepítés.

 

Az Enterprise Edition javítócsomagokat szintén a Magento hivatalos oldaláról tölthetjük le a következő lépéseket végrehajtva:

  1. Jelentkezzünk be fiókunkkal a magentocommerce.com/download linken. Az oldal jobb felső részében kattintsunk a My Account linkre.
  2. A bal oldali panelen válasszuk a Downloads
  3. Kattintsunk a Magento Enterprise Edition szövegre a jobb oldali részben.
  4. Kattintsunk a Support Patches-re.
  5. Keressük meg a megfelelő patch-et.
  6. Kattintsunk az általunk használt megfelelő verzió számú letöltésre.
  7. Ha készen vagyunk a letöltéssel, következhet a telepítés.

 

magento patches letöltés panel, Enterprise Edition

Magento EE javítócsomagok gyűjtője

 

Folt vagy verzió frissítés?

A Magento letöltési oldalán feltünteti, hogy egy-egy szoftver verzió milyen foltot tartalmaz, így adott esetben kétféle választásunk is nyílhat a javítások alkalmazására:

  • Folt integrálása
  • A teljes verzió frissítése

 

A legfontosabb tudni, hogy az új verziók a javításokon túl egyéb új és módosított funkciókat is tartalmazhatnak, melyek – különösen nagyobb verzió ugrás esetén – „eltörhetik” a működő webáruházunkat. A biztonsági javításoknál a Magento fejlesztői arra törekednek, hogy a kódot a célnak megfelelően csak a szükséges mértékben módosítsák, így néhány kivételtől eltekintve foltozás után a webáruházunk jó eséllyel ugyanúgy fog működni, mint előtte. Ha a folt mégis visszafelé inkompatibilis hibát tartalmaz, azt a szoftverfejlesztő jelzi az adott foltnál vagy a verzió frissítésnél.

 

Hogyan kell telepíteni a javítócsomagokat Magento 1 alatt?

Mindegyik Magento verziónál adott a lehetőség, hogy a legfrissebb verziót – amely már tartalmazza a korábbi javítócsomagokat is – egyetlen állományként letöltsük a weboldalról és felülírjuk vele a már meglévő Magento verziónkat. Mivel feltételezzük, hogy a fejlesztők a szabályos moduláris kiterjesztéseket használták és a Core állományokat kiterjesztve érintetlenül hagyták, ezért ezzel nem okozhatunk problémát.

Azonban nézzük csak meg a Magento 1.9.2.4 (2016-02-23) telepítőjét: 109.4 MB, 14310 file, a 33.5MB-os ZIP állomány kitömörítése közel 1 percet vesz igénybe! Ha ezeket az állományokat fel szeretnénk másolni a szerverünkre, akkor a kapcsolat sebességétől függően akár fél óráig is eltarthat, ha közben még összehasonlítást is végzünk, akár órákra is emelkedhet ez az idő. Ez pedig közel sem ideális.

A foltok a maguk méretében kicsik (néhány kB-tól a pár száz kB-osig) és csupán a szükséges állományok megfelelő sorait cserélik ki a javított kódra. Ezek a szekvenciális állományok lépésről lépésre hajtják végre a feladatokat és végzik el a foltozást.

Ha ezt a megoldást használjuk, akkor mindenképpen figyeljünk arra, hogy a jelenlegi Magento-nk milyen verzióját használjuk és a hozzá tartozó patch fájlt futtassuk le.

 

# 9. Track patch applying result
echo "Patch was applied/reverted successfully."
ADDITIONAL_INFO=`$SED_BIN -n ""$ADDITIONAL_INFO_LINE"" "$CURRENT_DIR""$BASE_NAME"`
APPLIED_REVERTED_ON_DATE=`date -u +"%F %T UTC"`
APPLIED_REVERTED_PATCH_INFO=`echo -n "$APPLIED_REVERTED_ON_DATE"" | ""$ADDITIONAL_INFO""$REVERTED_PATCH_MARK"`
echo -e "$APPLIED_REVERTED_PATCH_INFO\n$PATCH_APPLY_REVERT_RESULT\n\n" >> "$APPLIED_PATCHES_LIST_FILE"

exit 0


SUPEE-6482 | CE_1.9.2.0 | v1 | | Tue Jul 14 14:17:04 2015 +0300 |

__PATCHFILE_FOLLOWS__
diff --git app/code/core/Mage/Api/Model/Server/Adapter/Soap.php app/code/core/Mage/Api/Model/Server/Adapter/Soap.php
index 0f9a3fa..1ac0d57 100644
--- app/code/core/Mage/Api/Model/Server/Adapter/Soap.php
+++ app/code/core/Mage/Api/Model/Server/Adapter/Soap.php
@@ -233,9 +233,9 @@ class Mage_Api_Model_Server_Adapter_Soap
 : $urlModel->getUrl('*/*/*');
 
 if ( $withAuth ) {
- $phpAuthUser = $this->getController()->getRequest()->getServer('PHP_AUTH_USER', false);
- $phpAuthPw = $this->getController()->getRequest()->getServer('PHP_AUTH_PW', false);
- $scheme = $this->getController()->getRequest()->getScheme();
+ $phpAuthUser = rawurlencode($this->getController()->getRequest()->getServer('PHP_AUTH_USER', false));
+ $phpAuthPw = rawurlencode($this->getController()->getRequest()->getServer('PHP_AUTH_PW', false));
+ $scheme = rawurlencode($this->getController()->getRequest()->getScheme());
 
 if ($phpAuthUser && $phpAuthPw) {
 $wsdlUrl = sprintf("%s://%s:%[email protected]%s", $scheme, $phpAuthUser, $phpAuthPw,
diff --git app/code/core/Mage/Catalog/Model/Product/Api/V2.php app/code/core/Mage/Catalog/Model/Product/Api/V2.php
index ff71ec5..46fc492 100644
--- app/code/core/Mage/Catalog/Model/Product/Api/V2.php
+++ app/code/core/Mage/Catalog/Model/Product/Api/V2.php

 

Példa: SUPEE-6482_CE_1.9.2.0_v1 sh állományból

 

Patch telepítése .sh állományból lépésről lépésre

A következő lépéseket követve tudja telepíteni az.sh kiterjesztésű foltot a Magento-jához – ha a kiterjesztése .patch lenne, akkor először látogasson el a Magento Support-hoz.

 

1) Másolja fel az .sh állományt a Magento telepítés gyökerébe.

sh patch-file-name.sh

 

2) Adja ki a következő parancsot egy olyan felhasználóval, aki képes írni a Magento állományokat.

Ha a folt sikeresen telepítésre került a következőhöz hasonló üzenetet fog kapni:

Patch was applied/reverted successfully.

 

3) A telepítés után vissza kell szereznie a jogosultságait a módosított állományok felett:

A) Keressük meg a webszerver felhasználóját:

ps -o “user group command” -C httpd, apache2

A USER oszlopban szereplő érték lesz a webszerver felhasználója.

B) root felhasználóként adjuk ki a következő parancsot a Magento telepítési gyökér könyvtárban:

chown -R web-server-user-name .

 

Hajtsunk végre minden további instrukciót, amit a Magento Support írt.

 

Patch visszavonása

Ha a foltozás során hiba lépett fel, akkor a következő lépéseket hajtsuk végre és vegyük fel a kapcsolatot a Magento Support-tal:

  1. Lépjen be a Magento telepítés gyökér könyvtárába.
  2. Adja ki a következő parancsot egy olyan felhasználóval, aki képes írni a Magento állományokat:
sh patch-file-name.sh -R

 

Hogyan kell telepíteni a javítócsomagokat Magento 2 alatt?

A Magento 2.0.4 (2016-03-31) telepítője: 224 MB, 41458 file, a 69.4MB-os ZIP állomány kitömörítése kb. 2-3 percet vesz igénybe! Ha ezeket az állományokat fel szeretnénk másolni a szerverünkre, akkor a kapcsolat sebességétől függően akár egy óráig is eltarthat, ha közben még összehasonlítást is végzünk, több órára is megnövekedhet ez az idő. Ez, ahogy az 1.9.2.4-es verziónál is megállapítottuk, nem ideális.

A Magento 2-es verziónál a frissítéseket Composer segítségével vagy a GIT repository-ból tölthetjük le és telepíthetjük parancssorból. Telepítéskor pedig lehetőségünk van rá, hogy egy varázsló segítségével lépésről lépésre haladva frissítsük rendszerünket.

 

Hogyan ellenőrizhető, hogy telepítésre kerültek a javítócsomagok?

Miután a foltok és javítócsomagok telepítése megtörtént, fontos lehet ellenőrizni annak helyességét, erre két módszert is tudunk javasolni:

  1. A http://magereport.com oldalon adjuk meg a Magento webáruházunk URL-jét és részletes elemzést kapunk arról, hogy milyen javítócsomagok vannak telepítve és milyen javításokra van még szükségünk.
  2. Az .sh állományokban szereplő kód részleteket azonosítva ellenőrizhetjük, hogy a kódbázis frissítése megtörtént-e.

 

Miért nem jó, ha nem telepítjük a javítócsomagokat?

A Magento közösség gőzerővel dolgozik azon, hogy Magento webáruházunk megfeleljen minden igénynek és az esetlegesen felmerülő biztonsági hibákat orvosolják. Hiszen, mint minden szoftver esetén, hiába a sok tesztelés, a használat folyamán derülnek ki olyan hibák, amelyek problémákhoz vezetnek.

A javítócsomagok ezeknek a hibáknak a javításaira adnak gyors megoldást, ráadásul a később érkező verziókba ezek már belekerülnek és így egy javított, biztonságosabb verziót telepíthetnek a felhasználók. Ez a folyamat hosszú, hiszen ahogy egyre többen használják a szoftvert, egyre több igény merül fel és egyre jobban kiderülnek azok az apróságok és megvalósítási problémák, melyek az elején még nem jelentkeztek.

 

Nézzünk rá egy egyszerű példát

Magento CE SUPEE-5344 SHOPLIFT BUG PATCH

 

A patch 2015. február 19-én jött ki, Netanel Rubin jelentette, részletes leírása megtalálható a fenti linken. Javításra kerül a CE 1.9.1.1 verzióban és minden korábbi webáruházat érint, valamint az EE verziót is az 1.14.2.0-ás verziószámig.

Ez egy biztonsági folt, amely megakadályozza, hogy az adminisztrációs oldal átirányítási rendszerében szereplő extra paramétert kihasználva valaki adminisztrációs felhasználókat hozzon létre vagy malware-t telepítsen a rendszerbe. A patch hasznosságának értéke 9.1 (kritikus), ami azt jelenti, hogy veszélyben van a webáruházunk, hiszen aki ismeri a sebezhetőséget akár a teljes uralmat átveheti felette!

Ha belegondolunk, hogy mennyi információt lehet az adminisztrációs felületen megszerezni, akkor láthatjuk, hogy ennek a foltnak a telepítése valóban kritikus webáruházunkban.

 

Konklúzió

A webáruházunk egy szoftver, így rendelkezik egy életciklussal, egy fejlődési úttal és sokszor tartalmazhat hibákat, bugokat vagy biztonsági réseket. Ezeket a Magento mögött álló hatalmas közösség gyorsan, pontosan próbálja orvosolni, így azonnal foltokat (patch) vagy javítócsomagokat adnak ki, melyeket mindenképpen érdemes telepíteni. Az újabb verzióban beépítik ezeket a javításokat, így egy megbízhatóbb és stabilabb rendszert kapunk, ha a legújabb verziót használjuk fel.

Fontos azonban, hogy figyelemmel kövessük a megjelenő patch-eket és újabb verziókat – telepítsük is őket azonnal –, mert a biztonsági réseken keresztül rosszindulatú hackerek férhetnek hozzá áruházunk adataihoz vagy vehetik át felette az uralmat. Legyünk naprakészek és ne sajnáljuk az időt, pénzt és energiát, hogy befoltozzuk ezeket a réseket.