如何在yii2的控制器操作中使用return而不是echo

时间:2018-10-19 11:28:03

标签: php ajax yii2

我有以下查看文件,当用户执行某些从系统中选择患者姓名的功能时,该查看文件将调用控制器actionListInvoices,后者依次执行一些检查并通过显示给用户的ajax响应html响应。这在localhost上运行良好,但是当我将其托管在实时服务器中时,出现以下错误:

An Error occurred while handling another error:
yii\web\HeadersAlreadySentException: Headers already sent in /home/stjamesh/public_html/backend/modules/finance/controllers/PaymentsController.php on line 152. in /home/stjamesh/public_html/vendor/yiisoft/yii2/web/Response.php:366
Stack trace:
#0 /home/stjamesh/public_html/vendor/yiisoft/yii2/web/Response.php(339): yii\web\Response->sendHeaders()
#1 /home/stjamesh/public_html/vendor/yiisoft/yii2/web/ErrorHandler.php(135): yii\web\Response->send()
#2 /home/stjamesh/public_html/vendor/yiisoft/yii2/base/ErrorHandler.php(111): yii\web\ErrorHandler->renderException(Object(yii\web\HeadersAlreadySentException))
#3 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\web\HeadersAlreadySentException))
#4 {main}
Previous exception:
yii\web\HeadersAlreadySentException: Headers already sent in /home/stjamesh/public_html/backend/modules/finance/controllers/PaymentsController.php on line 152. in /home/stjamesh/public_html/vendor/yiisoft/yii2/web/Response.php:366
Stack trace:
#0 /home/stjamesh/public_html/vendor/yiisoft/yii2/web/Response.php(339): yii\web\Response->sendHeaders()
#1 /home/stjamesh/public_html/vendor/yiisoft/yii2/base/Application.php(392): yii\web\Response->send()
#2 /home/stjamesh/public_html/dashboard/index.php(17): yii\base\Application->run()
#3 {main}

建议针对此错误的解决方案,根据yii2的当前更新,应使用return而不是echo。

我的问题是我试图使用return,但是前端没有得到任何预期的东西。如何在动作控制器中使用return和html函数?

这是我的观点:

<?php

use yii\helpers\Html;
use kartik\widgets\ActiveForm;
use wbraganca\dynamicform\DynamicFormWidget;
use yii\helpers\ArrayHelper;
use kartik\datecontrol\DateControl;
use kartik\builder\Form;

/**
 * @var yii\web\View $this
 * @var app\models\Payments $model
 */

