Katalog ve Ürün Sayfaları

1.7k görüntülenme Markdown

Genel kataloğun tamamını üç view taşır; zor iş, JavaScript'in hemen değiştirmeyeceği bir fiyat yazmaktır.

Genel Bakış

Katalog, bir temanın aynı sayıyı iki kez ürettiği tek bölümdür: sunucu ilk boyama için yazar, tarayıcı faturalama butonu her hareket ettiğinde yeniden yazar. Bir kuruş fark, sayfanın titremesidir.

Tutarlar çevrilmiş ve promosyonu çözülmüş gelir, yani view'a hiçbir fiyat mantığı ait değildir.

Yapı

Üç view, tek fiyat mekanizması. Kategori sayfası iki düzen taşır ve aralarında çalışma anında seçer. Fiyatlı ürün yoksa aşağıdaki dalların hepsi atlanır.

ViewCevap verdiğiAna veri
views/products/categoryHer kategori adresi, üst ve yaprak$mode, $tabs ya da $cards artı $plans, $billing_cycles, $price_mode
views/products/softwareMağaza kökü ve her mağaza kategorisi$products, $filters, $page_size, $total_count
views/products/detailTek bir yazılım ürününün kendi sayfası$product, $prices, $gallery, $included, $versions, $faq
components/plan-grid.tpl Dikey kartlar. $plans bekler ve $billing_cycles'ı üst kapsamdan okur, ikisini birden geçin.
components/plan-rows.tpl Yatay satırlar. Her planda features yerine specs ve chips bekler.
Products::catalog_plans() İki şekli de kurar; üçüncü argüman birini seçer.

Adım Adım

İki Kategori Modunu da Karşılayın

İçerik bloğunun içindeki ilk iş $mode'a dallanmak olsun.

  1. tabs: her çocuk bir yapraktır, sayfa alt aile sekmeleri ve pano başına bir ızgara gösterir. Her $tabs kaydı kendi başlığını, meta'sını, hero arka planını ve planlarını taşır.
  2. drilldown: kategorinin hem alt kategorileri hem kendi planları vardır — $cards ve $plans.
  3. Faturalama butonunu yalnız değiştirilecek bir şey varken gösterin: {if $billing_cycles|@count > 1}.

Planı Basın, Fiyat Mantığını Değil

  1. Kart öğesine plan-card, yatay yerleşimde plan-row sınıfını verin.
  2. Aşağıdaki sözleşmedeki data-* özniteliklerini ekleyin.
  3. Tükendi durumu için harekete geçirici mesajı $plan.in_stock ile değiştirin; kartı gizlemeyin.
  4. $plan.link'i geldiği gibi kullanın.

Fiyatı İki Kez, Aynı Şekilde Yazın

Sunucu sayfa boş kalmasın diye yazar, script üzerine yazar; ikisi aynı string'i üretmek zorundadır.

  1. Sunucu değerini şu düğüme basın: <span data-role="price-now">{$plan.price_now}</span>.
  2. Aylık son ekini yanına basın, dönem toplamında gizleyin: {if $plan.is_period}d-none{/if}.
  3. Türetilmiş figürleri boş bırakın — onlar script'in işi.
  4. Sayfa bağlamını sarmalayıcıya koyun.

Kategorinin Yerleşim Tercihine Uyun

Bir kategori ızgara yerine yatay satır isteyebilir; tercih $layout olarak gelir.

  1. Tek bir yerde, include'da dallanın: ya satır ya ızgara, asla yarı dönüşmüş bir kart değil.
  2. Izgara planında features vardır; satır planında specs ve chips vardır, features yoktur.
  3. value|label çifti taşımayan özellik metninde her satır çipe dönüşür ve özellik sütunları boş çıkar. Bu bir hata değil, veridir.

Referans

Tek Bir Planın Şekli

imza
public static function catalog_plans(int $categoryId, string $type, string $layout = 'grid'): array;

