How to output data with no html markup ?

Hi !

My question is very simple : how can I output data from Yii with no html markup wrapping it ?

I tried :


public function actionTest() {

	$this->layout='';

	echo "I WANT YOU IN MY ROOM";

}

And the output received in my browser is :


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">

<html>

<head>

<title></title>

</head>

<body>

I WANT YOU IN MY ROOM

</body>

</html>

The desired output being :


I WANT YOU IN MY ROOM

Note that I tried any layout=none, app->end() combo.

Any idea on how to achieve that ?

Have you tried some text in the property $this->layout=‘none’;

Where are you getting that output with such a simple echo… there is not even the need to set the layout=’’…

Layouts are displayed on RENDER… echo doesn’t affect… Make sure that you look at some kind of http request/response filter not on the firebug / chrome dev tools, as they tend to display formatted html page.

You are probably using the default layout ?

If you want pure and raw output, you could just create a layout file which looks like this:


<?php echo $content;

This is how it normally looks:




<?php $this->beginContent('//layouts/main'); ?>

	<?php echo $content; ?>

<?php $this->endContent(); ?>

In the normal case, the content of layouts/main is wrapped around the content and thus giving you HTML.

<edit>

If you can’t get your browser to display plain content, then the problem is most likely that you need to send a header indicating the content type.

Otherwise the browser will generate the html automatically.

Especially modern browsers.

Thank you all, here are my answers to each of you :)

@vpk369: As said in the initial post, I tried to set $this->layout to none but it didn’t affect the output.

@Antonio Ramirez: I am well aware of the fact that echo and partialRender are not concerned by any kind of layout, but I was wondering that maybe there could be some default layout added in case the output was exempt of any html markup. I guess not…

As for the response in the browser, since the output is a response to an ajax call, it is not supposed to be rendered, thus I don’t expect it to be altered by the browser’s rendering engine or anything. Plus, I also modified the header in order to specify a json content, so the browser knows what it’s handling.

@jacmoe: the controller used to have the default layout but I created one simply echoing the $content and set it to be used by the controller. Anyway I am not using any render, only echo or renderPartial which are supposed to be raw output (layout-free).

As said in the answer to Antonio Ramirez, I changed the header and the browser noticed that it was some json content. Still the response contains html markup wrapped around my generated json.

To all: I am pretty sure that the browser is not involved because I changed my ajax call to a static html file containing the expect content (html-markup-free json), and it worked.

Thanks you all, I really do hope to find a solution to that issue since I’ve been on it for quite a few days.

If you are not setting any layout, the default layout for the controller will be used.

You need to explicity tell it to either not use one or use your custom layout.

Also when using echo: the content will appear in the default layout even if you are not rendering (or think that you are not rendering, because you really are). :)

I am currently working on a very heavy project, and we do a lot of AJAX-JSON related requests/responses and we do not have any issue at all and there is no html wrapped within it. There is no layout wrapping, nothing at all when you just echo from a controller’s action if you are not using render method…

I am not modifying even headers when working with JSON responses and our javascript code works very smooth… so, if you still having html wrapped within AJAX responses, then I doubt you are just using ‘echo’. Would be nice to see the actual code to check where is the issue.

Cheers

Even if I have no view and no layout, when I go to the url http://myapp/controller/action I see the output wrapped in HTML.

Obviously, that doesn’t happen if I don’t view the url in my browser.

The only way I could overcome that was to issue a header in some overridden controller function which I can’t remember. :)




public function actionTest() {

    echo "I WANT YOU IN MY ROOM";

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

}



That works for me well.

BTW, here is base ajax controller that we use:




class AjaxController extends Controller

{


	protected function success($data = array())

	{


		if ($this->beforeRender($data)) {

			$json = CJSON::encode(

				array(

					'success' => true,

				) + $data);


			$callback = $this->request->getParam('callback');


			if ($callback) {

				$json = $callback . '(' . $json . ')';

			}


			$this->noStoreHeaders();


			// lugs in IE7,8 with ajax form submitting

			if (!$this->request->isPostRequest)

				header("Content-type: application/javascript");


			echo $json;


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

		}

	}


	protected function error($message = '', $data = array())

	{

		if ($this->beforeRender($data)) {

			$json = CJSON::encode(array_merge(

				                      array(

				                           'id' => -1,

				                           'success' => false,

				                           'message' => $message

				                      ),

				                      $data

			                      ));

			$callback = $this->request->getParam('callback');


			if ($callback) {

				$json = $callback . '(' . $json . ')';

			}


			$this->noStoreHeaders();


			// lugs in IE7,8 with ajax form submitting

			if (!$this->request->isPostRequest)

				header("Content-type: application/javascript");


			echo $json;


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

		}

	}


        protected function noStoreHeaders() 

        {

		header('Cache-Control: no-store');

		header('Pragma: no-store');

	}

}

	




// usage 

class TestAjaxController extends AjaxController

{

	

	public function actionRight()

	{

		$this->success(array(

			'key' => 'value',

		));

	}

	

	public function actionWrong()

	{

		$this->error("Some error details");

	}


}



Hi,

So I rechecked my code on a fresh webapp. Even the simplest test - setting a dumb layout echoing $content and then echoing some text from a controller’s action - failed.

application.views.layout.empty :


echo $content;



Note: adding


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

prevented any further loading.

application.controllers.SiteController :


...

public $layout = 'application.views.layouts.empty';

public function actionTest() {

	echo "I WANT YOU IN MY ROOM";

}

...

The layout is used since the default actionIndex is now rendered without any style but is still wrapped in basic html (doctype, html, header, body).

I don’t know what else to tell you…

Thanks as always ;)

Where do you see the code returned? On the browser? If ajax call THERE IS NO LAYOUTS if you just ECHO content, not basic ones… BUT, if you look at that action on a browser is obvious as the browser will set basic html as jacmoe already pointed.

Are you checking your AJAX calls with FIREBUG or CHROME console XHR requests? or just using the view code of the browser?

If you echo, there is no wrapping at all to blame Yii.

I’m sorry to look like a fool but yes I’m using Chrome’s XHR so I don’t think the browser adds any html. I tried to load a file containing no html and no html was present in XHR view. That’s why I’m still looking in Yii’s direction.

Try this




public function actionTest() {

    echo "I WANT YOU IN MY ROOM";

    exit;

}



I had a problem sending JSON once because Yii was adding the debug info (I had debug on) and that screwed up IE’s JSON parser. Forcing the exit at the end of the action will solve this.

Note that Yii::app()->end(); is not the same as a plain exit; because events will still be triggered and can also add stuff after.

If you don’t setting any layout, the default layout for the controller will be used.

The workaround is simple, create a blank layout without markup like this: views/layouts/empty.php

From now, if you had any page that contains full markup HTML and don’t want inherit the parent layout, just add following line in the action.


$this->layout = '//layouts/empty';

In case of calling action by ajax, you just add following line at the end of action


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

Well I don’t see any problem just using echo with no “render” call. I’ve done that many times and the output is just the plain text. Viewing source in the browser shows nothing but the plain text.

You have something else going on.

Maybe something in /components/controller.php ?

Do you have something in "init" causing this?

Are you by any chance passing all output through HTML Purifier somehow?

Is there an extension that is causing this behavior?

Summary:

Look elsewhere. If you’re using echo in the way you described in the simple example, there is something else causing your problem.

Try a fresh app with nothing added to see what behavior you have there. If it’s the same then start looking at browser plugins or try a different browser altogether.