$this->title = 'Add Payment';
$this->params['breadcrumbs'][] = ['label' => 'Payments', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;

$js = '
jQuery(".dynamicform_wrapper").on("afterInsert", function(e, item) {
    jQuery(".dynamicform_wrapper .panel-title-address").each(function(index) {
        jQuery(this).html("Payment: " + (index + 1))
    });
    jQuery(".dynamicform_wrapper .invoice-data").each(function(index) {
        var new_index = index;
        jQuery(this).attr("id", "payment-" + new_index + "-invoice")
    });
});

jQuery(".dynamicform_wrapper").on("afterDelete", function(e) {
    jQuery(".dynamicform_wrapper .panel-title-address").each(function(index) {
        jQuery(this).html("Payment: " + (index + 1))
    });
    jQuery(".dynamicform_wrapper .invoice-data").each(function(index) {
        var new_index = index;
        jQuery(this).attr("id", "payment-" + new_index + "-invoice")
    });
});
';

$this->registerJs($js);

$this->registerJs(" 
    jQuery(function($){ 
        $(document.body).on('change', '#payments-patient_id', function(){ 
            var select_Id = $(this).attr('id');
            var invoiceId = 'payment-invoice';
            var id1 = $(this).val(); 
            // alert(id1); 
            $.ajax({ 
                type :'GET', cache : false, url : 'list-invoices', data: { patient_id : id1 }, success : function(response) { 
                    alert(response); 
                    $('#'+invoiceId).html(response); 
                } 
            }); 
            return false;
        }); 
    });
");
?>

<div class="row">
    <div class="payment-create">

        <div class="payment-form">

            <?php $form = ActiveForm::begin(['type' => ActiveForm::TYPE_VERTICAL]); ?>

            <div class="padding-v-md">
                <div class="line line-dashed"></div>
            </div>

            <div class="panel panel-default">
                <div class="panel-heading">
                    <i class="fa fa-money"></i> Payments
                    <button type="button" class="pull-right add-item btn btn-success btn-xs"><i class="fa fa-plus"></i> Add Payment</button>
                    <div class="clearfix"></div>
                </div>
                <div class="panel-body container-items"><!-- widgetContainer -->
                    <div class="item panel panel-default"><!-- widgetBody -->
                        <div class="panel-heading">
                            <span class="panel-title-address">Make Payment</span>
                            <button type="button" class="pull-right remove-item btn btn-danger btn-xs"><i class="fa fa-minus"></i></button>
                            <div class="clearfix"></div>
                        </div>
                        <div class="panel-body">

                            <?php 
                            echo Form::widget([

                                'model' => $model,
                                'form' => $form,
                                'columns' => 3,
                                'attributes' => [

                                    'receipt_number' => ['type' => Form::INPUT_TEXT, 'options' => ['placeholder' => 'Enter Receipt Number...', 'disabled'=> true]],

                                    'patient_id' => ['type' => Form::INPUT_WIDGET, 'widgetClass'=>'\kartik\widgets\Select2', 'options' => ['data'=>ArrayHelper::map(app\models\Patients::find()->all(), 'id', 'displayDetails'), 'options' => ['placeholder' => 'Select Patient...']]],

                                    'payment_reference' => ['type' => Form::INPUT_TEXT, 'options' => ['placeholder' => 'Enter Payment Reference...']],
                                ]

                            ]);

                            echo Form::widget([

                                'model' => $model,
                                'form' => $form,
                                'columns' => 3,
                                'attributes' => [

                                    'payment_date' => ['type' => Form::INPUT_WIDGET, 'widgetClass' => DateControl::classname(),'options' => ['type' => DateControl::FORMAT_DATETIME]],

                                    'payment_method_id' => ['type' => Form::INPUT_WIDGET, 'widgetClass'=>'\kartik\widgets\Select2', 'options' => ['data'=>ArrayHelper::map(app\models\PaymentMethod::find()->all(), 'payment_method_id', 'method'), 'options' => ['placeholder' => 'Select a Payment Method...']]],

                                    'amount' => ['type' => Form::INPUT_TEXT, 'options' => ['placeholder' => 'Enter Amount Paid...']],

                                ]

                            ]);

                            echo Form::widget([

                                'model' => $model,
                                'form' => $form,
                                'columns' => 1,
                                'attributes' => [

                                    'notes' => ['type' => Form::INPUT_TEXTAREA, 'options' => ['placeholder' => 'Enter Notes...', 'maxlength' => 255]],

                                ]

                            ]);?>

                            <div class="invoice-data" id="payment-invoice"></div>

                        </div>
                    </div>
                </div>
            </div>

            <div class="col-sm-offset-3 col-sm-9">
                <?= Html::submitButton($model->isNewRecord ? 'Add Payment' : 'Update Payment', ['class' => 'btn btn-primary']) ?>
                <?= Html::resetButton('Reset', ['class' => 'btn btn-default']) ?>
            </div>

            <?php ActiveForm::end(); ?>

        </div>
    </div>
</div>

这是我的控制器:

<?php

namespace app\modules\finance\controllers;

use Yii;
use app\models\Payments;
use app\models\PaymentsSearch;
use app\models\FinancialTransactions;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

/**
 * PaymentsController implements the CRUD actions for Payments model.
 */
class PaymentsController extends Controller
{
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
        ];
    }

    /**
     * Lists all Payments models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new PaymentsSearch;
        $dataProvider = $searchModel->search(Yii::$app->request->getQueryParams());

        return $this->render('index', [
            'dataProvider' => $dataProvider,
            'searchModel' => $searchModel,
        ]);
    }

    /**
     * Displays a single Payments model.
     * @param integer $id
     * @return mixed
     */
    public function actionView($id)
    {
        $model = $this->findModel($id);

        // $paymentInvoices = \app\models\PaymentInvoiceLink::find()
        //     ->where(['payment_id' => $id])
        //     ->all();

        $paymentInvoices = \app\models\InvoiceLine::find()
            ->joinWith(['invoiceLinks il'])
            ->where(['il.payment_id' => $id])
            ->all();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->payment_id]);
        } else {
            return $this->render('view', [
                'model' => $model,
                'paymentInvoices' => $paymentInvoices,
            ]);
        }
    }

    /**
     * Creates a new Payments model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new Payments;
        $modelTransactions = new FinancialTransactions;
        $model->receipt_number = $model->receiptNumber;

        if ($model->load(Yii::$app->request->post())) {
            $transaction = Yii::$app->db->beginTransaction();
            try {
                $data = Yii::$app->request->post();

                $period = \app\models\FinancialPeriod::find()
                    ->where(['<=', 'date_from', date("Y-m-d")])
                    ->andWhere(['>=', 'date_to', date("Y-m-d")])
                    ->one();
                $period_id = $period->period_id;
                // create a transaction
                $modelTransactions->debit_account_id = $modelTransactions->defaultDebitAccount($account_code = 'PAYRE');
                $modelTransactions->credit_account_id = $modelTransactions->defaultCreditAccount($account_code = 'ARE');
                $modelTransactions->amount = $data['Payments']['amount'];
                $modelTransactions->notes = 'Payment received from patient';
                $modelTransactions->period_id = $period_id;
                $modelTransactions->branch_id = Yii::$app->user->identity->branch_id;

                if (! ($flag = $modelTransactions->save())) {
                    $transaction->rollBack();
                }

                // create a payment
                $model->created_by = Yii::$app->user->id;
                $model->transaction_id = $modelTransactions->transaction_id;
                $model->amount_unallocated = $modelTransactions->amount;
                $model->branch_id = Yii::$app->user->identity->branch_id;

                if (! ($flag = $model->save())) {
                    $transaction->rollBack();
                }

                if ($flag) {
                    $transaction->commit();
                    \app\models\Invoices::clearInvoices($model->patient_id);
                    return $this->redirect(['view', 'id' => $model->payment_id]);
                } else {
                    $transaction->rollBack();
                }
            } catch (Exception $e) {
                $transaction->rollBack();
            }
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }

    public function actionTest()
    {
        $result = \app\models\Invoices::clearInvoices(2);
        echo $result;
    }

    /**
     * Displays an array of data model.
     * @param integer $id
     * @return mixed
     */
    public function actionListInvoices($patient_id)
    {
        $invoices = \app\models\Invoices::find()->joinWith(['patientVisit pv'])->where(['pv.patient_id' => $patient_id])->andWhere(['or', ['invoices.status_id'=> 1], ['invoices.status_id'=> 4]])->all();

        $count = \app\models\Invoices::find()->joinWith(['patientVisit pv'])->where(['pv.patient_id' => $patient_id])->andWhere(['or', ['invoices.status_id'=> 1], ['invoices.status_id'=> 4]])->count();

        if ($count > 0) {
            $total_amount = 0;
            echo '<table class="table table-bordered table-inverse table-hover">
                <thead class="thead-inverse">
                    <th>Invoice #</th>
                    <th>Invoice Date</th>
                    <th>Due Date</th>
                    <th>Amount</th>
                    <th>Amount Paid</th>
                    <th>Amount Due</th>
                </thead>
                <tbody>';

            foreach($invoices as $invoice){
                echo '<tr>
                        <td>'.$invoice->invoice_number.'</td>
                        <td>'.$invoice->date_created.'</td>
                        <td>'.$invoice->due_date.'</td>
                        <td>'.$invoice->invoiceAmount($invoice->invoice_id).'</td>
                        <td>'.$invoice->paidAmount($invoice->invoice_id).'</td>
                        <td>'.$invoice->amountDue($invoice->invoice_id).'</td>
                    </tr>';
                $total_amount = $total_amount + $invoice->amountDue($invoice->invoice_id) - $invoice->amountUnallocated($invoice->patientVisit->patient_id);
            }
            echo '<tr>
                     <td></td>
                     <td></td>
                     <td></td>
                     <td></td>
                     <td><strong>Previous over-Payment</strong></td>
                     <td class="total">'.$invoice->amountUnallocated($invoice->patientVisit->patient_id).'</td>
                </tr>
                <tr>
                     <td></td>
                     <td></td>
                     <td></td>
                     <td></td>
                     <td><strong>Total Due</strong></td>
                     <td class="total">'.$total_amount.'</td>
                </tr>';
            echo '</tbody></table>';
        } else {
            echo 'Patient has no pending invoice';
        }
    }

    /**
     * Updates an existing Payments model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->payment_id]);
        } else {
            return $this->render('update', [
                'model' => $model,
            ]);
        }
    }

    /**
     * Deletes an existing Payments model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $this->findModel($id)->delete();

        return $this->redirect(['index']);
    }

    /**
     * Finds the Payments model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return Payments the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = Payments::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

让我知道是否应该添加任何内容。

1 个答案:

答案 0 :(得分:1)

查看您的代码并作为示例操作actionListInvoices
您可以用echo的内容构建一个字符串,并使用return代替echo

/**
 * Displays an array of data model.
 * @param integer $id
 * @return mixed
 */