// $categoryId  ürünleri istenen kategori
// $type        ürün türü, yapılandırma adresinin kullandığı parçanın aynısı
// $layout      'grid' ya da 'rows'; dönen HER planın ŞEKLİNİ değiştirir
dönen listenin tek bir elemanı
$plan = [
    'id'          => 18,                 // ürün id'si
    'title'       => 'Starter',
    'tagline'     => 'İlk siteniz için',
    'popular'     => true,               // ürünün kendi seçeneklerinden
    'in_stock'    => true,               // '' stok sınırsız demek, 0 tükendi demek
    'prices'      => [                   // YALNIZ gerçekten fiyatı olan döngüler
        'monthly' => 4.90,
        'annual'  => 49.00,
    ],
    'currency'    => 'USD',              // görüntü kodu, data-currency özniteliği için
    'currency_id' => 2,                  // görüntü para birimi id'si, biçimlendirici kullanır
    'link'        => '/configure/hosting/18',
    'features'    => ['10 GB disk', '1 alan adı'],
];

// $layout = 'rows' iken son anahtar yerine iki anahtar gelir:
//   'specs' => [['value' => '10 GB', 'label' => 'Disk'], ...]   kıyaslanabilir sütunlar
//   'chips' => ['Ücretsiz taşıma', ...]                         düz satırlar

İlk Boyama Fiyatı Nasıl Üretilir

Products'taki tohumlama kuralı
public static function seed_plan_prices(array &$plans, string $cycle, bool $periodMode): void;

// $cycle       bu sayfanın varsayılan faturalama döngüsü
// $periodMode  true tam dönem toplamını basar, false aylık karşılığını basar
//
// Her plana iki anahtar ekler:
//   price_now  şablonun bastığı biçimlenmiş string
//   is_period  o string bir dönem toplamı mı ("/ay" son ekini o belirler)
//
// $cycle için fiyatı olmayan plan sıfır değil, price_now = '' alır.
// Aylık fiyatı olmayan plan, $periodMode false olsa bile dönem moduna zorlanır.

public static function plan_cycles(array $tabs): array;
// [['key' => 'monthly', 'label' => 'Aylık'], ['key' => 'annual', 'label' => 'Yıllık']]
// Yalnız sayfadaki en az bir planın gerçekten fiyatladığı döngüler. Sabit gösterim sırası.

public static function price_monthly_equivalent(): bool;
// $periodMode'un arkasındaki GENEL ayar. Kurulumun tema yapılandırmasında yaşar,
// temanızın kendi ayar şemasında DEĞİL, yani bir tema onu zorlayamaz.

data-* Sözleşmesi

Birini yeniden adlandırın, fiyat sessizce güncellenmeyi bırakır. İşleyici data-billing taşıyan her öğeyi grup, içindeki her .plan-card ve .plan-row öğesini kart sayar.

data-billing Sarmalayıcıda: $default_cycle'dan açılış döngüsü ve grup seçicisi; geçiş butonu onu değiştirir.
.plan-card ve .plan-row Kart seçicisi: ızgara birincisini, satır ikincisini kullanır. Sınıf ekleyin, bunları değiştirmeyin.
data-price-mode Sarmalayıcıda: $price_mode'dan monthly ya da period. Sayfa değeri, tema ayarı değil.
data-currency Sarmalayıcıda ve her kartta; kart kazanır, karışık para birimleri doğru biçimlenir.
data-monthly, data-annual ve diğerleri Kartta: döngü başına bir ham ondalık, |default:'' ile — fiyatsız döngü sıfır değil boş kalsın.
data-role Script'in yazdığı düğümler: price-now, price-suffix, price-was, savings, cycle-total, cycle-mo, currency-label.
data-save-text Sarmalayıcıda: kazanç rozetinin etiketi, dil dosyasından — script'in çevirmeni yok.

Faturalama Geçişi Sözleşmesi

Buton seçtiği döngüyü data-cycle içinde taşır, asla data-billing içinde değil: işleyici en yakın data-billing atasını arar, o özniteliği taşıyan buton kendi grubu olur.

data-billing-toggle Buton grubunda. Etkin sınıfı gruptaki butonlar arasında taşır, böylece birden çok geçiş bir arada durabilir.
data-action="set-billing" Her butonda. Temanın devredilmiş tıklama işleyicisi buna göre dallanır; kendi dinleyiciniz gerekmez.
data-cycle Her butonda: monthly, quarterly, semiannually, annual, biennial, triennial. $c.key'den, etiketi $c.label'dan yazın.

Örnek

controller tarafı
// controllers/website/products.php, drilldown dalı

$plans = Products::catalog_plans($categoryId, $kind, $layout);

