为什么与注册关联的注册类型信息显示不正确?

时间:2018-07-31 12:23:23

标签: php laravel

我有一个PaymentController,在这里我返回到视图registrationTypeDetailstotaltype_counts。因此可以显示如下所示的注册摘要。在这种情况下,用户使用“通用”注册类型与两个参与者进行了注册,因此应显示摘要,例如:

+-------------------+----------+---------+--------------+
| Registration Type | Quantity |  Price  |   Subtotal   |      
+-------------------+----------+---------+--------------+
| general           | 2        | 10.00 € |      20.00 € |
+-------------------+----------+---------+--------------+
| TOTAL             |          |         |      20.00 € |
+-------------------+----------+---------+--------------+

但是它出现如下,重复的信息:

+-------------------+----------+---------+--------------+
| Registration Type | Quantity |  Price  |   Subtotal   |      
+-------------------+----------+---------+--------------+
| general           | 2        | 10.00 € |      20.00 € |
| general           | 2        | 10.00 € |      20.00 € |
+-------------------+----------+---------+--------------+
| TOTAL             |          |         |      20.00 € |
+-------------------+----------+---------+--------------+

您知道为什么与注册关联的注册类型信息会出现两次吗?

在payment.blade.php视图中显示注册摘要:

<div>
    <ul>
        <li>
            <span>Registration Type</span>
            <span>Quantity</span>
            <span>Price</span>
            <span>Subtotal</span>
        </li>

        @foreach( $registrationTypeDetails->participants as $participant )
            <li>
                <span>{{$participant->registration_type->name}}</span>
                <span>{{$type_counts[$name]}}</span>
                <span>{{ number_format($participant->registration_type->price, 2)}}$</span>
                <span>{{ number_format($participant->registration_type->price * $type_counts[$name], 2)}}$</span>
            </li>
        @endforeach

        <li>
            <span>TOTAL</span>
            <span>{{ number_format($total, 2)}}$</span>
        </li>
    </ul>
</div>

PaymentController payment()方法的完整代码,在该方法中,我获得与注册相关联的注册类型信息,并使用此信息将用户重定向到付款页面以显示付款中的注册摘要页。

