How to change the separation character of Zend Url? - zend-framework

I use Zend URL view helper for building my urls. Everythings works exactly as I'd like to, except one thing: The character used for replacing spaces in the url is a plus (+). I'd like it to be a 'min' (-). How can I change this?
Example:
Now: /nl/nieuws/bericht/3/title/nieuwe**+affiches
Wish: /nl/nieuws/bericht/3/title/nieuwe-**affiches
Thanks in advcance!

This isn't in the documentation anywhere, but it appears that the Zend URL view helper can take a parameter in it's $urlOptions array called chainNameSeparator. No guarantee that's what you're looking for, but trying playing with that and see if it changes anything.

This is likely happening because, by default, Zend_View_Helper_Url will urlencode() what you send it, which would translate spaces into +. My suggestion to you would be to create a new view helper for the type of URL in your code that needs the special inflection.
Something like:
class Default_View_Helper_SpecialUrl extends Zend_View_Helper_Abstract
{
public function specialUrl(array $opts = array(), $name = null, $reset = false, $encode = true)
{
if (!empty($opts['whatever'])) {
$opts['whatever'] = str_replace(' ', '-', $opts['whatever']);
}
$router = Zend_Controller_Front::getInstance()->getRouter();
return $router->assemble($opts, $name, $reset, $encode);
}
}
This way the spaces are changed for whatever necessary route parameters before URL encoding happens by the router.

Related

Is there a Fluid viewhelper to truncate an URL? If not, how do I make one?

In TYPO3's Fluid or in Fedext/vhs, is there a viewhelper that can convert
http://www.stackoverflow.com/questions/ask
into
www.stackoverflow.com
?
PS: that's the goal:
<f:format.raw><f:link.external uri="{item.link}">{item.just-display-the-domain}</f:link.external></f:format.raw>
EDIT (adapting the question to the answer I got): If I have to build a custom view helper, how do I proceed?
I really doubt if there would be any sensible reason for adding this kind of VH into the core, de facto, writing custom VH is like a piece of cake (when you finally realize it is) so simple formatters can be created by devs in their custom tool exts just in minutes.
Ie. in TYPO3 4.x assuming that you have a custom extension with key urs all you need to do is create one proper class, containing render($params) method and extending Tx_Fluid_Core_ViewHelper_AbstractViewHelper class:
/typo3conf/ext/urs/Classes/ViewHelpers/GetDomainViewHelper.php:
<?php
class Tx_Urs_ViewHelpers_GetDomainViewHelper extends Tx_Fluid_Core_ViewHelper_AbstractViewHelper {
/**
* #param $link string Each `allowed` param need to have its line in PHPDoc
* #return string
*/
public function render($link) {
$link = str_replace('http://', '', $link);
$link = str_replace('https://', '', $link);
$segments = explode('/', $link);
return trim($segments[0]);
}
}
?>
Next in your templae declare its namespace and... that's all, you can use it:
{namespace urs=Tx_Urs_ViewHelpers}
<urs:getDomain link="http://stackoverflow.com/questions/20499453" />
Take special attention about letter case in things like Tx_Urs_ViewHelpers... etc.
More details in http://docs.typo3.org/typo3cms/ExtbaseFluidBook/8-Fluid/8-developing-a-custom-viewhelper.html
In TYPO3 ver. 6.x
Things works preaty similar the main change of course is new namespacing
/typo3conf/ext/urs/Classes/ViewHelpers/GetDomainViewHelper.php:
<?php
namespace TYPO3\Urs\ViewHelpers;
class GetDomainViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
/**
* #param $link string Each `allowed` param need to have its line in PHPDoc
* #return string
*/
public function render($link) {
$link = str_replace('http://', '', $link);
$link = str_replace('https://', '', $link);
$segments = explode('/', $link);
return trim($segments[0]);
}
}
In templates:
{namespace urs=TYPO3\Urs\ViewHelpers}
<urs:getDomain link="http://stackoverflow.com/questions/20499453" />
Of course in both cases instead of using hardcoded links you will use:
<urs:getDomain link="{item.link}" />
It's a little bit cumbersome and not very efficient, but it should work and would of course prevent the need for a custom ViewHelper class:
With protocol:
{url -> v:iterator.explode(glue: '/') -> v:iterator.slice(length: 3) -> v:iterator.implode(glue: '/')}
Without protocol:
{url -> v:iterator.explode(glue: '/') -> v:iterator.slice(start: 2, length: 1) -> v:iterator.first()}
Where {url} can come from anywhere, as long as it contains a full http:// or other protocol prefix. The line above of course explodes the URL into parts separated by / then slices off the first three segments and re-joins those using /. Or it simply picks offset 2 (which would be the full domain without protocol) and returns that single element. The result should be an url to the domain of the link, with or without protocol, without trailing slash (which you may or may not want to add yourself after cutting the URL).
Cheers,
Claus
All ViewHelper are located at typo3/sysext/fluid/Classess/ViewHelper. There are also examples in the header of each file. All ViewHelper of Fedext can be reviewed on the website.

