CakePHP adding language parameter to URLs - cakephp

I implemented the solution at this article.
"beforeFilter" and "_setLanguage" works fine. If URL has language parameter, I can successfully set cookies/session variables. And use it between controllers.
That solution also includes adding url() function to AppHelper.
class AppHelper extends Helper {
function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language'])) {
$url['language'] = $this->params['language'];
}
return parent::url($url, $full);
}
}
But I have many URLs in my View files that are written without using HtmlHelper. Like this:
// myfile.ctp
<a href="/mypage/">click me plase<a>
So it seems like AppHelper::url solution doesn't fix my issue. What would be better alternative to add language prefix to URLs?
I thought defining a global variable like this:
// AppController::_beforeFilter()
if ($this->request->params['language'] != "")
{
Configure::write('URLprefix', '/'.$this->request->params['language']);
} else {
Configure::write('URLprefix', '');
}
Then change view file like this:
// myfile.ctp
<a href="<?php echo URLprefix; ?>/mypage/">click me plase<a>
But it doesn't seem a good way. Is there a better way to add prefix to URLs. Or should I add to all links by hand ?
Related:
Adding a prefix to every URL in CakePHP
CakePHP 2.x i18n route
CakePHP 2.1 URL Language Parameter

You should generate all links and URLs within your application using HtmlHelper::link() and HtmlHelper::url()
This will make sure that your Routes are taken into account when generating URLs (Reverse routing)
For example, if you decide to define a 'friendly' URL Route /logout for /users/logout, then this:
echo $this->Html->link('Log out', array(
'controller' => 'users',
'action' => 'logout'
));
Will create this link:
<a href='/logout'>Log out</a>
If you later decide to modify the 'friendly' URL Route (/sign-out) for the logout URL, then all links in your application will automatically be adjusted.
The same call to the HtmlHelper, will now output:
<a href='/sign-out'>Log out</a>
Read more on this subject here:
Reverse Routing

Related

Dynamic base url with drupal and angularjs

I have create 2 angular app into drupal 7 like "example.com", "example.com/app1", "example.com/app2".
example.com is my main site. So, when I set html5 pushstate enable for removing hash in angular apps, I got nobase error from angularjs. Coz,
<base href="">
require for enable angularjs html5 pushstate.
My question is, since i have multiple angualr app in this drupal site, how can i dynamically add conditional base url for "/app1" and "app2" ?
anybody can help me? Waiting for response. Thanx.
You can add base element to your site in this way:
YOUR_THEME_NAME_preprocess_html(&$variables, $hook) {
$url = 'default';// default url
if($application1) {// your condition for app1
$url = 'app1';
} elseif($application2) {// your condition for app2
$url = 'app2';
}
$data = array(
'#tag' => 'base',
'#attributes' => array(
'href' => $url,
),
);
drupal_add_html_head($data, 'base_href');
}
Put it into your template.php

cakephp 3.0 $this->output function does not exist error

I am using the image helper of 2.x in my cakephp 3.x application but i am facing a problem with this that in my cakephp 2.x the function return the value as below code
return $this->output(sprintf($this->Html->_tags['image'], $this->webroot($relfile), $this->Html->_parseAttributes($htmlAttributes, null, '', ' ')), $return);
but in cakephp 3.x output and _parseAttributes function is removed so i dont know how to use these two function in cakephp 3.x
_parseAttributes function contain the image related data like 'class', 'alt' other things
i have searched a lot on net for output function in cake 3.x but did not find any successfull solution please try to help me
Thanks
Use the Html helper
There's nothing in your example code that justifies the use of custom code for generating the tag, so you could simply use the Html helper instead
// ...
class YourCustomHelper extends Helper
{
public $helpers = [
'Html',
// ...
];
public function someMethod($relfile, array $htmlAttributes)
{
$options = $htmlAttributes + ['pathPrefix' => false];
return $this->Html->image($url, $options);
}
// ...
}
Note the use of the pathPrefix option, since it looks like you want to point to a custom path, you should disable it, as otherwise you may end up with the default image base URL being prepended to the path.
Custom tags and attributes
If you'd really need a custom solution that isn't already covered by other helpers, then the replacement for output() and _parseAttributes() are return and string templates.
For the sake of supplying an example, here's a trimmed down one of what HtmlHelper::image() does:
use Cake\Core\Configure;
use Cake\View\StringTemplateTrait;
// ...
class YourCustomHelper extends Helper
{
use StringTemplateTrait;
protected $_defaultConfig = [
'templates' => [
'someTemplate' => '<img src="{{url}}"{{attrs}}/>',
],
// ...
];
public $helpers = [
'Url',
// ...
];
public function someMethod($relfile, array $htmlAttributes = [])
{
$url = $this->Url->assetUrl($relfile);
$templater = $this->templater();
return $templater->format('someTemplate', [
'url' => $url,
'attrs' => $templater->formatAttributes($htmlAttributes),
]);
}
// ...
}
This should be pretty much self explantory, you include the StringTemplateTrait that holds the templating functionality, define a custom template, and format it using the templater.
Note the use of the Url helper, it will do all the necessary stuff like encoding the URL, timestamping it, adding the webroot path, etc...
See also
Cookbook > Views > Helpers > Configuration options
Source > \Cake\View\Helper\HtmlHelper::image()
API > \Cake\View\Helper\UrlHelper::assetUrl()
API > \Cake\View\StringTemplate::format()
API > \Cake\View\StringTemplate::formatAttributes()
Cookbook > Appendices > 3.0 Migration Guide > Helpers

