How to sleep() between controller actions?

I’m developing a limited functionality prototype for a prospective client to close the sale. What I need is a way to display a “Processing…” view between the “Buy” and “Print Receipt” views to simulate the transaction processing. Inserting sleep() at the beginning of the controller action (and also inserting it directly on the view) isn’t working because the browser just displays a blank page for the duration of the sleep and then renders the last view directly. I’ve looked all over this site and haven’t found anything. Any ideas? Thanks in advance.

You could try using an HTML redirect with a delay. So, on the "Buy" page, you click a button or whatever which takes you to an intermediate page displaying 1) a progress bar, 2) a Processing Your Order… message, or 3) whatever you want. The page displays for N seconds and then automatically redirects to the "Print Receipt" page. You could have a single controller with actionBuy, actionWait, and actionReceipt methods each rendering the appropriate view.

This link explains the various HTML redirect options: HTML Redirect Explained

@bglee

Thanks for your prompt reply. What you described is exactly what I’m trying to do but I used PHP rather than plain old HTML. I’ll take a look at your suggestion and report back any results. Thanks again.

UPDATE – these approaches (HTML/JavaScript) require changes to the layout because they’re embedded in the <HEAD> section and/or <BODY> tag. Unfortunately that’s too complicated for this limited prototype.

Any more ideas are greatly appreciated.

Well, you could copy the layout files easily enough for a prototype. The <HEAD> section is probably in a main.php. Create a main_alt.php with the only difference being the delayed redirect. Copy column1.php (for example) as column1_alt.php and reference the main_alt.php instead of main.php. You only need this for your Processing Your Order…page. So, either within actionWait or in the actual view, specify


$this->layout='column1_alt.php'

The changes to the layout copies are minor.

An easier way: it suddenly occurred to me that you could just use a partial view (i.e. called using renderPartial() ) for actionWait. The partial view doesn’t use the layout. You could also use a static page with the layout set to false.

Thanks @bglee, I’ll look into it!

I’ve got another idea/approach that I used in my recent project.

I used jQuery. I binded most time-consuming operation (through onClick in menu) to jQuery function displaying progress window and then to redirect current page to required route. This way, my users sees some message (i.e. "Loading"), when page actually loads instead of thinking for 10-20 seconds that nothing is going on.

You could use the same idea, only instead of displaying progress window, use jQuery delay function. This way, after clicking, your browser would wait some seconds and then redirect, where you want.

@Tredjer:

Thanks for the tip. Unfortunately I’m no jQuery expert so if you could post a code snippet I could research it further.

@JFReyes

I’m including a renderPartial solution below.




// Test controller with 3 actions: index, receipt, and wait.

// Note: The Wait action makes a call to renderPartial

<?php


class TestController extends Controller

{

	public function actionIndex()

	{

		$this->render('index');

	}


	public function actionReceipt()

	{

		//$this->render('receipt');

                echo "Your receipt is below:";

	}


	public function actionWait()

	{

		$this->renderPartial('wait');

	}

}



The wait.php view file:




<html>

    <head>

        <meta http-equiv="refresh" content="5;url=receipt">

    </head>

<p>

    <b>Your order is being processed...</b>

</p>

</html>



If you set this up in your environment and go to the url at …test/wait, the controller will run the wait action. It will display "Your order is being processed…" for 5 seconds then redirect to the receipt action.

Thanks @bglee, I got it working. The renderPartial solution is simple and solid. Thanks for your help.

Sorry, for a late reply, but I’m not visiting Yii forum to often recently.

My solution is quite simple (and it is even simpler in your case). First, you create any link in any of your views. Here is an example:


<a href="javascript:void(0);" onclick="delayedRedirect(800, '/yii_app_name/controller/action.html')">

	<span>The Link</span>

</a>

As you can see, this function is taking only two parameters - first is the delay time in miliseconds and second one is the actual route, where document should be redirected after delay.

The URL (route) used in this link can be written by-hand or generated using YII standard route array:


array('/controller/action')

And then here you have definition of JS function used (in my example it is a partial view added with partialRender to views, where I’m using this solution):


<?php

    	Yii::app()->clientScript->registerScript('delayed-redirect',

    	'

            	function delayedRedirect(time, url)

            	{

                    	$(document).delay(time);


                    	if(url != "") window.location.href = url;

            	}

    	'

    	, CClientScript::POS_HEAD);

?>

Hope, this will help.

Thank you @Trejder, I’ll add this to my knowledgebase (bag of tricks) :)

Can we do this using Flash Messages as this is what it is supposed to do? Yii::app->user->setFlash()?