This commit is contained in:
2026-04-30 01:43:17 +02:00
parent 2114254518
commit 1994f95183
14 changed files with 2153 additions and 1251 deletions

View File

@@ -0,0 +1,155 @@
# Fix: linki produktów z permutacją atrybutów w feedzie Google → strona główna
## Problem
URL produktu z permutacją atrybutów wygenerowany do feedu Google miał format:
```
/slug-produktu/20-170/21-175
```
(dwa segmenty rozdzielone `/`). Google Merchant Center indeksował taki URL z feedu,
ale przy wejściu użytkownika serwer nie dopasowywał go do żadnej trasy w `pp_routes`
i `index.php` ładował domyślną stronę główną.
## Przyczyna
`permutation_hash` jest przechowywany w bazie jako `attr-val|attr-val` (np. `20-170|21-175`),
a w generatorze feedu Google znak `|` był podmieniany na `/` przy budowaniu linku.
Dodatkowo wzorzec routingu w `pp_routes` dla URL produktu z permutacją to
`^slug/([0-9-]+)$` — klasa `[0-9-]+` nie obejmuje `/`, więc URL ze slashem
nigdy się nie dopasuje.
## Rozwiązanie
Separatorem między parami `attr-val` w URL jest teraz `_`. Przy odczycie
`$_GET['permutation_hash']` w warstwie front podstawiamy `_` z powrotem na `|`
przed zapytaniem do bazy.
Format URL po zmianie:
```
/slug-produktu/20-170_21-175
```
## Pliki zmienione
### 1. `autoload/Domain/Product/ProductRepository.php`
W metodzie `appendCombinationToXml` (linie ~2372 i ~2374):
```php
// było
str_replace( '|', '/', $combination['permutation_hash'] )
// jest
str_replace( '|', '_', $combination['permutation_hash'] )
```
Dotyczy obu gałęzi `if/else` (z `seo_link` i fallback `p-id-name`).
### 2. `autoload/Shared/Helpers/Helpers.php`
W generatorze tras dla produktów z permutacją (linie ~694 i ~699) — rozszerzony
wzorzec regex o `_`:
```php
// było
'pattern' => '^' . ... . '/([0-9-]+)$'
// jest
'pattern' => '^' . ... . '/([0-9_-]+)$'
```
Dotyczy obu wariantów (z `seo_link` i fallback `p-id-name`).
### 3. `autoload/front/LayoutEngine.php`
W bloku `// PRODUKT` (linia ~196) — konwersja `_``|` przed przekazaniem do
`findCached`:
```php
// było
$product = ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )
->findCached( \Shared\Helpers\Helpers::get( 'product' ), $lang_id, $_GET['permutation_hash'] ?? null );
// jest
$permutation_hash = isset( $_GET['permutation_hash'] ) ? str_replace( '_', '|', $_GET['permutation_hash'] ) : null;
$product = ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )
->findCached( \Shared\Helpers\Helpers::get( 'product' ), $lang_id, $permutation_hash );
```
### 4. `templates/shop-product/_partial/product-attribute.php`
Domyślnie partial preselectuje wartości na podstawie flagi `is_default`. Po
wejściu na URL z `permutation_hash` (np. z feedu Google) UI nadal pokazywał
domyślną kombinację zamiast tej z URL. Dodane wymuszenie wyboru wartości na
podstawie `permutation_hash` z URL — jeśli atrybut jest obecny w hashu, jego
aktywna wartość pochodzi z URL; w przeciwnym razie zachowane stare zachowanie
(`is_default`).
```php
// na początku partiala — wyciągnięcie value_id dla bieżącego atrybutu z URL
$forced_value_id = null;
if ( isset( $_GET['permutation_hash'] ) && $_GET['permutation_hash'] !== '' )
{
$pairs = explode( '|', str_replace( '_', '|', $_GET['permutation_hash'] ) );
foreach ( $pairs as $pair )
{
$parts = explode( '-', $pair );
if ( count( $parts ) == 2 && (int)$parts[0] === (int)$this -> attribute['id'] )
{
$forced_value_id = (int)$parts[1];
break;
}
}
}
// w pętli foreach po values — zamiast bezpośrednio $value['is_default']:
$is_active = $forced_value_id !== null
? ( (int)$value['id'] === $forced_value_id )
: (bool)$value['is_default'];
```
`$is_active` jest następnie używane do `checked="checked"` na inpucie i do
emisji bloku `<script>` z `fradio_label_click(...)` (auto-refresh atrybutów),
zamiast dotychczasowego `$value['is_default']`.
UWAGA: jeśli sklep ma własną wersję tego partiala w `templates_user/shop-product/_partial/product-attribute.php`, zmianę trzeba zaaplikować tam (Tpl::view ma priorytet `templates_user/`).
## Po wgraniu zmian — wymagane akcje (kolejność istotna)
1. **Przegenerować `pp_routes`** — uruchomić w adminie funkcję regenerującą
routing (`Helpers::htacces()` / regeneracja sitemap), żeby nowe wzorce z `_`
trafiły do bazy. Bez tego stare wzorce `[0-9-]+` zostaną w `pp_routes` i nadal
nie zmatchują URL-a z `_`.
2. **Wyczyścić cache routingu** — w `index.php:63` cache key `pp_routes:all`
trzyma routing przez 24h (`$cache->set($cacheKey, $routes, 86400)`). Skasować
klucz w cache (Redis/plikowy) albo poczekać na expiry.
3. **Przegenerować feed Google** — uruchomić cron `cron/cron-xml.php`
(`\admin\factory\ShopProduct::generate_google_feed_xml()`), żeby `google-feed.xml`
miał nowe linki z `_`.
4. **Resubmit feedu w GMC** — po regeneracji feed musi się odświeżyć w Google
Merchant Center (automatycznie wg harmonogramu albo ręcznie „Fetch now").
5. **Stare URL-e w GMC z `/`** — same wypadną z indeksu po podmianie feedu.
Opcjonalnie można dodać redirecty 301 z `/slug/X-Y/Z-W` na
`/slug/X-Y_Z-W`, ale nie jest to konieczne — Google zaktualizuje linki z feedu.
## Walidacja
- Otworzyć URL produktu z permutacją w formacie `/slug/20-170_21-175`
powinien załadować stronę produktu z wybraną kombinacją atrybutów.
- Otworzyć `https://domena/google-feed.xml` i sprawdzić, że tagi `<link>`
używają `_` zamiast `/` między parami atrybutów.
- W GMC sprawdzić, że feed się zaciągnął bez błędów typu „Landing page error".
## Wdrożenie na innym sklepie (ten sam silnik)
Te same trzy zmiany w plikach + akcje 14. Kolejność: najpierw deploy kodu,
potem regeneracja routingu, potem czyszczenie cache, potem regeneracja feedu,
na końcu resubmit w GMC.