class PaymentController extends Controller
{

// method that shows the payment page
public function payment($id, $slug, $regID)
{
    $regPaid = Registration::where('id', $regID)->pluck('status')->first();

    // if the registration is incomplete because the user didnt pay yet 
    if ($regPaid == "I") {

        // get the current user
        $user_id = Auth::id();

        $conferenceDetails = Registration::with([
            'conference' => function ($query) {
                $query->select('id', 'name', 'start_date');
            }
        ])->find($regID);

        $registrationTypeDetails = Registration::with(['participants.registration_type',
            'participants' => function ($query) use ($regID) {
                $query->select('id', 'registration_type_id', 'registration_id')->where('registration_id', $regID);
            }
        ])->find($regID);

        $price = $registrationTypeDetails->participants->sum(function ($participant) {
            return $participant->registration_type->price;
        });

        $total = $price;
        $totalStripe = $total * 100;

        if ($registrationTypeDetails->main_participant_id != $user_id) {
            return redirect('/');
        } else {
            $type_counts = [];
            foreach ($registrationTypeDetails->participants as $p) {
                $name = $p->registration_type->name;
                if (!isset($type_counts[$name])) {
                    $type_counts[$name] = 0;
                }
                $type_counts[$name]++;
            }

            Session::put('total', $total);
            Session::put('totalStripe', $totalStripe);
            Session::put('registrationID', $regID);

            $conferenceDetails = [
                'name' => $conferenceDetails->conference->name,
                'start_date' => $conferenceDetails->conference->start_date
            ];

            Session::put('conference_name', $conferenceDetails['name']);
            Session::put('date', $conferenceDetails['end_date']);

            return view('conferences.payment', compact('conferenceDetails', 'name', 'total', 'type_counts', 'registrationTypeDetails', 'id', 'slug'));
        }
    } else {

        Session::flash('registration_complete', 'Your registration is already paid.');
        return redirect(route('user.index', ['user' => Auth::id()]) . '#myTickets');
    }

}

1 个答案:

答案 0 :(得分:4)

我认为问题出在构建数据的方式上。 使用Model的左连接和方法将极大地提高代码的可读性并帮助您调试。我不知道像您一样使用with()是否好。

某些功能确实需要进入模型的文件才能使其变为OOP。

将数据收集到该ConferenceDetails中的方式对我来说是一团糟。我建议您不仅要考虑收集所需的所有数据,还要考虑数据的结构。

在您的情况下,会议,注册,参与者是3种主要模式。您的代码弄乱了彼此之间的关系。如果您的程序专注于会议,则使用会议作为主要模型并获取其数据库。喜欢:

$registrations=$conference->registrations;
$participants=$conference->participants;

不使用$ conference-> participants()的原因是,参与者()应该返回一个关系而不是集合,而参与者返回您需要的集合。这是由Laravel完成的

现在您可以看到,会议数据是会议数据,请不要与参与者和注册混淆。 在会议模型中,编写一个名为particiants()的函数,并在其中进行通过多对多关系获取数据的工作。您可以在Laravel文档中找到示例代码。

此外,如果您是入门者,我建议您不要涉及付款。付款系统所需要的远远超出了我从您的代码中所能看到的。交易,退款等等。即使您正在使用Stripe,我仍然可以看到您对MVC编程没有深刻的了解。如果我正在编写此程序,那么我将通过Ajax完成许多步骤,并提供更友好的用户交互界面以及更详细的错误和消息,以帮助用户。

无论如何,请检查下面的代码并对其进行调整以适合您的需求。不要在生产程序上使用您的程序,它肯定会引起恶梦。尤其是在付款相关时。

public function payment($id, $slug, $regID){
$reg=Registration::find($regID); //It's always good to check if the instance exists
if(!$reg){
    return back()->with(['error'=>'Could not find the Registration with the given ID']);
}

if($reg->status=='I'){ //By the way, if the status is an integer, it would be better for database design in MySQL
    $isRegPaid=false;
} else {
    $isRegPaid=true;
}

// get the current user
$user_id = Auth::id(); //remember you can also use $request->user() if the function provides Request $request as a parameter

// if the registration is incomplete because the user didnt pay yet 
if ($isRegPaid) {
    $conferenceDetails = Registration::with([
        'conference' => function ($query) {
            $query->select('id', 'name', 'start_date');
        }
    ])->find($regID);

    $conferences=Conference::where('registration_id',$regID)->get();
    //        $registrationTypeDetails = Registration::with(['participants.registration_type',
    //            'participants' => function ($query) use ($regID) {
    //                $query->select('id', 'registration_type_id', 'registration_id')->where('registration_id', $regID);
    //            }
    //        ])->find($regID);

    $total=0;
    //As I don't know the actual structure of your model, I could only provide you the most basic way to sum the price
    //If I was writing my own code, I could do a lot more than this like left join etc.
    //And you also need to remember to put some of the functions into your Model, to make it more Object Oriented
    foreach($conferences as $conference){
        //I'm assuming participants is actually a function is Conference, if it's in Registration, you will need to rewrite this part
        foreach($conference->participants as $participant){
            $total+=$participant->registration_type->price;
        }
    }

    $totalStripe = $total * 100;

    if($reg->main_participant_id != $user_id){ //I'm guessing this main_participant_id property belongs to Registration
        return back()->with(['error'=>'You do not have the permission to process this payment']); //Let the user know what error they have encountered, it's good for debugging
    } else {
        $type_counts = [];
        foreach($conferences as $conference){
            foreach($conference->participants as $participant){
                $name = $participant->registration_type->name; // I don't know how you could get this name property, assuming registration_type should be a function
                if (!isset($type_counts[$name])) {
                    $type_counts[$name] = 0;
                }
                $type_counts[$name]++;
            }
        }

        Session::put('total', $total);
        Session::put('totalStripe', $totalStripe);
        Session::put('registrationID', $regID);

        //You will need to rewrite this part to format your data
        //            $conferenceDetails = [
        //                'name' => $conferenceDetails->conference->name,
        //                'start_date' => $conferenceDetails->conference->start_date
        //            ];

        Session::put('conference_name', $conferenceDetails['name']);
        Session::put('date', $conferenceDetails['end_date']);

        //            return view('conferences.payment', compact('conferences', 'name', 'total', 'type_counts', 'registrationTypeDetails', 'id', 'slug'));
        //ID should not need to be rendered into the view as it should be able to be accessed from Request
        //I don't like using compact, I usually do this:
        return view('conferences.payment')->with(['conferences'=>$conferences,'name'=>$name,'total'=>$total,'type_counts'=>$type_counts,
            'slug'=>$slug]);
    }
} else {
    Session::flash('registration_complete', 'Your registration is already paid.');
    return redirect(route('user.index', ['user' => Auth::id()]) . '#myTickets');
}
}