Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?

mgsmus Merhaba Hocam,
2 Gündür Buradaki Yazıları ve Diğer https://laravel.gen.tr/d/2771-e-ticaret-sistemi/7 Adresindeki Yazılarını Okuyorum ve Ürünler Varyasyon Olayını Çözmeye Çalışıyorum.

Urunler
+---+------------+---------------+
| ID | StokKodu | UrunAdi
+---+------------+---------------+
| 1 | DP01 | Elbise |
+---+------------+---------------+

UrunVaryasyonlar
+---+---------+------------------+
| ID | UrunID | VaryasyonAdi
+---+---------+------------------+
| 1 | 1 | Beden |
| 2 | 1 | Renk |
+---+---------+------------------+

UrunVaryasyonSecenekleri
+---+---------+-----------------+----------------+-------------+
| ID | UrunID | VaryasyonID | SecenekAdi | SkuKodu
+---+---------+-----------------+----------------+-------------+
| 1 | 1 | 1 | Small | S |
| 2 | 1 | 1 | Medium | M |
| 3 | 1 | 1 | Large | L |
| 4 | 1 | 2 | Beyaz | B |
| 5 | 1 | 2 | Siyah | S |
| 6 | 1 | 2 | Mavi | M |
+---+---------+-----------------+----------------+-------------+

UrunSKU
+---+---------+------+---------------------------+------+---------------+--------------+
| ID | UrunID | Sku | VaryasyonSecenekID| Fiyat | StokMiktari | AktifPasif
+---+---------+------+---------------------------+------+---------------+--------------+
| 1 | 1 | DP01-S-B | 1,4 | 10,00 | 5 | 1 |
| 2 | 1 | DP01-M-B | 2,4 |15,00 | 10 | 1 |
| 3 | 1 | DP01-L-B | 3,4 | 20,00 | 15 | 1 |
| 4 | 1 | DP01-S-S | 1,5 | 25,00 | 20 | 1 |
| 5 | 1 | DP01-M-S | 2,5 | 30,00 | 25 | 1 |
| 6 | 1 | DP01-L-S | 3,5 | 35,00 | 30 | 1 |
| 7 | 1 | DP01-S-M | 1,6 | 40,00 | 50 | 0 |
| 8 | 1 | DP01-M-M | 2,6 | 45,00 | 50 | 0 |
| 9 | 1 | DP01-L-M | 3,6 | 50,00 | 50 | 0 |
+---+---------+------+---------------------------+------+---------------+--------------+

Bu Şekilde Tablo Oluşturdum. "UrunSKU" Adlı Tablomun Olup Olmadığı Hakkında ve Kullanıcı İlgili Varyasyonları Seçerken Bu Tablo İle Stok Kontrolü ve Fiyat Kontrolünü Yapabilir miyim Bilemedim.

VaryasyonSecenekID Ne İçin Yaptınız Diye Soracak Olursanız;
Kullanıcı Varyasyon Secimi Yaptığında Karsısına O Varyasyonla Birlikte Secilecek Olan 2. Varyasyon Varsa 3.Varyasyon Hatda Varsa 4.Varyasyonları Listelemek İçin Karşılastırma İşlemini Yapabilmek İçin Oluşturdum.

Tabi Bu İşlemleri Yapıp Yapamayacağım Konusunda Kafamda Oturmuş Net Bir Durum Yok.

