Fix: ProductRepositoryCachePlugin entfernt. Es beantwortete ProductRepository::getById()
mit einem Klon des Collection-Items, sobald dieselbe ID vorher über eine Product-Collection
geladen war. Ein Collection-Item enthält aber nur die dort selektierten Attribute und keine
Daten der ReadHandler (Optionen, Media-Gallery, Extension-Attribute). getById() lieferte
so still ein unvollständiges Produkt — z. B. Configurable::getProductByAttributes() beim
Add-to-Cart (Fatal Error bei Zugriff auf ein fehlendes Custom-Attribut) oder Templates, die
Collection-Items per getById() nachladen (Platzhalterbilder, fehlende Buttons). Der zweite
Zweig des Plugins (Ergebnis nach einem Miss ablegen) war redundant zum eigenen Cache von
ProductRepository. Wer Produkte aus einer Collection schnell braucht, selektiert die
benötigten Attribute in der Collection statt sie per getById() nachzuladen
Neu: CMS-Blöcke werden im Frontend über eine request-weite Scope-Map aufgelöst. Magento
braucht pro gerendertem Block drei Abfragen — Identifier → block_id, die Entity-Zeile und
die Store-Zuordnung des ReadHandlers. Erste und dritte beantwortet jetzt eine einzige Abfrage
über cms_block/cms_block_store (gemessen: 74 → 26 Abfragen auf einer Produktseite). Der
Inhalt wird weiterhin pro Block über den EntityManager geladen, damit ReadHandler,
Extension-Attribute und Load-Callbacks anderer Module unverändert laufen
Die Map schaltet sich über copex/performance/preloaders/cms_blocks_enabled ab, ebenso
oberhalb von copex/performance/preloaders/cms_block_map_max_rows (Default 2000 Zeilen =
Block × zugeordneter Store) und auf Staging-Schemata; in allen Fällen läuft der Shop auf
Magento-Standard weiter
Fix: Store\Model\Information::getStoreInformationObject() lud Region und Land bei jedem
Aufruf neu — zwei Abfragen gegen directory_country_region/directory_country pro CMS-Widget
mit Shop-Adresse (gemessen 21 Aufrufe = 42 Abfragen pro Seite). Das Ergebnis wird jetzt pro
Store-Id für die Dauer des Requests gehalten, jeder Aufruf bekommt weiterhin ein eigenes
DataObject
Fix: Der media-Preloader lieferte Galerie-Zeilen, die nicht der Struktur von
Gallery::createBatchBaseSelect() entsprachen — der Dateiname stand unter value statt
file, value_id und media_type fehlten ganz. ConfigurableProduct\Helper\Data::getGalleryImages()
reicht $image->getFile() an UrlBuilder::getUrl() weiter, das string erwartet: Jede
Configurable-PDP endete mit einem TypeError und HTTP 500. Die Query holt jetzt zusätzlich
value_id, file und media_type, fällt für label/position/disabled auf die
Default-Store-Werte zurück, filtert auf das media_gallery-Attribut, sortiert nach
position und entfernt Dateien, die unter mehreren value_ids hängen
ProductMediaGalleryPlugin ergänzt url, id und path und übernimmt die Filter aus
Product::getMediaGalleryImages() (deaktivierte, entfernte und doppelte Bilder); das
Ergebnis wird wie im Original am Produkt zwischengespeichert
Tests prüfen die Galerie jetzt gegen den echten Konsumenten statt gegen eine erfundene
Zeilenstruktur — inklusive Vergleich mit Magentos eigenem Ladepfad
Doku-Fix: Der Aktivierungsschalter heißt copex/performance/preloaders/enabled. Die bisher
dokumentierten Pfade copex/performance/enabled und copex/performance/preloaders_enabled
werden von keinem Modul ausgewertet — wer sie gesetzt hatte, lief ohne Preloader. Neu dokumentiert: einzelne Preloader lassen sich über preloaders/<key>_enabled abschalten
Benchmarks nehmen Store-View und SKU wieder aus der Konfiguration (copex_performance/cart_benchmark/sku, .../store_id), wenn --sku / --store nicht angegeben sind. Damit laesst sich das Paar einmalig in app/etc/env.php hinterlegen statt es bei jedem Lauf mitzugeben; eine Option sticht weiterhin den hinterlegten Wert
Benchmarks, die ein konkretes Produkt brauchen (cart_add_item, cart_update_qty, cart_get, pdp_render), nehmen Store-View und SKU jetzt aus den Optionen --store / --sku von copex:performance:benchmark (über BenchmarkParametersInterface aus module-performance-suite) statt automatischer Katalog-Ermittlung. Fehlt der Wert, brechen sie mit klarer Meldung ab
Cart-Benchmarks emulieren die Ziel-Store-View korrekt via Emulation::startEnvironmentEmulation() (statt nur emulateAreaCode). Hintergrund: Der Gast-Warenkorb-Pfad lädt das Produkt über CartItemPersister ohne Store-ID, status wird daher auf Store 0 gelesen, während die Verkaufbarkeitsprüfung in der emulierten Store-View erfolgt. Die SKU muss ein Simple-/Virtual-Produkt sein, auf Store 0 aktiviert und in der Store-View kaufbar
pdp_render-Benchmark lädt das Produkt jetzt pro Iteration frisch (ProductFactory) statt über den prozessweit cachenden ProductRepository — vorher maß der Benchmark ab der 2. Iteration nur noch Cache-Treffer (~0,3 ms / 1 SELECT), jetzt die echte Ladezeit (z. B. ~25 ms / ~40 SELECTs). Die hartkodierte Demo-SKU entfällt; das erste aktive Produkt wird automatisch verwendet
StockRegistryPlugin liefert jetzt ein echtes StockItemInterface (per Factory + DataObjectHelper) statt eines generischen DataObject — behebt den TypeError in ProductExtension::setStockItem() auf Produktlade-Pfaden (REST/AfterProductLoad). Der Stock-Preloader lädt dafür die vollständige cataloginventory_stock_item-Zeile, damit alle Felder (manage_stock, min_qty, use_config_*) erhalten bleiben
product_options-Preloader gehärtet: nur noch Existenzprüfung (eine Query statt zwei), keine ungültige price/price_type-Selektion mehr — behebt den SQLSTATE-42S22-Fehler auf Magento-2.4-Schemata; die Preisberechnung bleibt unberührt (Produkte mit Optionen laufen weiter über Magentos Standardpfad)
Benchmark-SKU wird automatisch aus dem Katalog ermittelt (erstes aktives Simple-Produkt) statt der Luma-Demo-SKU 24-MB01 — Cart-Benchmarks laufen damit auf jedem Shop