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

Merhabalar, @mgsmus hocamın https://laravel.gen.tr/d/3176-urun-ve-urun-detay-tablolarinin-olusumu/36 konudaki varyasyon sistemi mantığı ile sistemi oluşturdum ancak kategori filtreleme işleminde takıldığım bir nokta oldu. İlgili kodları buraya yazıyorum, yaklaşık 1 haftadır ara ara bakıp farklı yöntemler denesemde işin içinden çıkamayınca buraya başvurmak zorunda kaldım. Rahatsızlık için kusura bakmayın belki basit bir durum ama çok yöntem denedim yapamadım.

kategori filtrede url yapısı:
http://localhost:8888/xxx/public/test-kategorisi?filtre=1&renk=5|2&beden=19|3

Controller içinde url yapısını düzenleme ve yönlendirme kodu

if(request()->has('_token')){
$url = "";
if (strpos(url()->previous(), "filtre") !== false) {
$url = url()->previous()."&".$_GET["name"]."=".$_GET["value"];
}else{
$url = url()->current()."?filtre=1&".$_GET["name"]."=".$_GET["value"];
}
return response()->json($url);
}

Model içindeki filtre işleme kodu

`foreach ($GET as $get_key => $item_get) {
if( $get_key!="fiyat" ){
$resp = explode("|", $item_get);
$
GET["options_id"] = $resp[1]; // $resp[1] pivottaki options_id
$_GET["value_id"] = $resp[0]; // $resp[0] pivottaki value_id

            $whereInOptions[] = $resp[1]; $whereInValues[] = $resp[0];
            
            //$result->where( ['product_options_pivot.options_id' => strip_tags($_GET["options_id"]), 'product_options_pivot.value_id' => strip_tags($_GET["value_id"]) ] );
            $result->whereIn( 'product_options_pivot.options_id', [ implode(",", $whereInOptions) ] ); $result->whereIn( 'product_options_pivot.value_id', [ implode(",", $whereInValues) ] );

        }
        unset($_GET["options_id"]); unset($_GET["value_id"]);
    }`

