2010-05-13 4 views

Répondre

82

Créer cette fonction dans votre (base) Contrôleur:

/** 
* Return data to browser as JSON and end application. 
* @param array $data 
*/ 
protected function renderJSON($data) 
{ 
    header('Content-type: application/json'); 
    echo CJSON::encode($data); 

    foreach (Yii::app()->log->routes as $route) { 
     if($route instanceof CWebLogRoute) { 
      $route->enabled = false; // disable any weblogroutes 
     } 
    } 
    Yii::app()->end(); 
} 

Ensuite, il suffit d'appeler à la fin de votre action:

$this->renderJSON($yourData); 
+0

J'ai remarqué que la définition de ** header() ** ou ** Yii :: app() -> end(); ** ne fait aucune différence.Dans les outils de développement Chrome, si vous remarquez ** En-tête de réponse ** sous l'onglet ** En-tête **, ils ont tous la même longueur de contenu. Si l'ajax a été fait avec la sortie attendue dans le format "json", alors même si HTML est envoyé, le navigateur/jQuery traite cette réponse comme json. Et il semble fonctionner dans tous les navigateurs modernes. Bien que, je ne nie pas que la définition de l'en-tête() est une bonne chose. – mohitp

+0

Au lieu de désactiver les routes du journal Web, cette approche sera plus robuste (pas encore testé): ~~~ ob_start(); Yii :: app() -> end (0, false); ob_end_clean(); sortie (0); – marcovtwout

9
$this->layout=false; 
header('Content-type: application/json'); 
echo json_encode($arr); 
Yii::app()->end(); 
+0

json_encode ne fonctionne pas avec les modèles –

+4

Quelques tewaks: utilisez CJSON :: encoder() pour les modèles; inutile de faire '$ this-> layout = false' puisque' Yii :: app() -> end() 'terminera l'application sans sortir la mise en page. – Ethan

+0

Je pense qu'il est préférable de changer la meilleure réponse à @marcovtwout –

19
$this->layout=false; 
header('Content-type: application/json'); 
echo CJavaScript::jsonEncode($arr); 
Yii::app()->end(); 
+0

N'oubliez pas non plus de désactiver WebLogRoutes avant d'appeler Yii :: app() -> end(), sinon des informations de débogage pourraient être ajoutées à votre json et potentiellement rendre invalide . – marcovtwout

+0

assez sûr que la fin() éteint les journaux, ce qui explique pourquoi je l'ai ajouté ici –

+1

Ce n'est pas le cas. end(): "Termine l'application Cette méthode remplace la fonction exit() de PHP en appelant onEndRequest avant de quitter." Et dans CLogRouter (http://www.yiiframework.com/doc/api/1.1/CLogRouter#processLogs-detail): "Cette méthode est un gestionnaire d'événements pour l'événement CApplication :: onEndRequest." – marcovtwout

-1
Yii::app()->end() 

Je pense que cette solution est la meilleure façon de mettre fin à l'écoulement d'application, car il utilise la fonction exit() de PHP, sorcière signifie sortie immédiate du flux d'exécution. Oui, il y a le gestionnaire onEndRequest de Yii, et le register_shutdown_function de PHP mais il reste encore trop fataliste.

Pour moi, la meilleure façon est ce

public function run($actionID) 
{ 
    try 
    { 
     return parent::run($actionID); 
    } 
    catch(FinishOutputException $e) 
    { 
     return; 
    } 
} 

public function actionHello() 
{ 
    $this->layout=false; 
    header('Content-type: application/json'); 
    echo CJavaScript::jsonEncode($arr); 
    throw new FinishOutputException; 
} 

Ainsi, le flux de l'application continue d'exécuter même après.

+0

Si vous avez déjà mis layout = false, un simple 'return' fera l'affaire? Peut même être omis. Je ne vois aucune raison d'essayer/attraper et créer une exception personnalisée. – marcovtwout

+1

C'est juste mauvais. Lancer une exception pour sortir la réponse. – grantwparks

+0

Maintenant, après un certain temps, je suis entièrement d'accord que l'utilisation d'exceptions pour gérer la logique de contrôleur/présentation est fausse. – Mihailoff

0

une manière plus simple en utilisant

echo CJSON::encode($result); 

exemple de code:

public function actionSearch(){ 
    if (Yii::app()->request->isAjaxRequest && isset($_POST['term'])) { 
      $models = Model::model()->searchNames($_POST['term']); 
      $result = array(); 
      foreach($models as $m){ 
       $result[] = array(
         'name' => $m->name, 
         'id' => $m->id, 
       ); 


      } 
      echo CJSON::encode($result); 
     } 
} 

cheers :)

5
class JsonController extends CController { 

    protected $jsonData; 

    protected function beforeAction($action) { 
     ob_clean(); // clear output buffer to avoid rendering anything else 
     header('Content-type: application/json'); // set content type header as json 
     return parent::beforeAction($action); 
    } 

    protected function afterAction($action) { 
     parent::afterAction($action); 
     exit(json_encode($this->jsonData)); // exit with rendering json data 
    } 

} 

class ApiController extends JsonController { 

    public function actionIndex() { 
     $this->jsonData = array('test'); 
    } 

} 
0

Dans l'action du contrôleur que vous souhaitez rendre JSON données, par exemple: actionJson()

public function actionJson(){ 
    $this->layout=false; 
    header('Content-type: application/json'); 
    echo CJSON::encode($data); 
    Yii::app()->end(); // equal to die() or exit() function 
} 

Voir plus de Les Yii API

10

Pour Yii2 l'intérieur d'un contrôleur :

public function actionSomeAjax() { 
    $returnData = ['someData' => 'I am data', 'someAnotherData' => 'I am another data']; 

    $response = Yii::$app->response; 
    $response->format = \yii\web\Response::FORMAT_JSON; 
    $response->data = $returnData; 

    return $response; 
} 
+2

Cela aurait dû être la réponse acceptée. +1 pour suivre l'API de Yii. – Gogol

+0

Merci Monsieur!^- ^ –

Questions connexes