Bu Konu Hakkında Yardımcı Olabilir misiniz ?

    kadirakkus9 Tablo isimlendirmeleriniz çok karışık ve bazı yerler farklı olmuş. Aslında farklı bir cevap yazacaktım ama sildim. Ben size temel tabloları yazayım:

    categories
    Ürün kategorileri.

    +----+-----------+-----+-----+-----------+
    | id | parent_id | lft | rgt |   name    |
    +----+-----------+-----+-----+-----------+
    |  1 |           |   1 |   6 | Erkek     |
    |  2 |         1 |   2 |   5 | Giyim     |
    |  3 |         2 |   3 |   4 | Üst Giyim |
    +----+-----------+-----+-----+-----------+

    Burada Nested Set veri yapısı kullanılıyor, forumda aratabilirsiniz. Örneğin bu tabloya göre Erkek kategorisinin içinde hangi kategoriler var derseniz (ve Erkek kategorisini de sonuca dahil ederseniz)

    SELECT *
    FROM categories
    WHERE lft >= 1
      AND rgt <= 6
    ORDER BY lft

    şeklinde sorgu atılır. Bu sorgu size şunu döner:

      1   Erkek      
      2   Giyim      
      3   Üst Giyim  

    ve mesela şunu yapmanıza olanak tanır:

    Erkek > Giyim > Üst Giyim 

    Bu yapıyı Laravel'de kolayca kullanmak için şu paketi kullanıyorum:
    https://github.com/lazychaser/laravel-nestedset

    Yapıyı resimle anlatmak gerekirse (lft ve rgt nedir mesela):

    products
    Ana ürünler

    +----+---------+
    | id |  name   |
    +----+---------+
    |  1 | T-Shirt |
    +----+---------+

    product_categories (pivot)
    Hangi ürün hangi kategoride

    +------------+-------------+
    | product_id | category_id |
    +------------+-------------+
    |          1 |           3 |
    +------------+-------------+

    attributes
    Ürün özellikleri

    +----+-------+
    | id | name  |
    +----+-------+
    |  1 | Beden |
    |  2 | Renk  |
    +----+-------+

    attribute_values
    Özellik değerleri

    +----+--------------+---------+------+
    | id | attribute_id |  name   | code |
    +----+--------------+---------+------+
    |  1 |            1 | S       | S    |
    |  2 |            1 | M       | M    |
    |  3 |            2 | Kırmızı | KRM  |
    |  4 |            2 | Mavi    | MVI  |
    +----+--------------+---------+------+

    product_attributes (pivot)
    Hangi ürün hangi özelliğin hangi değerine sahip. Bu tabloya göre T-shirt, S beden ve kırmızı renge sahip

    +------------+--------------+----------+
    | product_id | attribute_id | value_id |
    +------------+--------------+----------+
    |          1 |            1 |        1 |
    |          1 |            2 |        3 |
    +------------+--------------+----------+

    variants
    Ürünler/Varyantlar/Varyasyonlar...

    +----+------------+-------------+-------------------------+
    | id | product_id |     sku     |          name           |
    +----+------------+-------------+-------------------------+
    |  1 |          1 | 1-S-KRM     | Kırmızı S Beden T-Shirt |
    +----+------------+-------------+-------------------------+

    shops
    Dükkanlar/Şubeler. Neden böyle bir tablo var derseniz sebebi product_stock tablosunda yazıyor:

    +----+-----------------+
    | id |      name       |
    +----+-----------------+
    |  1 | Kadıköy Şube    |
    |  2 | Beylikdüzü Şube |
    +----+-----------------+

    product_stock (pivot)
    Ürün stokları tablosu. Birden fazla şube vs olabileceği için her ürün her mağazada farklı stokta ve nadiren de olsa farklı fiyatta yer alabilir. O yüzden ayrı tabloda tutulması mantıklı (Tabloya göre Beylikdüzü mağazasında Kırmızı S beden t-shirt stokta kalmamış)

    +---------+------------+------------+----------+-------+
    | shop_id | product_id | variant_id | quantity | price |
    +---------+------------+------------+----------+-------+
    |       1 |          1 |          1 |       17 | 29.95 |
    |       2 |          1 |          1 |        0 | 29.95 |
    +---------+------------+------------+----------+-------+

    Senaryo:

    • Kullanıcı ürün detay sayfasına geldi. product_id=1 yani hangi ürün olduğunu biliyoruz.
    • Hangi ürün olduğunu bildiğimiz için product_attributes tablosundan product_id=1 olan özellikleri alıp ekrana gösterdik. Detay sayfasında şimdi sırasıyla Beden ve Renk gösteriyoruz.
    • Bu beden ve renk altında attribute_values tablosunda yer alan değerleri gösteriyoruz ama bunu yaparken sadece product_attributes içinde yer alan value_id'lerine göre listeletiyoruz. Yani beden altında S; renk altında ise sadece Kırmızı listelendi.
    • Kullanıcı S seçti, Kırmızı seçti. S'nin kodu S, Kırmızının kodu KRM, product_id ise 1. Şu an aslında SKU kodunu tekrar oluşturmam için tüm veri var. Hepsini - ile, sırasını bozmadan birleştirince 1-S-KRM elde ettim.
    • Elde ettiğim bu 1-S-KRM kodu ile variants tablosuna where sku = '1-S-KRM' şeklinde sorgu atarak seçilen özelliklere denk gelen varyantı buldum.
    • Sepete ekledim.

    Bu varyant elde etmenin başka yolları da var. Herkes kendi sistemine, tablo yapısına göre kodluyor. Sizin VaryasyonSecenekID olayı mantıklı, kullanabilirsiniz. Örneğin şöyle bir pivot tablo da tutulabilir:

    variant_attribute_values

    +------------+----------+
    | variant_id | value_id |
    +------------+----------+
    |          1 |        1 |
    |          1 |        3 |
    +------------+----------+

    ya da product_attributes tablosuna variant_id eklenebilir.

    SKU kodu otomatik oluşan bir kod olmalı ve tersten tekrar oluşturulabilmeli. Bu kod müşterinin gireceği bir kod değil. Varsa öyle bir kod, barkod gibi, onu ayrı bir alanda tutmalısınız.

      Hocam Cevabınız İçin Teşekkür Ederim. Tablo İsimlendirmelerini Genellikle Türkçe Kullandığım İçin Biraz Karışık Oluyor. Bu Sefer Sanırım Olayı Çözdüm. Birazdan Uygulamaya Geçeceğim. Yalnız Aklıma Bir şey Takıldı.

      Bu Durumda Kullanıcı S Bedenini Seçtikten Sonra S Bedenine Ait Kırmızı Renkteki Ürünün Stokta Olup Olmadığını Nasıl Gösterebiliriz.

      Ayrıca,

      Anlattığınız Sistemde İlerde Karşımıza Çıkabilecek Herhangi Bir Sorun Var mı ?

        kadirakkus9 Stoğu sizin yaptığınız gibi varyant tablosunda tutuyorsanız varyanta ulaştınız mı zaten stocğa da ulaşmış oluyorsunuz. Benim dediğim gibi product_stock kullanırsanız shop_id ve variant_id ile o tabloya sorgu atacaksınız.

        kadirakkus9 Anlattığınız Sistemde İlerde Karşımıza Çıkabilecek Herhangi Bir Sorun Var mı ?

        Kesinlikle Öyle Bir Şey Söz Konusu Olamaz, Garantisi Bizzat Şahsım. Bunu 4 Kişiye Daha Anlattım, Biri Hepsiburada’yı, Diğeri Trendyol’u, Bir Diğeri De Gittigidiyor’u Kurdu. 4. Kişi Bu Bana Pek Uymadı Dedi, O Da Nevzat 🙂 Tabi ki sorun vardır, siz ilerledikçe karşınıza çıkar, ben sadece kitabın önsözünü yazdım size.

        Verdiğiniz Bilgiler İçin Teşekkür Ederim Hocam.

        9 ay sonra

        Merhaba @mgsmus discount_price alanını product_stock tablosuna mı eklemek mantıklı yoksa product_discounts adında tablo açmak mı daha efektif bir kullanım olur.2. sorumda kategoride lft ve rgt migration ile biz ekliyoruz dime(nested ile bir alakası yok) lft ve rgt create ederken nasıl bir mantık ile değerlerini veriyoruz.
        3.sorum ürün url slug ile aratacağım . ürünün slug vartiantta mı tutulmalı

          echo75 İlk sorunuza cevap veremiyorum, 9 ay önce konuşulmuş bir konu, konuyu incelemem lazım.

          İkinci sorunuzun cevabı ise, ilk kategorinin left değeri 1, right değeri 2 oluyor. Aynı seviyede bir kategori ekleyeceğiniz zaman yeni kategorinin değerleri bir öncekinin left+1, right+1 oluyor. Eğer ilk kategorinin altına bir kategori ekleyecekseniz oradaki değerleri bulup +2 ekleyerek yer açıyorsunuz ve araya ekliyorsunuz. Şöyle mesela:

          SELECT @newrgt := rgt,
                 @newparentid := 1
          FROM   categories
          WHERE  id = 1;
          
          UPDATE categories
          SET    rgt = rgt + 2
          WHERE  rgt > @newrgt;
          
          UPDATE categories
          SET    lft = lft + 2
          WHERE  lft > @newrgt;
          
          INSERT INTO categories
                      (name, parent_id, lft, rgt)
          VALUES      ('Alt kategori', @newparentid, @newrgt + 1, @newrgt + 2); 

          Kısa yolu olan bir şey değil yani. Her seferinde değerlerin baştan hesaplanması gerekiyor. Ekleme, silme ve taşıma işlemleri için.

          Üçüncü sorunuzun cevabı evet, slug varyantta tutulacak çünkü sattığınız ürün o. Ana ürünün görevi sadece gruplama gibi işlemler.

            mgsmus Öncelikle geri dönüşünüz için çok teşekkür ederim.
            +----+-----------+-----+-----+-----------+
            | id | parent_id | lft | rgt | name |
            +----+-----------+-----+-----+-----------+
            | 1 | null | 1 | 6 | Erkek |
            | 2 | 1 | 2 | 5 | Giyim |
            | 3 | 2 | 3 | 4 | Üst Giyim |

            | 4 | null | 1 | 6 | Elektronik|
            | 5 | 4 | 2 | 5 | Bilgisayar|
            | 6 | 5 | 3 | 4 | Laptop |
            +----+-----------+-----+-----+-----------+

            Erkek ve Elektronik eklendim. Eleltronik için lft değerleri 1,2,3 mü olmalı yoksa. Erkek,Giyim,Üst Giyim lft degeleri 1,2,3 üzerinden devam edip 4,5,6 mi olmalı orayı tam anlayamadım
            Product_discount içinde variants tablosuna discount_id ekledim. product_discounts diye bir tablo açtım bu konuda da müsait olduğunuzda geri dönüşünüzü bekliyorum. Teşekkü ederim

              echo75

              +----+-----------+-----+-----+------------+
              | id | parent_id | lft | rgt |    name    |
              +----+-----------+-----+-----+------------+
              |  1 | null      |   1 |   6 | Erkek      |
              |  2 | 1         |   2 |   5 | Giyim      |
              |  3 | 2         |   3 |   4 | Üst Giyim  |
              |  4 | null      |   7 |  12 | Elektronik |
              |  5 | 4         |   8 |  11 | Bilgisayar |
              |  6 | 5         |   9 |  10 | Laptop     |
              +----+-----------+-----+-----+------------+

              Ürün indirimleri dediğiniz kampanyalar ise discount_id eklemeyin, ayrı bir pivot tabloda variant_id, discount_id tutun. Böylece ürüne birden fazla kampanya uygulanabilir.

                mgsmus Kategori örneği için teşekkür ederim. İndirim ürüne özel olacak, kampanyayı dediğiniz gibi ayrı bir tabloda tutacağım. Zaman zaman sorularım olacak sizi rahatsız edebilirim 😄 Teşekkür ederim hakkın ödenmez abi

                5 gün sonra

                Ürün varyasyonuna göre resim tablosu nasıl olmalı
                varyant images adında tablo oluşturup variyants id ile mi ilişkilendirmeli Yani

                id--------images_name-------------varyants_id

                1--------beyaz-t-shirt-1-.jpeg--------1
                2--------beyaz-t-shirt-2-.jpeg--------1
                3--------sari-t-shirt-1-.jpeg--------2
                4--------sari-t-shirt-2-.jpeg--------2

                Resimler varyant tablosunda da tutulabilir ama bir ürünün renk dışında da varyasyonları olabileceği için null alanlar çok olabilir.
                Değişik renkte ki ürüne ait her renk için örnek 3 resim olsa
                2 renk x 3 = 6 resim.
                Ama beden vb. attribute değerlerinde resim olmayabilir.

                Sizce doğrumu tablo yapım.

                3 ay sonra

                mgsmus variant mantığını bu şekilde 4,5 tabloda veri tutarak yapmak yerine ürün tablosunda variant adında bir sütun açıp bilgileri json olarak tutmak daha hızlı bir çözüm olmaz mı ? Deneyen var mı ?

                Örneğin ben filtreleme kriterleri için hali hazırda @mgsmus örneklerindeki mantıkla çalışıyorum. Ancak şimdi ürün tablosunda feature adında bir sütun ekleyip [14,15,16,8,9] (14:5W, 15:10W, 16:20W, 8:Beyaz, 9:Siyah) benzeri özellik ID belirterek filtrelemeleri yazıyorum.

                SELECT recordID,recordTitle,recordFeature FROM record WHERE JSON_CONTAINS(recordFeature, '[14,15]') bu şekilde basit bir sorgu ile de 5W ve 10W seçeneği olan ürünler

                SELECT recordID,recordTitle,recordFeature FROM record WHERE JSON_CONTAINS(recordFeature, '[14]') OR JSON_CONTAINS(recordFeature, '[15]') bu şekilde de 5W veya 10W seçeneği olan ürünleri listeliyorum.

                Performans olarak ne farklılık var üzerinde durmadım ama sql sorgusu ve yer yer içe içe döngü ile veri çekme çilesi yok gibi duruyor.

                Bu konudaki fikirlerinizi merak ediyorum

                Kaynak: http://www.erbilen.net/mysqlde-json-verileriyle-calismak/

                  fatihtorun RDMBS veritabanı kullanıyorsanız en rahat olacağınız yaklaşım şekli ilişkisel veri kullanmaktır. Oldu ki json içindeki bir alanın güncellenmesi gerekirse, 10 bin satırda geçiyorsa ya 10 bin satırı tek tek güncelleyeceksiniz ya bir kere yazıldı mı güncellenemez kuralı koyacaksınız ya da revizyon/versiyon sistemi geliştireceksiniz. Olaya sadece INSERT ve SELECT tarafından bakmayın; bu işin bir de UPDATE tarafı var.

                  Ayrıca RDMBS veritabanlarda json veri ile çalışmak sizi farklı indeksleme yöntemlerine, virtual column gibi yapılara yönlendirerek altyapının ilerledikçe karışmasına sebep olacaktır.

                  Benim tasviyem ilişkisel veri, kayıtlara ulaşmak için de ElasticSearch gibi 3. parti uygulamalar kullanmak. Ben JSON alanı sadece güncellenmeyeceğini düşünüyorsam ve ana başvuru kaynağım olmayacaksa kullanıyorum.

                    mgsmus Henüz düzgün bir sonuç olamadım ama mysql'e json olarak yazılmış verinin update, delete de mümkün görünüyor. Aşağıda bir örneği var.

                    İlk parametresi json verisi, 2. parametresi path yani yolu, 3. parametresi ise yeni değeri. Daha sonrasında path, value, path, value şeklinde devam ederek kullanılabilir.

                    UPDATE tablo_adi
                    SET kolon_adi = JSON_REPLACE(kolon_adi, '$.uye.ad', 'Tayfun')

                    Denemelerimde filtre seçeneklerini yönetim panelinden direk ilgili sütunu komple güncelliyorum. Spesifik olarak key belirterek de mevcut json verinin ilgili alanını da uptade/delete mümkün gibi. Tabi sanırım mysql 8 versiyon gerekiyor. Ben beceremedim🙂

                      fatihtorun Ben uyarımı yaptım, gerisi size kalmış.

                      9 ay sonra

                      Merhabalar,
                      Admin tarafında e ticaret sayfası icin ürün galerisi yapmaya calısıyorum toplu ürün yüklerken tablodaki satır iki kere tekrar saglıyor toplu image yükledigim de bir den fazla row tekrarlıyorum bu arada kod ve görsel ekliyebilirim tüm kod tek sayfada tesekkürler emeginiz ve ilginiz icin

                      ` $this->validate([
                      'title' => 'required',
                      'NewsImage.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048',
                      'product_id' => 'required',
                      ]);

                          if(!empty($this->NewsImage)) {
                              foreach ($this->NewsImage as $image) {
                                  $imageName = $image->hashName();
                                  $image->store('public/products');
                                  Image::create([
                                      'title' => $this->title,
                                      'image' => $imageName,
                                      'product_id' => $this->product_id,
                                  ]);
                              }
                          }
                          $this->modalFormVisible = false;
                          $this->reset();
                          $this->resetFields();`

                      ` @if(count($NewsImage))
                      @foreach($NewsImage as $image)
                      <td class="px-6 py-4 text-sm whitespace-no-wrap">
                      <img class="w-8 h-8 rounded-full" src="{{ \Illuminate\Support\Facades\Storage::url($Image->image) }}" />
                      </td>
                      @endforeach

                                                         @endif`

                      https://i.hizliresim.com/961q98o.png

                        mgsmus, tartışmayı kilitledi.