OK, będę musiał się z tym pogodzić! Ten kod jest całkowicie nieprzetestowany! Twój problem polega na tym, że akcja nie ma możliwości sprawdzenia, czy została wywołana z elementu iframe, chyba że ją podasz. Tak więc podstawą mojej próby odpowiedzi jest to, że wszystkie adresy URL dla elementów iframe powinny mieć dodatkowy parametr get. Nazwijmy to caller
. Więc każdy iframe powinna wyglądać
<iframe url="index.php?r=controller/action&caller=this-controller/action</iframe>
Teraz zawsze można przetestować URL żądania, aby sprawdzić, czy został wywołany z iframe. Ponadto każdy link w elemencie iframe powinien mieć ten parametr dodany do adresu URL.
Mamy teraz co najmniej dwa problemy. Po pierwsze, jak automatycznie dodać caller
jako parametr get
, bez konieczności ponownego napisania każdego adresu URL, a po drugie, jak zmienić konfigurację metody goBack()
, aby wiedzieć, jaka jest różnica między tymi dwoma typami żądań.
Pierwszy problem można stosunkowo łatwo rozwiązać, dodając kolejną warstwę widoku pomiędzy kontrolerem a żądanym widokiem. Nazywam to iframe
. A więc w akcji kontrolera dodaj to;
$view = 'The name of the view you want to render';
$this->render('iframe', 'view' => $view);//Add in any other parameters you want to pass
Twój plik widoku iframe powinien zawierać coś takiego;
<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>
Teraz mamy sposób testowania controller/action
wezwanie, aby zobaczyć, czy to jest wymagane przez am iframe. Parametr caller
jest ważny, ponieważ pozwala nam wyodrębnić ciąg znaków do użycia jako wartość dla goBack()
i innych metod.
Następnie musimy rozszerzyć UrlManager
, ponieważ wszystkie request
, response
, Url:to()
i goBack()
metody i klasy ostatecznie użyć UrlManager
wypełnić metody generowania adresów URL.
Stwórz więc nowy UrlManager. Skopiujemy większość kodu z istniejącego UrlManager, dodając tylko odrobinę pikanterii. Przechowałem kopalnię w commands
, ale umieść ją tam, gdzie chcesz i odpowiednio zmień przestrzeń nazw.
<?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);
}
}
Więc teraz, iframe generuje parametr caller
, a każde ogniwo w iframe będzie również caller
dołączana jako parametr, jak długo ass użyłeś albo Url::to()
(lub wariantów tego sposobu) lub Yii::$app->UrlManager
generować twoje linki.
Teraz wystarczy, że dostosujemy metodę goBack() kontrolera, aby wysłać wszystkie żądania goBack() do oryginalnego źródła 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));
}
Na koniec musisz skonfigurować Yii, aby używać nowego UrlManager w pliku konfiguracyjnym;
'components' => [
'urlManager' => [
'class' => 'app/commands/CustomUrlManager'
]
]
Chciałbym wiedzieć, czy to działa, to było ciekawe wyzwanie!
Czy wszystkie twoje ramki iframe zajmują tę samą stronę widoku? –
Nie, elementy iframe znajdują się w różnych widokach. – Dean