Consolecommand: Eseguire Una Action Di Un Controller

Ho una pagina che mi fa un bellissimo report

E’ il risultato di una action, a cui passo semplicemente una data (tra l’altro via ajax-post), la quale fa un renderPartial del solo report.

Ora vorrei che ogni sera un mio ConsoleCommand potesee ottenere lo stesso report, senza riscrivere codice, e inviarlo via mail.

Inviare dell’html via mail non è mai stato un problema.

Ma che tecnica uso per ‘eseguire’ una action e “catturarne / usarne” l’output ?

A favore dei posteri, vi trasmetto la soluzione, anche se mi rendo conto che è un po’ specifica per la mia esigenza, che NON è quella di eseguire una action ‘e basta’ ma ne devo proproprio avere l’output.

Nel mio caso specifico si tratta di una action che fa un renderPartial, perchè viene chiamata via ajax allo scopo di aggiornare una parte della pagina dinamicamente.

Questa stessa parte di pagina deve essere inviata via mail tramite console command schedulato tramite cron.

1. Rendere l’action desiderata una function privata, dandogli un nome diverso

questa deve accettare un parametro booleano, per esempio ‘return_output’.

Passare alla function eventuali parametri necessari, nel mio caso la data di riferimento, che è presa dalla chiamata ajax oppure passata a forza come ‘oggi’ se chiamato dal console command




// Called from actionGetReportViaAjax and actionGetReportOutput

private function getReport($date, $return_output)



.

2. Ricreare l’action modificata in modo che si limiti a chiamare la function privata

In questo caso il parametro sarà false. Dopo sarà piu chiaro perchè




public function actionGetReportViaAjax()

{

    $request = Yii::app()->getRequest();

    $date   = $request->getParam("date");

    // volendo potete verificare così che sia chiamato solo via ajax

    if (!$request->isAjaxRequest) {

        throw new Exception("Your request is invalid", 1);

        return;

    }


    // chiamo la function privata dandogli la data e

    // chiedendo che NON venga dato restituito l'output come stringa

    $this->getReport($date, false);

}



3. Creare una nuova action a specifico uso del console command

In questo caso il parametro


"$return_output"

sarà true.

La function farà semplicemente qualcosa come questo:




public function actionGetReportOutput()

{

    // chiamo la funzione passandogli la data 

    // in questo caso richiedo l'output come stringa

    $output = $this->getReport(date("Y-m-d"), true);

    return $output;

}



4. Nella function privata (‘getReport’), modificare la parte relativa al renderPartial

In verità come tecnica si applica anche al render normale come tecnica.

Bisogna che i parametri da passare al render siano messi in una variabile, invece che passati esplicitamente come array.

esempio




$param_array = array (

        'month_names'               => $month_names,

        'abbreviated_month_names'   => $abbreviated_month_names,

);



Quindi valutiamo se eseguire restituire l’output o no




if ($return_output) {

    $renderer = new CPradoViewRenderer();

    $view = YiiBase::getPathOfAlias("application.modules.order.views.charged") . "/_report.php";

    return $renderer->renderFile($this, $view, $param_array, true);

}


// output

$output = $this->renderPartial("_report", $param_array, $return_output);



5. il console command

Importa esplicitamente il controller




Yii::import('application.modules.order.controllers.ChargedController');



Lo istanzia




$orderController = new ChargedController("Charged"); 



Esegue l’action specifica appena creata




$output = $orderController->actionGetReportOutput();



Che ne pensate ?