A few months ago I posted my experience using the Jake bridge between CakePHP and Joomla. Overall it’s pretty slick, but with one annoyance: the URL’s are not search-engine-friendly. Moreover they broadcast your frameworks of choice which is not a good from a security viewpoint.
So after much research into the Joomla component routing and how the framework parses SEF URL’s, I came up with the following upgrade to Jake, which allows much prettier URLs.
This presumes that you have your Cake app installed in a subdirectory of your Joomla webroot (assume it’s “/webapp”). Secondly, decide upon the SEF base you want to use – it must be different from the former since you want to force it to route the request through Joomla and that requires a path that doesn’t correspond to a physical directory (I chose “/app” to be nondescript).
- Update your /.htaccess file to add a rewrite rule, before the core SEF section, for this new SEF base path:
... RewriteBase / # For Jake: redirect everything that starts with app/ # See http://www.phpbb-seo.com/en/apache-mod-rewrite/article3226.html for more details RewriteRule ^app\/(.*)$ /index.php?option=com_jake&jrun=/$1 [QSA,L] ########## Begin - Joomla! core SEF Section # ...
- In /components/lib/cake_embedded_dispatcher_class.php:597, replace _changeUrl() with the following:
/** * Base for SEF URI's * * @since 1.1 * @var string */ var $sefCakeApplicationBase = null; /** * Set base path to CakePHP application, using SEF URL's. * * @param string $base Base path to Cake application in SEF URI * * @access public * @since 1.1 */ function setSefCakeApplicationBase($base) { $this->sefCakeApplicationBase = $base; } function _changeUrl($start, $p1, $url, $p3, $ending, $startUrl='href="', $endUrl='"', $useComponent = true, $clean = false) { if (isset($this->sefCakeApplicationBase)) { $newUrl = $this->sefCakeApplicationBase . $url; } else { // Patterns to match URLs that should not pass through the component $passThroughLinksMatching = array('/\.jpg$/i', '/\.png$/i', '/\.gif$/i', '/\.pdf$/i', '/\.rss$/i'); if ($useComponent && isset($passThroughLinksMatching)) { foreach($passThroughLinksMatching as $element) { if (preg_match($element, $url)) { $useComponent = false; break; } } } if ($useComponent) { $newUrl = str_replace('$CAKE_ACTION', urlencode($url), $this->component); if (!empty($this->cakeUrlAddParameters)) { $newUrl .= '&' . $this->cakeUrlAddParameters; } if ($clean) { $newUrl .= '&' . $this->cleanOutputParameter; } } else { $newUrl = $this->cakeUrlBase . $url; } } $newUrl = str_replace('&', '&', $newUrl); $result = $start . $p1; $result .= $startUrl . $newUrl . $endUrl; $result .= $p3 . $ending; $result = stripslashes($result); return $result; }
- In /components/lib/jake.class.php:160, add this new method to be used in place of getUrl():
** * Gets the SEF URL to execute the specified CakePHP action with Jake * * @param string $action CakePHP URL. (leave empty for default cake action) * * @return string A valid Jake URL * * @access public * @since 1.1 */ function getSefUrl($action = '', $sefCakeApplicationBase = '') { return $this->joomlaUrl . $sefCakeApplicationBase . $action; }
- In /components/com_jake/jake_front_component_class.php:89, add these lines:
// Set the SEF URL to match the rewrite rule in /.htaccess $cakeDispatcher->setSefCakeApplicationBase('/app');
- And finally, in your app_controller.php, you can “Jakeify” an ordinary CakePHP URL to the new SEF base, with the simple function:
function jakeify($url) { if (defined('JAKE')) { // set this to the same SEF base defined in /.htaccess $url = $this->jake->getSefUrl($url, '/app'); } return $url; }
Once you do this, your CakePHP URIs, running through Joomla, become the much friendlier /app/controllername/actionname instead of /components/jake/?jrun=controllername/actionname. You can still access the CakePHP URI’s directly via /webapp/controllername/actionname, just as before.
1 comment