How do I read the url parameters from a ZendFramework Controller

I have a ZendFramework controller whose view forms a framework similar to this:
http://foo.com/#/controler/someaction/state/city/address/
The action looks like this:
public function someactionAction()
{
$this->view->someaction = App_Model_WebService_Menu::getInstance()->getRows(array(
'address' => '1600 Pennsylvania Ave',
'returnRecordsLimit' => 1,
));
}
Is there a way where I can access state, city and address as parameters?
From Zend_Controller_Request documentation
$state = $this->getRequest()->getParam('state');
$city = $this->getRequest()->getParam('city');
$address = $this->getRequest()->getParam('address');
Ignoring the URL fragment part which I assume is reliant on some JavaScript configuration, that looks like it would be part of a custom route, ie
:controller/:action/:state/:city/:address
You will have to look into the route definition to discover the actual parameter names, after which you simply use (from your controller)
$state = $this->_getParam('state-param-name');

Zend_Controller_Router_Route_Regex allow '?' in pattern

Imagine situation, when the url should looks like
/catalog/sectionIdent?page=1
where page param is optional.
Of course, custom route should be defined. Consider the following code:
$route = new Zend_Controller_Router_Route_Regex(
'catalog/([-a-z]+)(?:\?page=([0-9]*))?',
array('controller'=>'catalog','action'=>'list','page'=>''),
array(1=>'section',2=>'page'),
'catalog/%s?page=%d'
);
$router->addRoute('catalog-section-page',$route);
But this route won't be triggered with '?' symbol in url.
Without '?' (for example, by adding escaped '!' symbol to pattern) everything works as it should.
Is there any way to achieve '?' presence in custom defined regex route? Maybe I'm doing something wrong in pattern?
P.S.: Don't offer to use '/' instead of '?', question is exactly about pattern restrictions in Zend_Controller_Router_Route_Regex implementation.
The ZF routing classes operate on the REQUEST_URI with the query string stripped off, so you may have a hard time get this working in the way you are expecting. However, I believe GET parameters are put into the request object by default, so you shouldn't need to cater for them in your routes. I'd suggest changing your route to remove the query string parts:
$route = new Zend_Controller_Router_Route_Regex(
'catalog/([-a-z]+)',
array('controller'=>'catalog','action'=>'list'),
array(1=>'section'),
'catalog/%s'
);
$router->addRoute('catalog-section-page',$route);
You should still be able to access the params in your controller as if they had been populated by the routes:
public function listAction()
{
echo $this->_getParam('page');
}
and you can use the same method to set a default:
public function listAction()
{
$page = $this->_getParam('page', 1); // defaults to 1 if no page in URL
}
You just may need to sanitise them there (make sure they are numeric).
Edit:
Example of URL helper with this route:
echo $this->url(array('section' => 'foo', 'page' => 2), 'catalog-section-page')

Zend: Quick and succinct way of inserting custom HTML into a Zend_Form?

