how can i get an url params along with redirect url for zend php framework?
lets say i have the following URL on current page
localhost/business/microsoft
when a user click a button on that page it will redirect them to another page with the following url
localhost/comment/WavvLdfdP6g8aZTtbBQHTw?return_url=%2Fbusiness%2FWavvLdfdP6g8aZTtbBQHTw
how i can write bootstrap getRouter so it can catch the above url params? the current one seems not doing well
$router->addRoute('comment', new Zend_Controller_Router_Route_Regex(
'business/comment/id=',
array(
'controller' => 'business',
'action' => 'comment'
)
, array(
'id' => '\d+'
)
));
Thanks!!!
You'll want to write a plugin that captures the request parameters either before (preDispatch()) or after dispatch (postDispatch()) depending on whether or not you might want to intercept and redirect the request.
//basic example of controller plugin
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
return $this->getRequest->getParams();
}
}
Then register your plugin.
Related
I've got urlManager section in app configuration with several URLs per route:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'article-a' => 'article/a', // canonic comes first
'article-deprecated-a' => 'article/a',
'article-another-a-is-deprecated' => 'article/a',
'b-annoucement' => 'announcement/b', // canonic comes first
'legacy-b-annoncement' => 'announcement/b',
...
SEF URLs for routes are stored in frontend/config/main.php as an array, with multiple URLs per route. The first URL for the given route (i.e. /article-a) is canonical and the rest are legacy URLs.
What's the most natural way to specify canonical URL for a group of URLs that are pointing to the same route? It can be either rel="canonical" in view or 301/302 redirect to canonical URL.
Canonical URLs should be preferably specified in a place where the routes were defined (frontend/config/main.php configuration file in this case). The requirement here is that canonical URL should be defined outside of the controller, not hard-coded to controller.
I'm not sure how exactly you need to manage your rules so I'll go for a general use case and I'll base my answer on what I did understand from Paddy Moogan's Article which I will resume within the following example and I hope it helps on designing your required solution:
requirement:
Assuming a Search Engine did send a robot to check page B in my website and I'm not fine with people getting to page B instead of page A. So this is how I can clarify my point to the robot:
Forcing a 301 redirect to page A:
Telling the Search Engine that this page is permanently moved to page A. So please don't send more people to it. Send them to page A instead.
Forcing a 302 redirect to page A:
Telling the Search Engine that this page is temporary moved to page A. So do whatever you think it
is appropriate.
Opening page B (200 status code) but insert a Canonical
link element
pointing to page A:
Telling the Search Engine that this page is working fine but it is to me a secondary page and I would suggest sending the next visitors to page
A instead.
design:
So based on that this is how I would see a possible structure to my rules configuration:
'rules' => [
[
// by default: 'class' => 'yii\web\UrlRule',
'pattern' => '/',
'route' => 'site/index',
],
[
// the custom class
'class' => 'app\components\SEOUrlRule',
'pattern' => 'about',
'route' => 'site/about',
'permanents' => [
'deprecated-about',
'an-older-deprecated-about'
],
'temporaries' => [
'under-construction-about',
],
'secondaries' => [
'about-page-2'
]
],
[
// different route with own action but canonical should be injected
'class' => 'app\components\SEOUrlRule',
'pattern' => 'experimental-about',
'route' => 'whatever/experimental',
'canonical' => 'about'
],
]
This way I can chain as much arrays as I need to use Yii's default class yii\web\UrlRule while I can have a custom one in my app components folder dedicated to SEO related controllers.
Before going to code, this is how I would expect my website to behave :
You visit the /about page you get a 200 response (no
canonical added).
You visit the /deprecated-about page you get redirected to
/about with 301 status code.
You visit the /under-construction-about page you get redirected to
/about with 302 status code.
You visit the /about-page-2 page you get a 200 response (rendered by index/about action). No redirections except a similar tag to this is automatically injected into source code:
<link href="http://my-website/about" rel="canonical">
You visit the /experimental-about page you get a 200 response (rendered by its own action whatever/experimental) but with that same canonical tag above injected.
code:
The SEOUrlRule will simply extend \yii\web\UrlRule and override its parseRequest method to define the extra attributes based on which we will force a HTTP redirection or call parent::parseRequest() after registering the canonical link tag to the Yii::$app->view:
namespace app\components;
use Yii;
class SEOUrlRule extends \yii\web\UrlRule
{
public $permanents = [];
public $temporaries = [];
public $secondaries = [];
public $canonical = null;
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if(in_array($pathInfo, $this->permanents))
{
$request->setPathInfo($this->name);
Yii::$app->response->redirect($this->name, 301);
}
else if(in_array($pathInfo, $this->temporaries))
{
$request->setPathInfo($this->name);
Yii::$app->response->redirect($this->name, 302);
}
else if($this->canonical or in_array($pathInfo, $this->secondaries))
{
$route = $this->name;
if ($this->canonical === null) $request->setPathInfo($route);
else $route = $this->canonical;
Yii::$app->view->registerLinkTag([
'rel' => 'canonical',
'href' => Yii::$app->urlManager->createAbsoluteUrl($route)
]);
}
return parent::parseRequest($manager, $request);
}
}
And that is all what it needs. Note that Yii::$app->controller or its related actions won't be yet available at this early stage of solving routes as it is shown in this lifecycle diagram but it seems that Yii::$app->view is already initialized and you can use its $params property to set custom parameters (as it is done in this example) which may be useful for more advenced cases where more data should be shared or populated to final output.
I think you will have problems when creating the URL from the application to "article/a".
Why not use htaccess or the vhost file to do a 302 redirect to the proper URL?
If you want to handle it through the urlManager, I think you can just register the canonical link
$this->registerLinkTag(['rel' => 'canonical', 'href' => 'article/a']);
in the view.
Mode details here: http://www.yiiframework.com/doc-2.0/yii-helpers-baseurl.html#canonical()-detail
Yii2 provides a tool to generate canonnical urls based on your rules.
\helpers\Url::canonical()
The idea is that it will provide you an url to 'article-a'.
In a Zend application with an example url like this one:
http://example.com/profile/423423(some id)
How do I get param from url?
I try to use:
$this->getRequest()->getParam('action');
But I get action does not exist.
then I try something like this:
protected function _initRouter()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
$router->addRoute('profile/:catid', new Zend_Controller_Router_Route('profile/:catid',
array(
'module' => 'default',
'controller' => 'profile',
'action' => 'index' // Check your action and controller
)));
}
How do I get param from url?.
You can use the getParam() methods to retrieve request variables like route, GET and POST.
Inside your controllers action you can do this.
$this->getParam('parameterName'); or $this->getRequest()->getParam('parameterName');
If you want to get the name of action and controller that matched the current route you need to use following methods.
$this->getRequest()->getActionName() and $this->getRequest()->getControllerName()
You should just use
$this->getRequest()->getParam('profile');
from your controller.
You shouldn't need to use a custom route.
Kind regards
Garry
EDIT
I have just noticed that you wish to use the profile controller. The simplest solution would be to add an id into your url like.
http://example.com/profile/id/423423
and get the profile id with
$this->getRequest()->getParam('id');
class IndexController extends Zend_Controller_Action{
public function init(){
if(!isset($_SESSION['administrator'])){
$this->_helper->redirector->gotoRouteAndExit(array('controller' => 'index', 'module' => 'cp', 'action' => 'login'), null,!0,!0);
}
}
}
I tried on Firefox, it shows me:
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
But when I put redirector outside of init() method, it works.
public function indexAction(){
if(!isset($_SESSION['administrator'])){
$this->_helper->redirector->gotoRouteAndExit(array('controller' => 'index', 'module' => 'cp', 'action' => 'login'), null,!0,!0);
}
}
Can anyone help me?
Edit:
I don't want to repeat the "redirect code" because there are many other actions need to be checked permission in the same controller.
The problem is, that on index/login, you also run the init() method, detect that the user is not an admin, and try to again redirect him to index/login, which will run the init() method again, detect that he still is not an admin... and so on. Thus the infinite redirect loop.
So in your init() you may first check if you are trying to call the login action, and only if not, check for admin permissions and redirect to index/login.
In your concrete case, you may want to change your init() method as follows:
public function init(){
if ($this->getRequest()->getActionName() !== 'login' && !isset($_SESSION['administrator'])){
$this->_helper->redirector->gotoRouteAndExit(array('controller' => 'index', 'module' => 'cp', 'action' => 'login'), null,!0,!0);
}
}
This excludes the login action from checking admin permissions and redirecting, breaking the infinite redirect loop.
The thing is, init() function will always runs first in any controller,
So When you do a redirect is init() it essential redirects to itself , which will create infinite loop in your case, so it will keep redirecting to itself, as "BluePsyduck" Suggested.
So do the alternate what you have already done and redirect it in index Action of your controller..
I am using zend framework 2.1. I am trying to load the output of my indexAction from my login controller inside of my index controller. The end result I am trying accomplish is to just have my login form loaded on the index page as if it is part of that view.
I have searched for a few hours with no avail. I have attempted to use $this->view->action, which i've seen in earlier versions of zf2 but that has not worked either.
Any information would be helpful.
Taken from this blog, which explains in depth why $this->view->action() has been removed from ZF2, an example how to use the forward() (ZF2 documentation) controller plugin:
You can forward all necessary data to another controller inside your index controller action using the forward() controller plugin like this:
public function indexAction() {
$view = new ViewModel();
$login_param = $this->params('login_param');
$login = $this->forward()->dispatch('App\Controller\LoginController', array(
'action' => 'display',
'login_param' => $login_param
));
$view->addChild($login, 'login');
return $view;
}
In your view, all you need to do is:
<?php echo $this->login; ?>
Please note that the forward() plugin might return a Zend\Http\PhpEnvironment\Response instead. This happens if you use a redirect() in your login controller / action.
Also, if the Servicemanager claims to not find App\Controller\LoginController, have a look in your module.config.php. Look for a section called controllers.
Example:
[...]
'controllers' => array(
'invokables' => array(
'LoginCon' => 'App\Controller\LoginController',
'IndexCon' => 'App\Controller\IndexController',
'DataCon' => 'App\Controller\DataController',
)
),
[...]
Here, there is an alias for your login controller called LoginCon, you should use this name as controller name in the dispatch() method instead.
I recently upgraded from CakePHP 1.2 to CakePHP 1.3 and now I have some code that is trapping the user in a redirect loop. This is after the user has successfully logs in and decides to click on a link to manage emails.
I have some code in a controller where the index() method will check if the current user is an admin or not. If the user is not an admin it will do the following:
function index()
{
if ($this->Session->read('is_admin') < 1) {
$this->redirect(array('controller' => 'emails', 'action' => 'view', 'id' => $this->Session->read('username')));
}
//...more code...
}
This is intended to redirect the user to a view() method and display only their email and not everyone's email. What is happening when I debug this is the redirect keeps ending up in the index() method.
Is there something new in CakePHP that I'm missing? Is it a no-no to use the name "view" as an action in a controller?
* EDIT *
Okay, I was a little premature with this post. The code in the view($username) method is being reached. But the thing is the $username is not defined and I have some client code that is then redirecting back to the index() action if it is not defined.
I did check the original redirect and the $this->Session->read('username') is populated with the username but it is just not being passed in the view()'s $username argument.
Thanks!
It turns out the redirect signature changed from 1.2 to 1.3:
http://book.cakephp.org/view/1561/Migrating-from-CakePHP-1-2-to-1-3
Library Classes > Router
// CakePHP 1.2 way
$this->redirect(array('controller' => 'emails', 'action' => 'view', 'id' => $this->Session->read('username')));
// CakePHP 1.3 way
$this->redirect(array('controller' => 'emails', 'action' => 'view', $this->Session->read('username')));