I'm trying to capture a URL parameter in my bootstrap file but after several attempts I'm not able to do it.
I've tried this but it does not work:
protected function _initGetLang() {
$frontController = Zend_Controller_Front::getInstance();
$lang= $frontController->getParam('lang');
}
Is this the right way to do it?
Thks.
You won't be able to access the request params from the bootstrap because it hasn't yet gone through the dispatch/routing process. I think you'd be better served by using a Controller Plugin, performing actions based on the URL is what they do best. Or if you absolutely have to do it in the bootstrap, getRequestUri() or $_GET is available, or you could write a quick script to parse the url yourself.
Edit:
I've done some silly stuff like this in the past before I figured out how plugins work:
/**
* Grab the module name without a request instance
*
* #return string The module name
*/
public static function getModuleName()
{
$uri = ltrim($_SERVER["REQUEST_URI"], "/");
$module = substr($uri, 0, strpos($uri, "/"));
return $module;
}
This would at least give you a module name that you could switch on in the bootstrap. You should be able to do anything you need with the plugins done correctly though.
Related
I would like to generate a rich snippet for ratings in my TYPO3 pages. The rating information are fetched via an API, so I need some kind of caching mechanism.
I have some basic knowledge and experience with TYPO3 extensions, but I am not sure about the cleanest solution. I could render the meta tags with the TYPO3 Meta Tag API and cache the fetched information using the TYPO3 Caching Framework.
But I am not sure where to store the logic so that it gets executed at every page visit. I do not want to use a content plugin for obvious reasons. Should I set up a Controller and call the Contoller's function with e.g. some hook?
Thanks for any help!
You may have a look at the tslib/class.tslib_fe.php hooks in TypoScriptFrontendController class.
Choose the correct one (maybe tslib_fe-PostProc) and do something like this :
1) Register hook in ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['tslib_fe-PostProc'][] = \Vendor\Name\Hook\AdditionalMetaData::class . '->addRating';
2) Create your class with the following method
<?php
namespace Vendor\Name\Hook;
class AdditionalMetaData
{
/**
* #param array $parameters
* #return void
*/
public function addRating(&$parameters)
{
/** #var TypoScriptFrontendController $tsfe */
$tsfe = &$parameters['pObj'];
// Do your logic here...
}
}
I have an existing web application accessing a MySQL database. I'm porting this application to Symfony. The new application has to use the old database, as we cannot port the whole application at once, i.e. the old and the new application are accessing the same database and the applications are running simultaneously.
The old application had a simple CMS functionality which has to be ported:
There is a table pagewhich represents a page tree. Every page has a slug field. The URL path consists of those slugs representing the path identifying the page node, e.g. "/[parent-slug]/[child-slug]".
The page table also contains a content field. As I already mentioned, the CMS functionality is very simple, so the content is just rendered as page content inside a page layout. The page entry also specifies the page layout / template.
My problem is that I don't know how to set up the routing. In a normal Symfony application I'd know the URL patterns before, but in this case they are dynamic. Also routes cannot be cached, because they could be changed any time by the user. I wonder if I have to drop Symfony's routing completely and implement something on my own. But how?
Now I found Symfony CMF which tells a lot about the framework VS CMS routing conflict. So first, I thought this would be the right way. However the tutorials aim at building an entirely new application based on PHPRC. I wasn't able to derive the tutorial's concepts to my use case.
since you run several URL rules on one symfony application, you will need to work with url prefixes. Either your cms should work with a prefix /cms/parent-slug/child-slug or all other controllers. Otherwise you are not able to differ which controller is meant when a dynamic request arrives.
You can try a workaround with a KernelControllerListener. He will catch up every request and then check if a cms page is requested. On the basis of the request you can set controller and action by yourself. Concept:
Create only one route with "/". Abandon oll other rules. Then create a Listener like this:
<?php
namespace AppBundle\Listener;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
/**
* Class KernelControllerListener
* #package ApiBundle\Listener
*/
class KernelControllerListener
{
/**
* #var CmsRepository
*/
private $requestParser;
/**
* KernelControllerListener constructor.
* #param CmsRepository $CmsRepository
*/
public function __construct(CmsRepository $CmsRepository)
{
$this->CmsRepository = $CmsRepository;
}
/**
* #param FilterControllerEvent $event
*/
public function onKernelController(FilterControllerEvent $event){
$request = $event->getRequest();
//should be /parent-slug/children/slug or any other path
$path = $request->getPathInfo();
if($this->CmsRepository->getCmsControllerIfMatch($path)){
//cms repository search in db for page with this path, otherwise return false
$event->setController([AppBundle\CmsController::class, 'cmsAction']);
return;
}
//repeat if clause for any other application part
}
}
in services.yml:
app.controller_listener:
class: AppBundle\Listener\KernelControllerListener
arguments:
- "#app.cms_repository"
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
Edit: catch all routes, see https://www.jverdeyen.be/symfony2/symfony-catch-all-route/
The question is: Do you whant to migrate the data or not. For both question, the CMF can be an answer. If you wanna a simple dynamic router, you should have a look into the ChainRouter with an custom router definition:
https://symfony.com/doc/current/cmf/bundles/routing/dynamic.html
and
https://symfony.com/doc/current/cmf/components/routing/chain.html
If you wanna migrate the data, you can use fixture loaders, as we use in almost all of our examples.
One of the application I am developing using Zend Framework requires the user's profile page to be accessed via website.com/username, while other pages should be accessed by website.com/controller_name/action_name
I am not too sure how can this be achieved, however, I feel this can be done with some tweaks in the .htaccess file.
Can someone here please help me out?
Many thanks in advance
As suggested before, you can use a custom route that will route single level requests. However, this will also override the default route. If you're using modules, this will no longer work example.com/<module>.
I have done this before but only for static pages. I wanted this:
example.com/about
instead of this:
example.com/<some-id>/about
while maintaining the default route so this still works
example.com/<module>
example.com/<controller>
The way I did this was using a plugin to test if my request could be dispatched. If the request could not be dispatched using the default route, then I would change the request to the proper module to load my page. Here is a sample plugin:
class My_Controller_Plugin_UsernameRoute extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
if (!$dispatcher->isDispatchable($request)) {
$username = $request->getControllerName();
$request->setModuleName('users');
$request->setControllerName('dashboard');
$request->setActionName('index');
$request->setParam('username', $username);
/** Prevents infinite loop if you make a mistake in the new request **/
if ($dispatcher->isDispatchable($request)) {
$request->setDispatched(false);
}
}
}
}
What about using Zend_Controller_Router_Route, look here the link http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.standard.variable-requirements
I'm trying to centralise my redirects (based on authentication and various other states) into a front controller plugin. So far I've tried:
$this->setRequest(new Zend_Controller_Request_Http('my_url'));
at various points in the plugin (i.e. from routeStartup to dispatchLoopShutdown) and also:
$this->setResponse(new Zend_Controller_Response_Http('my_url'));
Can anyone offer some assistance on this, or point me in the direction of a tutorial?
The easiest way would be to use ZF's Redirect ActionHelper
$r = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
$r->gotoUrl('/some/url')->redirectAndExit();
Alternatively instantiate it without the HelperBroker
$r = new Zend_Controller_Action_Helper_Redirector;
$r->gotoUrl('/some/url')->redirectAndExit();
The ActionHelper provides an API solely concerned about redirecting through a number of methods, like gotoRoute, gotoUrl, gotoSimple, which you can use depending on your desired UseCase.
Internally, the ActionHelper uses the APIs of Response and Router to do the redirect though, so you can also use their methods directly, e.g.
$request->setModuleName('someModule')
->setControllerName('someController')
->setActionName('someAction');
or
$response->setRedirect('/some/url', 200);
Further reading:
http://devzone.zend.com/article/3372-Front-Controller-Plugins-in-Zend-Framework
http://framework.zend.com/manual/en/zend.controller.actionhelpers.html
http://framework.zend.com/manual/en/zend.controller.response.html
http://framework.zend.com/manual/en/zend.controller.plugins.html
http://framework.zend.com/apidoc/core
http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Controller/
If you are looking to redirect if the user is not logged it, the first parameter of dispatchLoopStartup() is a handle to the request object.
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
if(!Zend_Auth::getInstance()->hasIdentity())
{
$request->setControllerName('auth');
$request->setActionName('login');
// Set the module if you need to as well.
}
}
If you want to redirect in the index page then this should suffice.
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
if(!Zend_Auth::getInstance()->hasIdentity())
{
$baseUrl = new Zend_View_Helper_BaseUrl();
$this->getResponse()->setRedirect($baseUrl->baseUrl());
}
}
If you want to redirect somewhere else then just change the parameter in the setRedirect() function
Thanks!
:)
I've spent many hours trying to get this to work. And I'm getting quite desperate.
Would be great if someone out there could help me out :)
Currently using Zend Framework 1.9.5, though I have been struggling to get this to work for many versions now.
What I want to do is provide my own routes through an XML config, and make sure that everything that is not defined in my config will end up on my errorController.
(preferably in a way so I can em apart from EXCEPTION_NO_CONTROLLER and EXCEPTION_NO_ACTION)
I figured that this means I have to get rid of default /:module/:controller/:action and /:controller/:action routes.
So when I tell the router to removeDefaultRoutes(), it won't match these default routes anymore. But now the router is now routing every unrouted route to the defaultcontroller::defaultaction (What the ??)
$front->getRouter()->removeDefaultRoutes();
So, anyone know how to make the frontcontroller (or a part of it) throw an exception when an URI can not be routed?
Reason I want to do this is to prevent duplicate content, and have better 404 pages (in this case, no controller / no action errors are actually application errors instead of not-found)
did you try adding a new route like
$route = new Zend_Controller_Router_Route('*', array('controller'=>'error', 'module'=>'default', 'action'=>'error'));
$router->addRoute('default', $route);
You need to add this route first as it needs to be the last processed.
Fast forward in time to one year later... (time travel music)
Here's another way that I think is much less "intrusive". You can write a plugin to catch the default route and when that happens just throw an exception which at the end of the whole cycle gets translated into a 404 by the front controller.
class Application_Plugin_DisableDefaultRoutes extends Zend_Controller_Plugin_Abstract
{
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
$front = Zend_Controller_Front::getInstance();
$currentRoute = $front->getRouter()->getCurrentRouteName();
if ($currentRoute == 'default') {
throw new Exception('Default route is disabled');
}
}
}
You can load your plugin in Bootstrap.php
protected function _initPlugins()
{
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Application_Plugin_DisableDefaultRoutes());
}
With this way you can load the plugin in the production machine and leave it out in development where you might want to use the default route for quick tests or something else.