【发布时间】: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