Son olarak SQL çıktısı bu şekilde;
select product.*, product_variation.id as pro_var_id, product_variation.title as pro_var_title, product_variation.slug as pro_var_slug, product_variation.sku as pro_var_sku, product_variation.price as pro_var_price, product_variation.stock as pro_var_stock from product_category_pivot inner join product on product.id = product_category_pivot.product_id inner join product_variation on product_variation.product_id = product_category_pivot.product_id inner join product_options_pivot on product_options_pivot.product_id = product_category_pivot.product_id where (product_category_pivot.category_id = 27 and product_variation.show_primary = 1 and product.deleted_at is null and product.publish = 0) and (product_options_pivot.options_id = 2 and product_options_pivot.value_id = 5) and (product_options_pivot.options_id = 3 and product_options_pivot.value_id = 19);
`

tek olarak örneğin beden seçtiğimde sorunsuz getiriyor ama bedenden sonra diğer varyasyonları seçtikçe where kullandığımda 0 ürün, whereIn kullandığımda da bir önceki seçimdeki kadar veri getiriyor. Yardımcı olabilirseniz çok sevinirim şimdiden teşekkür ederim.

    mgsmus teşekkürler hocam, anlık kullandığım için request() şeklinde kullanmamıştım orayı toparlayacağım o şekilde. Buradaki sorunu nasıl aşabilirim peki 🙁

      cihanx Sorguya vs bakmaya vaktim yok ama gördüğüm kadarıyla whereIn kısmında hata yapmışsınız. whereIn() ikinci parametre olarak direkt array vereceksiniz.

      @mgsmus hocam düzenledim. Yarın konudaki kodları da düzenleyeceğim biraz daha uğraşıp. Teşekkür ederim.

        cihanx

        ?filtre=1&renk=5|2&beden=19|3

        $query = [];
        
        foreach ($request->query() as $key => $value) {
            $query[$key] = strpos($value, '|') !== false 
                ? explode('|', $value) 
                : $value;
        }
        {
          "filtre": "1",
          "renk": [
            "5",
            "2"
          ],
          "beden": [
            "19",
            "3"
          ]
        }

          mgsmus teşekkürler hocam şu şekilde aslında yapı:

          renk=5|2 ayrışmasında | ile ayırdığımda soldaki value değeri sağdaki options değeri
          pivot tablomda bu şekilde

          id
          variation_id
          product_id
          options_id
          value_id

          ilk click işleminde tek varyasyon seçimi sonrakilerinde de url üzerine ekleme yaparak gidiyorum
          yani gelen yapıda renk=5|2&beden=19|3

          options_id 2 olan ve value_id 5 olanları seçtikten sonra, beden seçildiğinde tekrar aynı noktada
          options_id 3 olan ve value_id 19 olanları seçtirmeye çalışıyorum. Burada ilk gelen verileri bir yerde tutup bunlar içerisinden seç dediğimde de sonucu sıfırlayıp çıkıyor. Kodun son hali bu:
          `
          $request_arr = request()->except("filtre");

              foreach ($request_arr as $get_key => $item_get) {
          
                  $resp = explode("|", $item_get);
                  $resp_opt = strip_tags($resp[1]); // $resp[1] pivottaki options_id
                  $resp_val = strip_tags($resp[0]); // $resp[0] pivottaki value_id
          
                  $whereInOptions[] = $resp_opt;
                  $whereInValues[] = $resp_val;
          
                  // $result->whereIn( 'product_options_pivot.options_id', [ implode(",", $whereInOptions) ] );
                  // $result->whereIn( 'product_options_pivot.value_id', [ implode(",", $whereInValues) ] );
                  $result->where( ['product_options_pivot.options_id' => $resp_opt, 'product_options_pivot.value_id' => $resp_val ] );
          
                  unset($resp_opt); unset($resp_val);
              }

          `

            cihanx

            $filters = [];
            
            foreach ($request->query() as $key => $value) {
                if(strpos($value, '|') !== false) {
                    $filter = explode('|', $value);
                    
                    $filters[] = [
                        'option_id' => $filter[0],
                        'value_id' => $filter[1],
                    ];
                }
            }
            
            $result->when($filters, function($query, $filters) {
                $query->where(function($query) use ($filters) {
                    foreach($filters as $filter) {
                        $query->orWhere(function($query) use ($filter) {
                            $query->where('product_options_pivot.options_id', $filter['option_id'])
                                ->where('product_options_pivot.value_id', $filter['value_id']);
                        });
                    }
                });
            });

            Bu şöyle bir SQL oluşturur:

            WHERE (
                (product_options_pivot.options_id = 5 AND product_options_pivot.value_id = 2)
                OR (product_options_pivot.options_id = 19 AND product_options_pivot.value_id = 3)
            );

              mgsmus teşekkürler hocam olmadı buda 🙁

              Sql çıktı aldığımda ve bunu manuel çalıştırdığımda 2 ürün birden geliyor oysa sadece biri gelmesi gerekiyor çünkü 19 ID'si 40 numara bir bedene ait tek bir ürün kalıyor.

              SQL çıktısı:

              SELECT 
                  selectproduct.*,
                  product_variation.id AS pro_var_id,
                  product_variation.title AS pro_var_title,
                  product_variation.slug AS pro_var_slug,
                  product_variation.sku AS pro_var_sku,
                  product_variation.price AS pro_var_price,
                  product_variation.stock AS pro_var_stock
              FROM 
                  product_category_pivot
              INNER JOIN 
                  product ON product.id = product_category_pivot.product_id
              INNER JOIN 
                  product_variation ON product_variation.product_id = product_category_pivot.product_id
              INNER JOIN 
                  product_options_pivot ON product_options_pivot.product_id = product_category_pivot.product_id
              WHERE 
                  (
                      product_category_pivot.category_id = 27 
                      AND product_variation.show_primary = 1 
                      AND product.deleted_at IS NULL 
                      AND product.publish = 0
                  ) 
                  AND (
                      (product_options_pivot.options_id = 2 AND product_options_pivot.value_id = 5)
                      OR
                      (product_options_pivot.options_id = 19 AND product_options_pivot.value_id = 3)
                  ) 
              GROUP BY 
                  product_variation.id 
              ORDER BY 
                  product.id DESC;

              buda sorgu sonucu
              https://prnt.sc/-h8H0bw37UYN

                mgsmus değiştirdim hocam sql çıktı bu şekilde;
                selectproduct.*,product_variation.idaspro_var_id,product_variation.titleaspro_var_title,product_variation.slugaspro_var_slug,product_variation.skuaspro_var_sku,product_variation.priceaspro_var_price,product_variation.stockaspro_var_stockfromproduct_category_pivotinner joinproductonproduct.id=product_category_pivot.product_idinner joinproduct_variationonproduct_variation.product_id=product_category_pivot.product_idinner joinproduct_options_pivotonproduct_options_pivot.product_id=product_category_pivot.product_idwhere (product_category_pivot.category_id= 27 andproduct_variation.show_primary= 1 andproduct.deleted_atis null andproduct.publish` = 0) and

                (
                (product_options_pivot.options_id = 2 and product_options_pivot.value_id = 5)
                and
                (product_options_pivot.options_id = 3 and product_options_pivot.value_id = 19)
                ) group by product_variation.id order by product.id desc`

                kaç varyasyon olursa olsun 0 ürün getiriyor

                  mgsmus hocam;

                  kategori sayfamda ürünleri çekmek için $category->getProducts şeklinde modelden çağırıyorum.

                  getProducts metodu içerisi şu şekilde;
                  `public function getProducts($id = null)
                  {


                      if($id==null){ $pass_id = $this->id; }else{ $pass_id = $id; } // kategoride ki benzer ürünler için oluşturuldu
                  
                      $result = DB::table('product_category_pivot')
                          ->where(['product_category_pivot.category_id' => $pass_id, 'product_variation.show_primary' => 1, 'product.deleted_at' => null, 'product.publish' => 0])
                          ->join('product','product.id','=','product_category_pivot.product_id')
                          ->join('product_variation','product_variation.product_id','=','product_category_pivot.product_id')
                          ->join('product_options_pivot','product_options_pivot.product_id','=','product_category_pivot.product_id') ## varyasyon filtre için sonradan ekledim
                          ->select(
                              'product.*',
                              'product_variation.id as pro_var_id','product_variation.title as pro_var_title','product_variation.slug as pro_var_slug',
                              'product_variation.sku as pro_var_sku','product_variation.price as pro_var_price','product_variation.stock as pro_var_stock'
                          )
                          ->groupBy('product_variation.id')
                          ->orderBy('product.id','desc');
                  
                  
                      $request_arr = request()->except("filtre");
                  
                      if( isset($request_arr["marka"]) ) {
                          $result->join('brand_pivot', function ($join) {
                              $join->on('brand_pivot.product_id', '=', 'product.id')->where('brand_pivot.brand_id', '=', strip_tags($request_arr["marka"]));
                          });
                          unset($request_arr["marka"]);
                      }
                  
                      unset($request_arr["fiyat"]);
                  
                      $filters = [];
                  
                      foreach ($request_arr as $key => $value) {
                          if(strpos($value, '|') !== false) {
                              $filter = explode('|', $value);
                  
                              $filters[] = [
                                  'option_id' => $filter[0],
                                  'value_id' => $filter[1],
                              ];
                          }
                      }
                  
                      $result->when($filters, function($query, $filters) {
                          $query->where(function($query) use ($filters) {
                              foreach($filters as $filter) {
                                  $query->orWhere(function($query) use ($filter) {
                                      $query->where('product_options_pivot.options_id', $filter['option_id'])
                                          ->where('product_options_pivot.value_id', $filter['value_id']);
                                  });
                              }
                          });
                      });
                      
                      return $result->paginate(48);
                  }`

                    cihanx Şöyle bir deneyin. | ile ayırdığınız değerlerde value solda option sağda demişsiniz, ben ters yapmışım, onu da düzelttim. Yazdığım şeyi direkt yapıştırıp çalışmadı demeyin, ne yaptığımı anlamaya çalışın, hata yapmış olabilirim, siz kendinize uyarlamaya çalışın.

                    $filters = [];
                    
                    foreach ($request->query() as $key => $value) {
                        if (strpos($value, '|') !== false) {
                            $filter = explode('|', $value);
                    
                            $filters[] = [
                                'option_id' => $filter[1],
                                'value_id' => $filter[0],
                            ];
                        }
                    }
                    
                    $result->when($filters, function ($query, $filters) {
                        $query->where(function ($query) use ($filters) {
                            $query->selectRaw('count(*)')
                                ->from('product_options_pivot')
                                ->whereColumn('product_options_pivot.product_id', 'product_category_pivot.product_id');
                    
                            $query->where(function ($query) use ($filters) {
                                foreach ($filters as $filter) {
                                    $query->orWhere(function ($query) use ($filter) {
                                        $query->where('product_options_pivot.options_id', $filter['option_id'])
                                            ->where('product_options_pivot.value_id', $filter['value_id']);
                                    });
                                }
                            });
                        }, '=', count($filters));
                    });
                      4 gün sonra

                      mgsmus teşekkürler hocam, dediğiniz gibi ben ek olacak yerleri yada düzenlenecek yerleri düzenliyorum ancak başka bir noktada takılıyor onu bir türlü yakalayamadım. Hala da olmadı. Tekrar uğraşmaya devam edeceğim. Çok teşekkürler ilginiz ve yardımınız için.

                      6 gün sonra

                      @mgsmus hocam, join yaptığım satırları ayırıp yukarıda kullandım ve filtre yapacağım bütün durumları da return paginate satırı arasında bıraktım. Şu an ne gelirse gelsin sorunsuz şekilde sonuç veriyor. Bilgi vermek amaçlı sizi etiketledim. Çok teşekkür ederim yardımlarınız için faydası oldu. Saygılarımla