156 lines
5.6 KiB
Markdown
156 lines
5.6 KiB
Markdown
# 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 1–4. Kolejność: najpierw deploy kodu,
|
||
potem regeneracja routingu, potem czyszczenie cache, potem regeneracja feedu,
|
||
na końcu resubmit w GMC.
|