Is there some method that accepts inserting custom html without having to actually add form controls, even if they're hidden and making my html a decorator?
I'm looking for something like:
$this->addCustomElement( array(
'div',
'body' => '<p>inner text</p>'
) );
I need something short and quick, I don't want to create a new class or something overkill.
Well it's really as simple as this:
$note = new Zend_Form_Element('note');
$note->helper = 'formNote';
$note->setValue('<b>hi</b>');
$form->addElement($note);
But the problem is that when you submit the form, the form calls $note->isValid(), which overrides the value, so if there are errors with the form, the next time you display it, the custom HTML won't be shown. There are two easy ways to fix this, the first is to override isValid() in your Form class like this:
public function isValid($data)
{
$note = $this->note->getValue();
$valid = parent::isValid($data);
$this->note->setValue($note);
return $valid;
}
But personally I find this kinda hackish way, and prefer the second option. That is to write a very simple class (this should really be part of Zend itself, I have no idea why it isn't, since it includes a formNote view helper, but no element that uses it):
class My_Form_Element_Note extends Zend_Form_Element_Xhtml
{
public $helper = 'formNote';
public function isValid($value, $context = null) { return true; }
}
Then you just have to do:
$note = new My_Form_Element_Note('note');
$note->setValue('<b>hi</b>');
$form->addElement($note);
And everything will just work.
Other options include doing some black magic with decorators, but I really recommend you to not go down that path.
Also note the AnyMarkup Decorator.

CodeIgniter: URIs and Forms

I'm implementing a search box using CodeIgniter, but I'm not sure about how I should pass the search parameters through. I have three parameters: the search string; product category; and the sort order. They're all optional. Currently, I'm sending the parameters through $_POST to a temporary method, which forwards the parameters to the regular URI form. This works fine. I'm using a weird URI format though:
http://site.com/products/search=computer,sort=price,cat=laptop
Does anyone have a better/cleaner format of passing stuff through?
I was thinking of passing it into the products method as arguments, but since the parameters are optional things would get messy. Should I suck it up, and just turn $_GET methods on? Thanks in advance!
Query Strings
You can enable query strings in CodeIgniter to allow a more standard search function.
Config.php
$config['enable_query_strings'] = FALSE;
Once enabled, you can accept the following in your app:
http://site.com/products/search?term=computer&sort=price&cat=laptop
The benefit here is that the user will find it easy to edit the URL to make a quick change to their search, and your search uses common search functionality.
The down side of this approach is that you are going against one of the design decisions of the CodeIgniter development team. However, my personal opinion is that this is OK provided that query strings are not used for the bulk of your content, only for special cases such as search queries.
A much better approach, and the method the CI developers intended, is to add all your search parameters to the URI instead of a query string like so:
http://site.com/products/search/term/computer/sort/price/cat/laptop
You would then parse all the URI segments from the 3rd segment ("term") forward into an array of key => value pairs with the uri_to_assoc($segment) function from the URI Class.
Class Products extends Controller {
...
// From your code I assume you are calling a search method.
function search()
{
// Get search parameters from URI.
// URI Class is initialized by the system automatically.
$data->search_params = $this->uri->uri_to_assoc(3);
...
}
...
}
This would give you easy access to all the search parameters and they could be in any order in the URI, just like a traditional query string.
$data->search_params would now contain an array of your URI segments:
Array
(
[term] => computer
[sort] => price
[cat] => laptop
)
Read more about the URI Class here: http://codeigniter.com/user_guide/libraries/uri.html
If you're using a fixed number of parameters, you can assign a default value to them and send it instead of not sending the parameter at all. For instance
http://site.com/products/search/all/somevalue/all
Next, in the controller you can ignore the parameter if (parameter == 'all'.)
Class Products extends Controller {
...
// From your code I assume that this your structure.
function index ($search = 'all', $sort = 'price', $cat = 'all')
{
if ('all' == $search)
{
// don't use this parameter
}
// or
if ('all' != $cat)
{
// use this parameter
}
...
}
...
}