Issue with Laravel orderby

2019-07-23 16:08发布

问题:

I am trying to order my products by price once the client click order by inside the product page. I keep getting the next error: Undefined index: title (View: C:\xampp\htdocs\eshop\resources\views\content\item.blade.php) . My 'item.blade.php' is the page that shows the larger size of the product in separate page. I think the issue is inside my controller Item function or im my model getItem function , I might be wrong... would appreciate if you could help me out .Thanks

My Route :

Route::get('shop/{category_url}/sorting-{sort?}', 'ShopController@products'); 

My view in content.products:

 @if($products)   

   <br><br> 
   <a href="  {{ url('shop/'.$category['url'].'/sorting-asc')}}" style="color:black"> High to low</a> |
  <a href="  {{ url('shop/'.$category['url'].'/sorting-desc')}}" style="color:black">Low to high</a>  

My item.blade.php:

@extends ('master') 

@section('content') 
<div class="row"> 
    <div class="col-md-12 text-center"> 
    @if('item') 
    <h1>{{ $item['title']}}</h1>  
    <p><img width="500" src="{{ asset ('images/' . $item['image'])}}" </p>  
    <p>{!! $item['article'] !!}</p>
    <p><b>Price on site:</b>{{ $item['price']}}$</p> 
    <p>  
        @if(Cart::get($item['id']))  
        <input disabled="disabled" type="button" value="In Cart!" class="btn btn-success">
        @else 
        <input data-id="{{ $item['id']}}" type="button" value="+ Add to cart" class="btn btn-success add-to-cart"> 
        @endif

        <a href="{{ url('shop/checkout') }}" class="btn btn-primary">Checkout</a> 
    </p>
        @else 
        <p class="text-center" style="font-size: 18px">No product details ...</p>  
    @endif 
    </p>
@endsection

My Controller:

public function products(Request $request, $category_url, $sort= 'ASC'){
   Product::getProducts($category_url, self:: $data);
    $catsort = Categorie::where('url', '=', $category_url)->first();
    $products = Product::where('categorie_id', $catsort->id)->orderBy('price', $sort)->get(); 
    return view('content.products', self::$data ,['products' => $products, 'sort' => $sort]); 
}  

 public function item($category_url, $product_url){ 

       Product::getItem($product_url, self::$data);   

       return view('content.item', self::$data);
   }  

My Model:

static public function getProducts($category_url, &$data){

    $data['products']=$data['category']=[];


    if ($category=Categorie::where('url','=', $category_url)->first()){

        $category= $category->toArray();
        $data['category']=$category;
        $data['title']=$data['title']. ' | ' . $category['title'];


        if ($products=Categorie::find( $category['id'])->products){

            $data['products']= $products->toArray();
        }
    }
}

static public function getItem($product_url, &$data) {


    $data['item'] = [];

    if ($product = Product::where('url', '=', $product_url)->first()) {

        $product = $product->toArray(); 

        $data['item'] = $product;
        $data['title'] .= '|' . $product['title'];  

    }
}

回答1:

So based on the chat, I'm going to try and provide an answer.

To start, we need to understand how you want to structure your database.

I can see for sure you have Products & Categories. I'm still not clear what you're trying to achieve with the $items.

So, starting with this, you have two tables. Lets think this through to determine what relationship they have. To start, ask the question, how many categories can a product have (1 or more than 1)? Most people structure categories so products can have more than one, so in Laravel, this is known as a HasMany relationship. The inverse of this is "how many products can a category have?". The answer, once again in this case, is more than 1. Therefore, instead of a HasMany relationship, this is actually a BelongsToMany relationship. A category can have many products, and a product can have many categories.

Next, you need to create a pivot table. This is a table that will store the ID of the product, and the ID of the category that have a relationship. You might create some migrations that look like this. Each of them should go in it's own migration file in the "up" method.

Schema::create('products', function (Blueprint $table) {
     $table->increments('id');
     $table->string('name');
     $table->string('slug', 100)->index();
     $table->integer('price');
     $table->timestamps();
 });


Schema::create('categories', function (Blueprint $table) {
         $table->increments('id');
         $table->string('name');
         $table->string('slug', 100)->index();
         $table->timestamps();
     });


Schema::create('category_product', function (Blueprint $table) {
         $table->increments('id');
         $table->integer('category_id')->index();
         $table->integer('product_id')->index();
         $table->timestamps();
     });

Next we need to setup the models to accept the relationship. So, in your Product.php class, add the following method.

public function categories(){
    return $this->belongsToMany(Category::class);
}

And the inverse of this in the Category.php class.

public function products(){
    return $this->belongsToMany(Product::class);
}

Now, you should be able to access your relationships like so

$category = Category::first();
$products = $category->products;

Okay, now lets get this working. Your route looks fine, though I wouldn't add the sort the way you are. You can send this in as GET data like so http://example.com/shop/test-category?sort=ASC

Route::get('shop/{category_url}', 'ShopController@products');

Okay, so now your controller.

public function products(Request $request, $category_url){
    $category = Category::with(['products' => function($q){
        $q->orderBy('price', request()->get('sort')??"ASC");
    }])->whereSlug($category_url)->first(); // Eager load in products

    return view('content.products', ['category' => $category]); 
} 

Lastly, within your blade you can now use object syntax instead of array syntax.

@section('content') 
    Category Name: {{$category->name}} <br />
    @foreach($category->products as $product)
        Product Name: {{$product->name}} <br />
        Product Price: {{$product->price}} <br />
        Product Name: {{$product->name}} <br />
    @endforeach
@endsection

Without seeing more, I can't be more specific as I'm not clear on how you're trying to handle your $items. You should set it up in the same way we setup products and categories though. Think about the relationship and determine if it's a "HasMany", "HasOne", or "BelongsToMany".

Also, there are default naming conventions you should try and follow. Your database tables should be lowercase and plural. So the table names should be exactly "products" and "categories". Your models should be singular. "Product" & "Category". No need to name it "Categorie". Then, for all pivot tables, you want to name them like the following "category_product". So singular and alphabetical order with the two tables you are pivoting on. Lastly, in your database, you'll want to make sure your pivot table columns are named "product_id" & "category_id", so the singular version of the database name + "_id".

I hope that's enough to get you going.