缺少 [Route: home.products] [URI: item/{id}/{slug}] 的必需参数

时间:2021-06-14 17:34:43

标签: php laravel laravel-8 laravel-routing

<块引用>

缺少 [Route: home.products] [URI: item/{id}/{slug}] 的必需参数。 (查看:/home/elawzsuf/website.com/resources/views/front/default/partials/top_menu.blade.php) (查看:/home/elawzsuf/website.com/resources/views/front/default/partials/top_menu.blade.php) (查看:/home/elawzsuf/website.com/resources/views/front/default/partials/top_menu.blade.php) {"userId":2,"exception":"[object] (ErrorException(code: 0):

<块引用>

缺少 [Route: home.products] [URI: item/{id}/{slug}] 的必需参数。 (查看:/home/elawzsuf/website.com/resources/views/front/default/partials/top_menu.blade.php) (查看:/home/elawzsuf/website.com/resources/views/front/default/partials/top_menu.blade.php) (查看:/home/elawzsuf/website.com/resources/views/front/default/partials/top_menu.blade.php) 在/home/elawzsuf/website.com/vendor/laravel/framework/src/Illuminate/Routing/Exceptions/UrlGenerationException.php:17)

网络:

Route::get('item/{id}/{slug}', 'HomeController@product')
->name('home.product');