public function actionListInvoices($patient_id)
{
    $invoices = \app\models\Invoices::find()->joinWith(['patientVisit pv'])->where(['pv.patient_id' => $patient_id])->andWhere(['or', ['invoices.status_id'=> 1], ['invoices.status_id'=> 4]])->all();

    $count = \app\models\Invoices::find()->joinWith(['patientVisit pv'])->where(['pv.patient_id' => $patient_id])->andWhere(['or', ['invoices.status_id'=> 1], ['invoices.status_id'=> 4]])->count();

    if ($count > 0) {
        $total_amount = 0;
        $myEcho = '<table class="table table-bordered table-inverse table-hover">
            <thead class="thead-inverse">
                <th>Invoice #</th>
                <th>Invoice Date</th>
                <th>Due Date</th>
                <th>Amount</th>
                <th>Amount Paid</th>
                <th>Amount Due</th>
            </thead>
            <tbody>';

        foreach($invoices as $invoice){
            $myEcho .= '<tr>
                    <td>'.$invoice->invoice_number.'</td>
                    <td>'.$invoice->date_created.'</td>
                    <td>'.$invoice->due_date.'</td>
                    <td>'.$invoice->invoiceAmount($invoice->invoice_id).'</td>
                    <td>'.$invoice->paidAmount($invoice->invoice_id).'</td>
                    <td>'.$invoice->amountDue($invoice->invoice_id).'</td>
                </tr>';
            $total_amount = $total_amount + $invoice->amountDue($invoice->invoice_id) - $invoice->amountUnallocated($invoice->patientVisit->patient_id);
        }
       $myEcho .=  '<tr>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td><strong>Previous over-Payment</strong></td>
                 <td class="total">'.$invoice->amountUnallocated($invoice->patientVisit->patient_id).'</td>
            </tr>
            <tr>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td></td>
                 <td><strong>Total Due</strong></td>
                 <td class="total">'.$total_amount.'</td>
            </tr>';
         $myEcho .= '</tbody></table>';
    } else {
        $myEcho ='Patient has no pending invoice';
    }
    return $myEcho;
}

并(作为建议)在MVC模式中,应将输出代码放置在视图中,而不是在控制器/动作内部。(在控制器/动作中,您应检索数据并调用传递数据的render函数)