I have views from various controller actions which are solely to be run from an iframe placed in another view.
Currently, when the iframe loads, and I go to the log in page to log in, on success the login controller (using yii2 user module) calls $this->goBack()
, redirecting me to the iframe source URL (since it's the last page visited), rather than the original page containing the iframe.
Basically, I'd like to exclude specific controller actions from being set as the return URL when $this->goBack()
is called. Bonus points if all actions loaded in iframes are automatically excluded from $this->goBack()
.
Ok, I'll have a go at this! This code is totally untested! Your problem is that the action has no way of knowing whether it's been called from an iframe or not, unless you give it one. So, the basis of my attempt at an answer is that all urls for iframes should have an additional get parameter. Lets call that caller
. So each iframe should look something like
<iframe url="index.php?r=controller/action&caller=this-controller/action</iframe>
Now you can always test the request url to see if it was called from an iframe. In addition, every link within the iframe should have this parameter added to it's url.
So, now we have at least two problems. Firstly, how to automatically add caller
as a get
parameter, without having to re-write every url, and secondly, how to reconfigure the goBack()
method so it knows the difference between the two types of request.
The first problem can be relatively easily resolved by adding another view layer in between the controller and the view you want I'll call it iframe
. So in your controller action, add this;
$view = 'The name of the view you want to render';
$this->render('iframe', 'view' => $view);//Add in any other parameters you want to pass
Your iframe view file should contain something like this;
<iframe src="<?php Url::to(['however you generate the url for your iframe', 'caller' => Url::to($this->context->route)]); ?>">
<?php $this->render($view); ?>//Pass additional parameters to the view if needed
</iframe>
Now we have a way of testing a controller/action
call to see if it being requested by am iframe. The caller
parameter is important because it allows us to extract a string to use as the value for goBack()
and other methods.
Next, we need to extend UrlManager
, as all request
, response
, Url:to()
and goBack()
methods and classes ultimately use the UrlManager
to complete the methods for generating urls.
So, create a new UrlManager. We'll copy most of the code from the existing UrlManager, just adding some spiciness of our own. I've stored mine in commands
, but put your where you like and change the namespace accordingly.
<?php
namespace app\commands;
use Yii;
use yii\web\UrlManager;
class CustomUrlManager extends UrlManager {
public function createUrl($params){
$request = Yii::$app()->request;
$caller = $request->get('caller');
if ($caller && !$params['caller']){
$params['caller'] = $caller;
}
return parent::createUrl($params);
}
}
So now, the iframe generates a caller
parameter, and every link within the iframe will also have caller
appended as a parameter, as long ass you've used either Url::to()
(or variants on that method) or Yii::$app->UrlManager
to generate your links.
Now all we need to do is customise the goBack() method of your controller to send any goBack() requests to the original source iframe.
public function goBack($defaultUrl = null)
{
$caller = Yii::$app->request->get('caller');
if ($caller){
return Yii::$app->getResponse()->redirect($caller);
}
return Yii::$app->getResponse()->redirect(Yii::$app->getUser()->getReturnUrl($defaultUrl));
}
Finally you need to configure Yii to use your new UrlManager, in your config file;
'components' => [
'urlManager' => [
'class' => 'app/commands/CustomUrlManager'
]
]
I'd love to know if this works, it's been an interesting challenge!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With