// Genel ayar, tersine çevrilmiş: aylık karşılık AÇIK ise dönem modu KAPALI.
$period_mode = !Theme::price_monthly_equivalent();

// Sayfanın varsayılan döngüsünde her plana price_now + is_period yazar.
Products::seed_plan_prices($plans, $default_cycle, $period_mode);

$this->addData("mode",           "drilldown");
$this->addData("plans",          $plans);
$this->addData("cards",          $cards);
$this->addData("layout",         $layout);
$this->addData("billing_cycles", Products::plan_cycles([['plans' => $plans]]));
$this->addData("default_cycle",  $default_cycle);
$this->addData("price_mode",     $period_mode ? "period" : "monthly");
views/products/category.tpl ve components/plan-grid.tpl
{* Bölüm sarmalayıcısı, fiyat script'inin okuduğu sayfa düzeyi bağlamı taşır. *}
<section data-billing="{$default_cycle}" data-currency="{$selected_currency_code}" data-price-mode="{$price_mode}">

    {if $layout == 'rows'}
        {include file='components/plan-rows.tpl' plans=$plans billing_cycles=$billing_cycles}
    {else}
        {include file='components/plan-grid.tpl' plans=$plans billing_cycles=$billing_cycles}
    {/if}

</section>

{* components/plan-grid.tpl, tek bir kartın fiyat bandı *}
<div class="card plan-card{if !$plan.in_stock} plan-soldout{/if}"
     data-currency="{$plan.currency}"
     data-monthly="{$plan.prices.monthly|default:''}"
     data-annual="{$plan.prices.annual|default:''}"
     data-biennial="{$plan.prices.biennial|default:''}">

  <div class="plan-price price-band">
    {* Script doldurur. Sunucuda bilerek boş. *}
    <del class="price-was num-tabular d-none" data-role="price-was"></del>
    <span class="badge d-none" data-role="savings"></span>

    {* Sunucu basar ki ilk boyama hiç boş kalmasın, sonra script yüklemede
       AYNI string ile üzerine yazar. *}
    <span class="price-now num-tabular" data-role="price-now">{$plan.price_now|default:''}</span>
    <span class="{if $plan.is_period}d-none{/if}" data-role="price-suffix">{lang key='website/products/category-per-month'}</span>

    {* Döngü başına bir satır; toplamlar script'in işi. *}
    {foreach $billing_cycles as $c}
      <tr data-cycle="{$c.key}">
        <td>{$c.label}</td>
        <td data-role="cycle-total"></td>
        <td data-role="cycle-mo"></td>
      </tr>
    {/foreach}
  </div>
</div>

Tuzaklar

Bir kuruşluk uyuşmazlık gözle görülür bir titremedir

toFixed(2) saklanan double'ı düzeltmesiz yuvarlar, sunucu biçimlendiricisi yarımı çifte yuvarlar, PHP'nin yuvarlaması önce kayan nokta düzeltmesi yapar. Üçü beşle biten değerlerde ayrışır: 237.905 iki farklı string olur ve sayfa zıplar. Tohumlama yardımcısı sprintf('%.2f') ile ön yuvarlar; siz de aynısını yapın.

Yatay yerleşimin arkasında iki anahtar var

Panel seçimi list_template seçeneğine yazar (2 = düz); sayfa ise layout okur ve rows bekler. Aralarında eşleme yok, düz seçilmiş kategori yine ızgara görünür; ana sayfa rafı ikisini de okur.

Aylık karşılık sizin temanızın ayarı değildir

Sistem geneli bir seçenektir, tema ayarları şemasından bilerek çıkarılmıştır. Onu $price_mode üzerinden okuyun ve kendi manifestinize benzeri bir anahtar eklemeyin.

Yapıştırılan gömülü kod türetilmiş figürleri geciktirir

Kategorinin zengin metin gövdesi ham çıkar; içindeki senkron bir üçüncü parti etiketi ayrıştırmayı durdurur. Ana fiyat kurtulur çünkü onu sunucu yazmıştır, türetilmiş figürler bekler.

Stok anlıktır, planla cache'lenmez

Plan listeleri cache'lenir; stok işareti cache okunduktan sonra tazelenir. $plan.in_stock'u güncel, gerisini bir saate kadar eski kabul edin; ikisini karıştıran bir parçayı cache'lemeyin.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.