【问题标题】:An exception has been thrown during the rendering of a template ("Unable to resolve dependency [Parameter #0 [ $listing ]]")渲染模板期间引发异常(“无法解析依赖项 [Parameter #0 [ $listing ]]”)
【发布时间】:2021-02-11 17:05:52
【问题描述】:

我决定升级 Laravel 框架版本以解决关键的安全漏洞。我已成功从 5.8 升级到 6,然后升级到 6.20(漏洞修复)。 但不幸的是,我遇到了从 Laravel 框架 6.19.0 开始的错误,它在我的类 (BuyWidget.php) 中引发了与 BoundMethod.php 相关的异常。我通过互联网查了一下,发现他们在 BoundMethod.php (Illuminate\Container\BoundMethod) 中实现了对非指定类型的检查。

我尝试相应地更改 BuyWidget.php 中的所有函数:public function run($listing)public function run(Listing $listing) 等。

BuyWidget.php

<?php

namespace App\Widgets\Order;

use Arrilot\Widgets\AbstractWidget;
use App\Models\Listing;

class BuyWidget extends AbstractWidget
{
    protected $config = [];
    
    public function calculate_price($listing, $params) {
        $fee_percentage = setting('marketplace_percentage_fee');
        $fee_transaction = setting('marketplace_transaction_fee');
        
        $quantity = isset($params['quantity'])?$params['quantity']:1;
        $variants = isset($params['variant'])?$params['variant']:null;
        $shipping = isset($params['shipping_option'])?$params['shipping_option']:null;
        $additional_options = isset($params['additional_option'])?$params['additional_option']:[];
        $additional_options_meta = isset($params['additional_options_meta'])?$params['additional_options_meta']:[];
        
        $listing_price = $listing->price;
        
        #calculate additional variant cost
        $selected_variant = null;
        $error = false;

        $user_choice = [];
        $user_choice[] = ['group' => 'general', 'name' => 'quantity', 'value' => $quantity];

        if($variants) {
            $variant_pricing = $listing->variants;
            foreach($variants as $k => $v) {
                $variant_pricing = $variant_pricing->where("meta.$k", $v);
                $user_choice[] = ['group' => 'variant', 'name' => $k, 'value' => $v];
            }
            
            if($variant_pricing->count() == 1) {
                $selected_variant = $variant_pricing->first();
                $listing_price += $selected_variant->price;
                if($quantity > $selected_variant->stock) {
                    $error = __('Insufficient stock. Please lower the quantity.');
                }               
                if($selected_variant->stock < 1) {
                    $error = __('Out of Stock');
                }
            }
        }
        
        #calculate shipping cost
        $selected_shipping_price = null;
        if(!is_null($shipping)) {
            $selected_shipping_method = $listing->shipping_options->firstWhere('id', $shipping)?:null;
            if($selected_shipping_method) {
                $selected_shipping_price = $selected_shipping_method->price;
            }
            $user_choice[] = ['group' => 'shipping', 'name' => 'Shipping', 'value' => $selected_shipping_method->name, 'price' => $selected_shipping_method->price];
        }

        #additional pricing
        $additional_options_price = $listing->additional_options->reduce(function ($carry, $item) use($additional_options, $additional_options_meta) {
            if(in_array($item->id, array_keys($additional_options))) {
                $price = $item->price;
                $quantity = 1;
                if(in_array($item->id, array_keys($additional_options_meta)) && isset($additional_options_meta[$item->id]['quantity'])) {               
                    $quantity = (int) $additional_options_meta[$item->id]['quantity'];
                }               
                return $carry + ($price*$quantity);
            }
                        
            return $carry;
        }, 0);

        $number = 0;
        foreach($listing->additional_options as $k => $item) {
            if(in_array($item->id, array_keys($additional_options))) {
                $number++;
                $user_choice[] = ['group' => 'additional_options', 'name' => 'Option '.($k+1), 'value' => $item->name, 'price' => $item->price];
            }
        }
        
        //date, time, qty
        $subtotal = ($quantity * $listing_price) + $additional_options_price;
        $service_fee_percentage = $subtotal * ($fee_percentage/100);
        $service_fee = (float) $service_fee_percentage + (float) $fee_transaction;
        $total = $subtotal + $service_fee + $selected_shipping_price;

        if($quantity > $listing->stock) {
            $error = __('Insufficient stock. Please lower the quantity.');
        }
        if($listing->stock < 1) {
            $error = __('Out of Stock');
        }
        
        //now check if we have any slots left for this time
        $price_items = [
            [
                'key'   => 'price',
                'label' => __(':price x :quantity :unit_label', ['price' => format_money($listing_price, $listing->currency), 'quantity' => $quantity, 'unit_label' => $listing->unit]),
                'price' => ($quantity * $listing_price)
            ]
        ];
        if($selected_shipping_price) {
            $price_items[] = [
                'key'   => 'service',
                'label' => __('Shipping'),
                'price' => $selected_shipping_price,
            ];
        }

        if($additional_options_price) {
            $price_items[] = [
                'key'   => 'additional',
                'label' => __('Additional options'),
                'price' => $additional_options_price,
            ];
        }

        if($service_fee > 0) {
            $price_items[] = [
                'key' => 'service',
                'label' => __('Service fee'),
                'price' => $service_fee,
                'notice' => __('This fee helps cover the costs of operating the website'),
            ];
        }
        
        return [
            'user_choice'   =>  $user_choice,
            'error'         =>  $error,
            'total'         =>  $total,
            'service_fee'   =>  $service_fee,
            'price_items'   =>  $price_items,
        ];
    
    }
    
    public function decrease_stock($order, $listing)
    {
        $quantity = $order->listing_options['quantity'];
        $listing->decrement( 'stock', $quantity );

        if(isset($order->listing_options['variant'])) {
            $variants = $order->listing_options['variant'];

            $listing_variants = $listing->variants;
            foreach($variants as $k => $v) {
                $listing_variants = $listing_variants->where("meta.$k", $v);
            }

            if($listing_variants->count() == 1) {
                $listing_variant = $listing_variants->first();
                $listing_variant->decrement( 'stock', $quantity );
            }
        }
    }

    public function validate_payment($listing, $request)
    {
        $result = $this->calculate_price($listing, request()->all());
        return $result;
    }

    
    /**
     * Treat this method as a controller action.
     * Return view() or other content to display.
     */
    public function run($listing)
    {
        //
        $total = 0;
        $quantity = request('quantity', 1);

        $result = $this->calculate_price($listing, request()->all());
        
        return view('listing.widgets.buy_widget', [
            'config'        => $this->config,
            'listing'       => $listing,
            'qs'            => http_build_query(request()->all()),
            'error'         => $result['error'],
            'total'         => $result['total'],
            'service_fee'   => $result['service_fee'],
            'price_items'   => $result['price_items'],
        ]);
    }
}

但应用这些更改后,应用无法正常运行,参数始终为空,产品显示为缺货。

在基于列表类型构建小部件的 sidebar.twig 文件中引发了初始异常。

“在渲染模板的过程中抛出了异常(“无法解析依赖项[Parameter #0 [ $listing ]]”)

sidebar.twig

{% if listing.pricing_model %}
    {{ Widget.run('Order.'~(listing.pricing_model.widget)~'Widget', {}, listing) | raw }}
{% endif %}

代码在 Laravel 6.19.0 之前的任何其他版本上都能完美运行。如果我手动还原文件 BoundMethod.php 中的更改,则即使在从未版本上,代码也会按预期工作。我想找到另一种解决方案来避免修改供应商文件,因为这不是最好的方法。

web.php

include "admin.php";
include "payments.php";

Route::get('/cp', function () {
    if(env('DEMO_PANEL')) {
        \Auth::loginUsingId(1, true);
        return redirect("/panel");
    }
});

Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => 'jailBanned'], function()
{
    Auth::routes();
    Route::get('email-verification', 'Auth\EmailVerificationController@sendEmailVerification')->name('email-verification.send');
    Route::get('email-verification/error', 'Auth\EmailVerificationController@getVerificationError')->name('email-verification.error');
    Route::get('email-verification/check/{token}', 'Auth\EmailVerificationController@getVerification')->name('email-verification.check');

    Route::get('/', 'HomeController@index')->name('home');
    Route::get('/browse', 'BrowseController@listings')->name('browse');
    Route::get('/categories', 'BrowseController@categories')->name('categories');

    Route::get('/pages/{slug?}', 'PageController@index')->name('page');
    Route::get('/contact', 'ContactController@index')->name('contact');
    Route::post('/contact', 'ContactController@postIndex')->name('contact.post');

    Route::get('/profile/{user}', 'ProfileController@index')->name('profile'); //PROFILE
    Route::get('/profile/{user}/follow', 'ProfileController@follow')->name('profile.follow'); //PROFILE

    //LISTINGS
    Route::group(['prefix' => 'listing'], function()
    {
        Route::get('/{listing}/{slug}', 'ListingController@index')->name('listing');
        Route::get('/{listing}/{slug}/card', 'ListingController@card')->name('listing.card');
        Route::get('/{listing}/{slug}/spotlight', 'ListingController@spotlight')->middleware('auth.ajax')->name('listing.spotlight');
        Route::get('/{listing}/{slug}/verify', 'ListingController@verify')->middleware('auth.ajax')->name('listing.verify');
        Route::get('/{listing}/{slug}/star', 'ListingController@star')->middleware('auth.ajax')->name('listing.star');
        Route::get('/{listing}/{slug}/edit', 'ListingController@edit')->name('listing.edit');
        #Route::get('/{listing}/{slug}/availability', 'AvailabilityController@availability')->name('listing.availability');
        Route::any('/{id}/update', 'ListingController@update')->name('listing.update');

    });


    //ACCOUNT
    Route::group(['middleware' => ['auth', 'isVerified'], 'prefix' => 'account', 'as' => 'account.', 'namespace' => 'Account'], function()
    {
        Route::get('/', function () {
            return redirect(route('account.edit_profile.index'));
        });
        Route::resource('change_password', 'PasswordController');
        Route::resource('edit_profile', 'ProfileController');

        Route::resource('purchase-history', 'PurchaseHistoryController');
        Route::resource('favorites', 'FavoritesController');

        Route::resource('listings', 'ListingsController');
        Route::resource('orders', 'OrdersController');

        Route::get('payments/{id}/unlink', 'BankAccountController@unlink')->name('payments.unlink');
        Route::resource('bank-account', 'BankAccountController');

        Route::get('paypal/connect', 'PayPalController@connect')->name('paypal.connect');
        Route::get('paypal/callback', 'PayPalController@callback')->name('paypal.callback');

    });

    //REQUIRES AUTHENTICATION
    Route::group(['middleware' => ['auth', 'isVerified']], function () {

        //INBOX
        Route::resource('inbox', 'InboxController')->middleware('talk'); //Inbox
        Route::get('/inbox/messages/{id}', 'InboxController@messages')->name('inbox.messages');

        //CREATE LISTING
        Route::resource('create', 'CreateController');
        Route::any('/create/{listing}/session', 'CreateController@session')->name('create.session');
        Route::get('/create/{listing}/images', 'CreateController@images')->name('create.images');
        Route::get('/create/{listing}/additional', 'CreateController@additional')->name('create.additional');
        Route::get('/create/{listing}/pricing', 'CreateController@pricing')->name('create.pricing');
        Route::get('/create/{listing}/times', 'CreateController@getTimes')->name('create.times');
        Route::post('/create/{listing}/times', 'CreateController@postTimes')->name('create.times');
        Route::get('/create/{listing}/boost', 'CreateController@boost')->name('create.boost');

        Route::post('/create/{listing}/uploads', 'CreateController@upload')->name('create.upload');
        Route::delete('/create/{listing}/image/{uuid?}', 'CreateController@deleteUpload')->name('create.delete-image');

        //CHECKOUT
        Route::get('/checkout/error', 'CheckoutController@error_page')->name('checkout.error');
        Route::get('/checkout/{listing}', 'CheckoutController@index')->name('checkout');
        Route::post('/checkout/{listing}', 'CheckoutController@store')->name('checkout.store');
        Route::get('/checkout/{session}/callback', 'CheckoutController@callback')->name('checkout.callback');
        Route::any('/checkout/process/{listing}', 'CheckoutController@process')->name('checkout.process');
        #Route::any('/checkout/test', 'CheckoutController@test')->name('checkout.test');
        #Route::resource('stripe', 'StripeController');
        #Route::any('/stripe/connect', 'StripeController@connect')->name('stripe.connect');

        Route::any('/paypal/{listing}/start', 'PaypalController@start')->name('paypal.start');
        Route::any('/paypal/cancel', 'PaypalController@cancel')->name('paypal.cancel');
        Route::any('/paypal/callback', 'PaypalController@callback')->name('paypal.callback');
        Route::any('/paypal/confirm', 'PaypalController@confirm')->name('paypal.confirm');
        #Route::any('/paypal/create_agreement', 'PaypalController@create_agreement')->name('paypal.create_agreement');


    });

    //REQUIRES AUTHENTICATION
    Route::group(['middleware' => ['auth']], function () {

        Route::get('email-verification', 'Auth\EmailVerificationController@index')->name('email-verification.index');
        Route::get('resend-verification', 'Auth\EmailVerificationController@resend')->name('email-verification.resend');
        Route::get('email-verified', 'Auth\EmailVerificationController@verified')->name('email-verification.verified');

    });

    Route::get('login/facebook', 'Auth\LoginController@redirectToProvider');
    Route::get('login/facebook/callback', 'Auth\LoginController@handleProviderCallback');


});

#errors
Route::get('/suspended',function(){
    return 'Sorry something went wrong.';
})->name('error.suspended');

【问题讨论】:

  • 请附上web.php
  • 包含的 web.php

标签: php laravel widget twig laravel-6


【解决方案1】:

public function run(Listing $listing)

并且您在该命名空间中包含了一个与列表匹配的类?还是可以通过服务提供商获得?

【讨论】:

  • 它可以通过服务提供商获得,为了安全起见,我已将其包含在文件中。当我在函数中指定类型时,异常消失,但产品属性为空,产品显示为缺货。添加了小部件的完整代码。
【解决方案2】:

从函数中移除参数:

public function run();

并将下面一行添加到函数中:

$listing = func_get_arg(0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 2014-12-28
    • 2021-07-21
    • 2022-01-25
    • 2015-11-18
    • 2019-04-23
    相关资源
    最近更新 更多