Cakephp route matches everything

I have following route added to routes.php in the end.
Router::connect('/:sellername/:itemtitle',
array('controller' => 'items', 'action' => 'view_item_detail'),
array(
'pass' => array('sellername','itemtitle'),
'sellername' => '[a-zA-Z0-9_-]+',
'itemtitle' => '[a-zA-Z0-9_-]+',
)
);
So this matches the dynamic urls like http://example.com/john/title-of-an-item
Problem is this also matches every other url like http://example.com/members/signin even though there's a MembersController controller and signin action in it.
I can fix it using following route entry.
Router::connect(
'/members/:action',
array('controller' => 'members')
);
But it's very tedious to add every route like above.
Doesn't existing matching controller names are prioritized while making a match?
Do order of routes in routes.php matter?
Custom Route classes is to help you
Custom route classes allow you to extend and change how individual routes parse requests and handle reverse routing. A route class should extend CakeRoute and implement one or both of match() and/or parse(). parse() is used to parse requests and match() is used to handle reverse routing.
You can use a custom route class when making a route by using the routeClass option, and loading the file containing your route before trying to use it:
Router::connect(
'/:slug',
array('controller' => 'posts', 'action' => 'view'),
array('routeClass' => 'SlugRoute')
);
This route would create an instance of SlugRoute and allow you to implement custom parameter handling.
custome routing class let you impliment anything
But personal opinion is to user a static and meaning full text in the url that diffrenciate it from the rest.

Using prefixes instead of extensions in CakePHP

I'm trying to implement REST and parseExtension like functionality in my app, running on CakePHP 2.
Instead of having URLs like http://myapp.dev/controller/action.json I would like to use http://myapp.dev/json/controller/action.
The reason for this is that sometimes extensions look a little stupid when put onto something like http://myapp.dev/controller/index/show:10/page:2.json.
While this could be implemented in a custom route, I already have lots of custom routes, and do not want to have to create duplicates of each with a :type field in there for maintenance reasons.
What would be ideal is setting it up such that any url with /json /xml /html etc. in first place would be treated as if json, xml, html etc. were the extension.
While Prefix Routing looks ideal for this, it requires new methods (e.g. json_index, html_index etc. and I would have to specify each format as a separate prefix).
Is there any good way of doing this? I just want parseExtensions to instead be like a parsePrefixes method instead.
You should try the following :
Router::connect('/:ext/', array(':ext'), array('pass' => 'ext'));
Router::connect('/:ext/:controller/*', array(':ext'), array('pass' => 'ext'));
Router::connect('/:ext/:controller/:action/*', array(':ext'), array('pass' => 'ext'));
Then, the router will pass the :ext argument, in the "ext" value of the route parameters. Add it for all your rules !
If you want to use traditionnel routes to work, you need to use a custom CakeRoute. Create a file "/libs/routes/RestRoute.php" in your app folder, add the following into it :
class RestRoutes extends CakeRoute {
function parse($url) {
$params = parent::parse($url);
if (empty($params)) {
return false;
}
if(!in_array($params['ext'], Router::extensions())) {
return false;
}
return $params;
}
}
And in your /core/routes.php :
App::import('Lib', 'routes/RestRoute');
Router::connect('/:ext/', array(':ext'), array('pass' => 'ext', 'routeClass' => 'RestRoute'));
Router::connect('/:ext/:controller/*', array(':ext'), array('pass' => 'ext', 'routeClass' => 'RestRoute'));
Router::connect('/:ext/:controller/:action/*', array(':ext'), array('pass' => 'ext', 'routeClass' => 'RestRoute'));
So, when your custom route won't be able to pass an url, it would try the default url, without the ext parameters. Otherwise, the order of the parameters are not quiet allright.
Maybe not the best or cleaner solution, but it's a good start.

CakePHP routing with colon separator

I need to create routes that include a colon to produce URLs like http://app.com/prjct:a9b5c. Obviously it's currently simple to use a slash instead with the default routing.
$SLUG = array('slug' => '[-_A-Za-z0-9]+');
Router::connect('/prjct/:slug', array('controller' => 'projects', 'action' => 'show'), $SLUG);
But routes specifications use the colon character as a special indicator, which interferes with my naive attempt to replace the second slash above with another colon.
How do I use colons in this case for a route?
You can use named parameter as explained in CakePHP Cookbook. Write code below in your app/config/routes.php:
// Parse only the 'prjct' parameter if the current action is 'show' and the controller is 'projects'.
Router::connectNamed(array('prjct' => array('action' => 'show', 'controller' => 'projects')));
// Then set default route to controller 'projects' and action 'show
Router::connect('/', array('controller' => 'projects', 'action' => 'show'));
In your projects_controller.php :
function show(prjct = null) {
// Check if prjct match the pattern
$pattern = '[-_A-Za-z0-9]+';
if(!preg_match($pattern, prjct)){
// Redirect somewhere else
}
// Rest of your code here
}
I think this is indeed out of scope for simple routes. I see two options:
Use a custom route parsing class, as described here. There isn't a whole lot of documentation on the topic, but you can extend the existing class and play around with it to get a hang of what it's doing. Then customize it to your needs.
class MyRoute extends CakeRoute {
public function parse($url) {
debug($url); // input
$route = parent::parse($url);
debug($route); // output
return $route;
}
}
Route these URLs with a catch-all route to a controller, where the parameter will be available as a named parameter in $this->params['named']. Do what you need to do there.

Resources