控制器:

 public function product(Request $request)
{
  $user_id = request()->user()->id ?? 'null';

  $product = Product::by_id($request->id, $user_id);

  $product->getAttributes() || abort(404);

  if(mb_strtolower(urldecode($request->slug)) !== mb_strtolower(urldecode($product->slug)))
  {
    return redirect(item_url($product));
  }

  $product->remaining_downloads = null;

  if($promotional_price_time = json_decode($product->promotional_price_time))
  {
    $promotional_price_time->from = format_date($promotional_price_time->from, 'Y-m-d');
    $promotional_price_time->to   = format_date($promotional_price_time->to, 'Y-m-d');

    $product->promotional_price_time = json_encode($promotional_price_time);
  }

  $product_prices = Product_Price::selectRaw("product_price.*, licenses.name as license_name, licenses.regular,
                    products.promotional_price_time IS NOT NULL as has_promo_time,
                    IF(product_price.promo_price IS NOT NULL AND DATE_FORMAT(CURRENT_TIMESTAMP, '%Y-%m-%d') BETWEEN STR_TO_DATE(SUBSTR(products.promotional_price_time, 10, 10), '%Y-%m-%d') and STR_TO_DATE(SUBSTR(products.promotional_price_time, 28, 10), '%Y-%m-%d'), products.promotional_price_time, null) AS promotional_time")
                    ->leftJoin('licenses', 'licenses.id', '=', 'product_price.license_id')
                    ->join('products USE INDEX(primary)', 'products.id', '=', 'product_price.product_id')
                    ->where('product_id', $product->id)
                    ->get()->toArray();

  $product_prices = array_combine(array_column($product_prices, 'license_id'), $product_prices);

  if(exchange_rate_required())
  {
    foreach($product_prices as &$product_price)
    {
      $product_price['price'] = convert_amount($product_price['price']);

      if($product_price['promo_price'])
      {
        $product_price['promo_price'] = convert_amount($product_price['promo_price']);
      }
    }
  }

  $valid_subscription = null;



  if(Auth::check())
  {
    $subscription = User_Subscription::useIndex('user_id', 'subscription_id')
                    ->selectRaw("
                      (user_subscription.ends_at IS NOT NULL AND CURRENT_TIMESTAMP > user_subscription.ends_at) OR
                      (subscriptions.limit_downloads > 0 AND user_subscription.downloads >= subscriptions.limit_downloads) OR 
                      (subscriptions.limit_downloads_per_day > 0 AND user_subscription.daily_downloads >= subscriptions.limit_downloads_per_day AND user_subscription.daily_downloads_date = CURDATE())
                       AS expired, subscriptions.products, subscriptions.limit_downloads_same_item,
                      IF(subscriptions.limit_downloads_same_item > 0, subscriptions.limit_downloads_same_item - IFNULL(subscription_same_item_downloads.downloads, 0), null) as remaining_downloads,
                      (subscriptions.limit_downloads_same_item > 0 AND subscription_same_item_downloads.downloads >= subscriptions.limit_downloads_same_item) as same_items_downloads_reached")
                      ->join('subscriptions', 'user_subscription.subscription_id', '=', 'subscriptions.id')
                      ->join('products', function($join) use($product)
                      {
                        $join->where('products.id', '=', $product->id)
                             ->where('products.for_subscriptions', 1);
                      })
                      ->leftJoin('subscription_same_item_downloads USE INDEX(product_id, subscription_id)', function($join) use($product)
                      {
                        $join->on('subscription_same_item_downloads.subscription_id', '=', 'user_subscription.id')
                             ->where('subscription_same_item_downloads.product_id', $product->id);
                      })
                      ->join('transactions USE INDEX(primary)', 'user_subscription.transaction_id', '=', 'transactions.id')
                      ->where(function($query)
                      {
                          $query->where('transactions.refunded', 0)
                                ->orWhere('transactions.refunded', null);
                      })
                      ->where('transactions.status', 'paid')
                      ->where('user_subscription.user_id', Auth::id())
                      ->whereRaw('CASE 
                                    WHEN subscriptions.products IS NOT NULL
                                      THEN FIND_IN_SET(?, subscriptions.products)
                                    ELSE 
                                      1=1
                                  END
                                    ', [$product->id])
                      ->first();

    if($subscription)
    {
      $valid_subscription = !$subscription->expired && !$subscription->same_items_downloads_reached;
      $product->remaining_downloads = $subscription->remaining_downloads;
    }
  }

  $product->table_of_contents = json_decode($product->table_of_contents);

  if(!$product->purchased && !$valid_subscription)
  {
    if($guest_token = $request->query('guest_token'))
    {
      $product->purchased = Transaction::useIndex('guest_token')
                            ->where(['guest_token' => $guest_token, 'status' => 'paid', 'refunded' => 0, 'confirmed' => 1])
                            ->where('transactions.products_ids', 'LIKE', "'%{$product->id}%'")
                            ->first();
    }
  }

  $meta_data  = $this->meta_data;
  
  if($request->isMethod('POST'))
  {        
    $type = $request->input('type');
    
    $redirect_url = url()->current().'#'.$request->input('type');

    if($type === 'reviews')
    {
      if(! $product->purchased) abort(404);

      $rating  = $request->input('rating');
      $review  = $request->input('review');
      $approved = auth_is_admin() ? 1 : (config('app.auto_approve.reviews') ? 1 : 0);

      if(!ctype_digit($rating)) return redirect($redirect_url);

      DB::insert("INSERT INTO reviews (product_id, user_id, rating, content, approved) VALUES (?, ?, ?, ?, ?) 
                  ON DUPLICATE KEY UPDATE rating = ?, content = ?", 
                  [$product->id, $user_id, $rating, $review, $approved, $rating, $review]);

      if(!$approved)
        $request->session()->put(['review_response' => 'Your review is waiting for approval. Thank you!']);

      if(Auth::check() && !auth_is_admin() && config('app.admin_notifications.reviews'))
      {
          $mail_props = [
            'data'   => ['text' => __('A new review has been posted by :user for :item.', ['user' => $request->user()->name ?? null, 'item' => $product->name]),
                         'subject' => __('You have a new review.')],
            'action' => 'send',
            'view'   => 'mail.message',
            'to'     => User::where('role', 'admin')->first()->email,
            'subject' => __('You have a new review.')
          ];

          NewMail::dispatch($mail_props, config('mail.mailers.smtp.use_queue'));
      }
    }
    elseif($type === 'support')
    {
      if(! $comment = $request->input('comment'))
      {
        return redirect($redirect_url);
      }

      $approved = auth_is_admin() ? 1 : (config('app.auto_approve.support') ? 1 : 0);
      $comment = strip_tags($comment);

      if($request->comment_id) // parent
      {
        if($parent_comment = Comment::where('id', $request->comment_id)->where('parent', null)->where('product_id', $product->id)->first())
        {
          DB::insert("INSERT INTO comments (product_id, user_id, body, approved, parent) VALUES (?, ?, ?, ?, ?)", 
                      [$product->id, $user_id, $comment, $approved, $parent_comment->id]);    
        }
      }
      else
      {
        DB::insert("INSERT INTO comments (product_id, user_id, body, approved) VALUES (?, ?, ?, ?)", 
                    [$product->id, $user_id, $comment, $approved]); 
      }

      if(!$approved)
        $request->session()->put(['comment_response' => __('Your comment is waiting for approval. Thank you!')]);

      if(Auth::check() && !auth_is_admin() && config('app.admin_notifications.comments'))
      {
          $mail_props = [
            'data'   => ['text' => __('A new comment has been posted by :user for :item.', ['user' => $request->user()->name ?? null, 'item' => $product->name]),
                         'subject' => __('You have a new comment.')],
            'action' => 'send',
            'view'   => 'mail.message',
            'to'     => User::where('role', 'admin')->first()->email,
            'subject' => __('You have a new comment.')
          ];

          NewMail::dispatch($mail_props, config('mail.mailers.smtp.use_queue'));
      }
    }

    return redirect($redirect_url);
  }

  Self::init_notifications();

  DB::update('UPDATE products USE INDEX(primary) SET views = views+1 WHERE id = ?', [$product->id]);

  $reviews = Review::useIndex('product_id', 'approved')
                      ->selectRaw("reviews.*, users.name, SUBSTR(users.email, 1, LOCATE('@', users.email)-1) as alias_name, CONCAT(users.firstname, ' ', users.lastname) AS fullname, IFNULL(users.avatar, 'default.jpg') AS avatar")
                      ->leftJoin('users', 'users.id', '=', 'reviews.user_id')
                      ->where(['reviews.product_id' => $product->id, 'reviews.approved' => 1])
                      ->orderBy('created_at', 'DESC')->get();

  $comments = Comment::useIndex('product_id', 'approved')
                      ->selectRaw("comments.*, users.name, SUBSTR(users.email, 1, LOCATE('@', users.email)-1) as alias_name, CONCAT(users.firstname, ' ', users.lastname) AS fullname, IFNULL(users.avatar, 'default.jpg') AS avatar, IF(users.role = 'admin', 1, 0) as is_admin, 
                        IF((SELECT COUNT(transactions.id) FROM transactions WHERE transactions.user_id = comments.user_id AND transactions.status = 'paid' AND transactions.refunded = 0 AND transactions.confirmed = 1 AND transactions.products_ids REGEXP CONCAT('\'', comments.product_id, '\'')) > 0, 1, 0) as item_purchased")
                      ->leftJoin('users', 'users.id', '=', 'comments.user_id')
                      ->where(['comments.product_id' => $product->id, 'comments.approved' => 1])
                      ->orderBy('id', 'ASC')->get();


  $similar_products = Product::useIndex('primary', 'category', 'active')
                      ->selectRaw(implode(',', Self::$product_columns).', categories.name as category_name, categories.slug as category_slug')
                      ->leftJoin('categories', 'categories.id', '=', 'products.category')
                      ->leftJoin('categories as subcategories', 'products.subcategories', 'REGEXP', DB::raw('CONCAT("\'", subcategories.id, "\'")'))
                      ->leftJoin('transactions', 'products_ids', 'REGEXP', DB::raw('concat("\'", products.id, "\'")'))
                      ->leftJoin('licenses', function($join)
                      {
                        $join->on('licenses.item_type', '=', 'products.type')
                             ->where('licenses.regular', 1);
                      })
                      ->leftJoin('product_price', function($join)
                      {
                        $join->on('product_price.license_id', '=', 'licenses.id')
                             ->on('product_price.product_id', '=', 'products.id');
                      })
                      ->where(['products.category' => $product->category_id, 
                               'products.active' => 1,
                               'products.for_subscriptions' => 0,
                               'products.is_dir' => (isFolderProcess() ? 1 : 0)])
                      ->where('products.id', '!=', $product->id)
                      ->groupBy('products.id', 'products.name', 'products.views', 'products.preview', 'products.preview_type',
                               'products.slug', 'products.updated_at', 'products.hidden_content', 'products.active', 'products.stock', 'products.bpm', 'products.label', 'products.pages', 
                               'products.authors', 'products.language', 'products.words', 'products.formats',
                               'products.cover', 'product_price.price', 'products.last_update', 
                               'category_name', 'category_slug', 'categories.id', 'promotional_price_time', 'products.tags', 'products.short_description', 'product_price.promo_price', 'products.free', 'products.trending', 'products.is_dir', 'products.for_subscriptions', 'products.type', 'licenses.id', 'licenses.name', 'products.country_city')
                      ->orderByRaw('rand()')
                      ->limit(5)->get();

  if($parents = $comments->where('parent', null)->sortByDesc('id')) // parents comments only
  {
    $children = $comments->where('parent', '!=', null); // children comments only

    // Append children comments to their parents
    $parents->map(function (&$item, $key) use ($children, $request, $product)
    {
      $request->merge(['item_type' => 'comment', 'item_id' => $item->id, 'product_id' => $product->id]);

      $item->reactions = $this->get_reactions($request); 

      $item->children = $children->where('parent', $item->id)->sortBy('created_at');

      foreach($item->children as $children)
      {
        $request->merge(['item_type' => 'comment', 'item_id' => $children->id, 'product_id' => $product->id]);

        $children->reactions = $this->get_reactions($request); 
      }
    });
  }
  
  if($product->country_city)
  {
    $country_city = json_decode($product->country_city);

    $product->country = $country_city->country ?? null;
    $product->city = $country_city->city ?? null;
  }

  if($product->screenshots)
  {
    $product->screenshots = array_reduce(explode(',', $product->screenshots), function($ac, $img)
                            {
                              $ac[] = asset_("storage/screenshots/{$img}");
                              return $ac;
                            }, []);
  }

  $product->tags = array_filter(explode(',', $product->tags));

  $product->additional_fields = json_decode($product->additional_fields);

  $product->faq = json_decode($product->faq, true) ?? []; 

  if(count(array_column($product->faq, 'Q')))
  {
    $faqs = [];

    foreach($product->faq as $faq)
    {
      $faqs[] = [
        'question' => $faq['Q'] ?? '',
        'answer' => $faq['A'] ?? ''
      ];
    }

    $product->faq = $faqs;
  }

  $product->faq = arr2obj($product->faq);

  $meta_data->title         = $product->name;
  $meta_data->description   = $product->short_description;
  $meta_data->image         = asset("storage/covers/{$product->cover}");

  return view_('product', [
              'title'     => mb_ucfirst($product->name),
              'product'   => $product,
              'reviews'   => $reviews,
              'comments'  => $parents, // Parents comments with their children in
              'similar_products' => $similar_products,
              'meta_data' => $meta_data,
              'valid_subscription' => $valid_subscription,
              'product_prices' => $product_prices
            ]);
}

top_menu.blade.php

 <div class="menu">
    <div>
     
      <div class="ui unstackable items">
        @if(config('notifications'))

        @foreach(config('notifications') as $notif)
        <a class="item mx-0"
               data-id="{{ $notif->id }}"
               data-href="{{ route('home.product', ['id' => $notif->product_id, 'slug' => $notif->slug . ($notif->for == 1 ? '#support' : ($notif->for == 2 ? '#reviews' : ''))]) }}">

          <div class="ui image">
            @if($notif->for == 0)
            <img src="{{ asset_("storage/thumbnails/{$notif->image}") }}">
            @else
            <img src="{{ asset_("storage/avatars/{$notif->image}") }}">
            @endif
          </div>

          <div class="content pl-1">
            <p>{!! __($notif->text, ['product_name' => "<strong>{$notif->name}</strong>"]) !!}</p>
            <time>{{ \Carbon\Carbon::parse($notif->updated_at)->diffForHumans() }}</time>
          </div>

        </a>
        @endforeach

        @else
        
        <div class="item mx-0">
          <div class="ui w-100 small message p-1 circular-corner bold">
            {{ __('You have 0 new notifications') }}
          </div>
        </div>
        
        @endif

        @auth
        <a href="{{ route('home.notifications') }}" class="item mx-0 all">{{ __('View all') }}</a>
        @endauth
      </div>
      
    </div>
  </div>
</div>
@endauth

0 个答案:

没有答案