问题描述
我决定升级 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 文件中抛出初始异常,该文件根据列表类型构建小部件。
“在渲染模板期间抛出异常(“无法解析依赖项 [参数 #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');
解决方法
public function run(Listing $listing)
并且您在该命名空间中包含了一个与 Listing 匹配的类?还是可以通过服务提供商获得?
,从函数中移除参数:
public function run();
并将以下行添加到函数中:
$listing = func_get_arg(0);