ZF2 - Retain query from form using url helper in pagination - zend-framework2

I'm new to ZF2 and I'm willing to share how I do to retain parameter from form using url helper especially during pagination. I modify the answer from How can you add query parameters in the ZF2 url view helper
This is what I do:
AlbumController.php
// get all the query from url
$input = $form->getData();
$paginator = $this->getAlbumTable()->fetchAll();
$paginator->setCurrentPageNumber((int)$this->params()->fromQuery('page', 1));
$paginator->setItemCountPerPage(30);
// unset the 'page' query if necessary
unset($input['page']);
return array(
'form' => $form,
'paginator' => $paginator,
'routeParams' => array_filter($input) // filter empty value
);
index.phtml
echo $this->paginationControl(
$this->paginator,
'sliding',
array('partial/paginator.phtml', 'Album'),
array(
'route' => 'album',
'routeParams' => $routeParams
)
);
paginator.phtml
<a href="<?php echo $this->url(
$this->route, // your route name
array(), // any url options, e.g action
array('query' => $this->routeParams) // your query params
);
echo (empty($this->routeParams))? '?' : '&'; ?>
page=<?php echo $this->next; ?>">Next Page</a>
Please provide any better solution and correct me if I'm wrong.
Thank you

I don't have a much better solution than yours - I don't see a proper way to retain existing query params while adding some new ones. But the following is neater than manually appending & and = characters:
paginator.phtml
<a href="<?php echo $this->url(
$this->route, // your route name
array(), // any url options, e.g action
// Merge the array with your new value(s)
array('query' => array('page' => $this->next) + $this->routeParams)
); ?>">Next Page</a>
This will also ensure that if you already have a page param, it will be overwritten by the new one.
(Technically you could also use $_GET or $_POST directly and avoid passing it from the controller at all, but that doesn't seem very neat)

Related

Prevent ZF2 formHelper escaping attributes

Hi I have a form with a number field. I use regex to validate the field. For that reason I added the pattern attribute the element. However when I use formText it html escapes the regex pattern.
//inside the form _construct
$this->add(array(
'name' => 'number',
'type' => 'text',
'options' => array(
'label' => 'Number',
),
'attributes' => array(
'pattern' => '/^(\+)?((\d)+(-|\s)?)+$/',
'maxLength' => '20',
'id' => 'number',
),
));
And in the form
<?php echo $this->formText($form->get('number')); ?>
The result is then
<input type="text" name="number" pattern="/^(\+)?((\d)+(-|\s)?)+$/" id="number" value="" maxlength="20">
How can I add the number field to my form without escaping the regex pattern?
Form view helpers are supposed to work that way, providing some baseline security features and automating stuff. So if you don't won't that don't use them:
<input type="<?php echo $form->get('number')->getType(); ?>" pattern="type="<?php echo $form->get('number')->getAttribute('pattern'); ?>" value="<?php echo $form->get('number')->geValue(); ?>">
Not sure what you need displayed, but it should give you a general idea of "my" approach. You can also manually escape stuff like value:
$this->escape($form->get('number')->geValue())
If you find this tedious, you can always write a helper that does this. You can also make PR with an option to turn of the escaping for attributes, but having them on by default is a sensible.

Render mail templete zend framework 2

i'm trying to sent an email with a template in Zend framework 2 applicatio.
This is code in my class called "EmailService...".
$view = new PhpRenderer();
$resolver = new TemplateMapResolver();
$resolver->setMap(array(
'mailTemplate' => __DIR__ . '/../../../mail/' . $template['name'] . '.phtml'
));
$view->setResolver($resolver);
$viewModel = new ViewModel();
$viewModel->setTemplate('mailTemplate')
->setVariables(
(!empty($template['variables']) && is_array($template['variables'])) ? $template['variables'] : array()
);
$this->_message->addFrom($this->_emailConfig['sender']['address'], $this->_emailConfig['sender']['name'])
->addTo($user['email'], $user['login'])
->setSubject($subject)
->setBody($view->render($viewModel))
->setEncoding('UTF-8');
Everything work fine but in this templete file I have to create a link to an action (I have specify route for this). But here is a problem. Becouse when I'm trying to use
<?php echo $this->url('auth') ; ?>
I've got "No RouteStackInterface instance provided" error.
If I use:
<?php echo $this->serverUrl(true); ?>
everything work fine... Any clue?
You shouldn't need to create a new instance of the PhpRenderer; you can just reuse the already created one.
$renderer = $this->serviceManager->get('viewrenderer');
$variables = is_array($template['variables']) ? $template['variables'] : array();
$viewModel = new ViewModel($variables);
$viewModel->setTemplate('mailTemplate');
$html = $renderer->render($viewModel);
In order to follow good DI practice, inject the PhpRenderer into the email service's __construct (rather than the service manager).
Also, the template path can be added in the normal module.config.php
return array(
'view_manager' => array(
'template_map' => array(
'mailTemplate' => __DIR__ . '/../view/foo/bar.phtml',
),
),
);
There are a lot of modules which make things easy when sending html mails. You can search them here.
My personal favourite is MtMail. You can easily use templates and layouts. You can easily set default headers(From, Reply-To etc.). You can use this Template Manager feature to better organize e-mail templates in object-oriented manner.
MtMail Usage:
$mailService = $this->getServiceLocator()->get('MtMail\Service\Mail');
$headers = array(
'to' => 'johndoe#domain.com',
'from' => 'contact#mywebsite.com',
);
$variables = array(
'userName' => 'John Doe',
);
$message = $mailService->compose($headers, 'application/mail/welcome.phtml', $variables);
$mailService->send($message);

ZF2 Form\Element\MultiCheckbox: how to get each item on a new line?

I've been Googling this to no avail. I have a multi-checkbox form element in one of my forms. Here's the code I used to create it:
$this->add(array (
'name' => 'thingyId',
'type' => 'MultiCheckbox',
'options' => array (
'value_options' => $thingyArray,
)
));
In my view script, I have this:
<?= $this->formRow($form->get('thingyId')); ?>
The form element shows up fine, but all of the checkboxes are on a single line. How do I get it so that each checkbox is on a new line?
If you view this link, you can see that the fourth argument is partial. So, you can use many ways to accomplish the task.
Method 1:
echo $this->formRow($element, null, null, 'template-file');
Now, create a template file named as template-file.phtml to render the element however you like.
//template-file.phtml
<span><?php echo $label; ?></span><br/>
<?php foreach ($element->getValueOptions() as $key => $value): ?>
<input type="checkbox" name="<?php echo $element->getName() ?>[]" value="<?php echo $value; ?>">
<span><?php echo $key; ?></span><br/>
<?php endforeach; ?>
Method 2
Create your own view helper by extending the default helper.
namespace Application\View\Helper;
class MyFormRow extends \Zend\Form\View\Helper\FormRow
{
/**
* #var string
*/
protected $partial = 'template-file';
}
Now, inform our application about our new helper in your module,
namespace Application;
class Module
{
public function getViewHelperConfig()
{
return array(
'invokables' => array(
'myFormRow' => 'Application\View\Helper\MyFormRow'
)
);
}
}
Lastly use the helper:
echo $this->myFormRow($element);
I came across this question when I was having this issue myself. The code that was being used was the following:
<?php
$oMultiCheckboxField = $oForm->get('multicheckboxelement');
echo $this->formMultiCheckbox($oMultiCheckboxField);
?>
The only additional parameter you could pass to the formMultiCheckbox view helper was whether to append or prepend the label.
How I eventually chose to solve this is with the following code:
<?php
$oMultiCheckboxField = $oForm->get('multicheckboxelement');
$oMultiCheckboxViewHelper = new \Zend\Form\View\Helper\FormMultiCheckbox();
$oMultiCheckboxViewHelper->setSeparator('<hr>');
echo $oMultiCheckboxViewHelper->render($oMultiCheckboxField);
?>
From what I recall, ZF1 had the option to set the separator (I clearly remember this at least for radio buttons). Why there isn't a clearer way to do this in ZF2 is a bit puzzling. If there are better ways to do this, I would certainly like to know about it.

ZF2 Generate absolute URI from CLI

I have a cron job which runs a ZF2 CLI route to send out some email notifications. The emails use an HTML view which I render via
$emailBody = $this->getServiceLocator()->get('viewrenderer')
->render('some/partial/name.phtml',$params);
Within this partial I use the view helper
<?php echo $this->url('some-route', array(), array('force_canonical' => true)); ?>
to generate an absolute URL to a page on my site. When I run this through a CLI however, I see an exception:
Zend\Mvc\Router\Exception\RuntimeException
Request URI has not been set
Do I need to inject a dummy HttpRequest object into the view rendering service or should I approach this a different way?
Because this is running through the CLI there's no real way for the script to know the correct domain to generate an absolute URI.
I ended up creating a view helper at module/Application/src/Application/View/Helper/CliDomain.php
<?php
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
class CliDomain extends AbstractHelper {
protected $_config_protocol;
protected $_config_domain;
public function __construct(array $cliConfig) {
$this->_config_protocol = $cliConfig['scheme'];
$this->_config_domain = $cliConfig['domain'];
}
public function __invoke() {
return $this->_config_protocol.'://'.$this->_config_domain;
}
}
and configured the factory in module/Application/config/module.config.php
return array(
...
'view_helpers' => array(
...
'cliDomain' => function ($sm) {
$config = $sm->getServiceLocator()->get('config');
if (!isset($config['cli_url'])) {
throw new \InvalidArgumentException('Please add a "cli_url" configuration to your project in order for cron tasks to generate emails with absolute URIs');
}
return new \Application\View\Helper\CliDomain($config['cli_url']);
},
and in the project's config/autoload/global.php file I added a new key to the returned array
<?php
return array(
...
'cli_config' => array(
'scheme' => 'http',
'domain' => 'prod.example.com',
),
);
for the staging server I added a matching config entry in config/autoload/local.php
<?php
return array(
...
'cli_config' => array(
'scheme' => 'http',
'domain' => 'staging.example.com',
),
);
So in the question's view script I just prepended a call to the helper in the URL and don't bother forcing canonical.
a link!
One way would be to pass in an Uri\Http object to the url() view helper:
<?php
// at the top of your view script, or passed assigned to the view model
$uri = new \Zend\Uri\Http('http://www.example.com/subdir');
?>
<!-- within the view script -->
<?= $this->url('some-route', array(),
array('force_canonical' => true, 'uri' => $uri)); ?>
or just code it in the view script:
http://example.com/subdir<?= $this->url('some-route'); ?>
(I'm assuming you're using PHP5.4 or higher, so you can use <?=)

How to adapt this wordpress loop query code to include pagination?

I have sourced the below code to query my posts in Wordpress and all works as intended.
I'd like to add pagination to this now. I don't want to alter the code too much now that I know it works, can anyone advise on the best way to adapt this to include the pagination?
I would like it to show a maximum of 18 posts per page and have next and prev links to other pages if they exist. This code is being used in custom category templates, but I have also setup a static page setup under the reading settings and the display of main posts uses home.php, I'd like to use the same or similar loop code to also paginate that. Any help is appreciated. Here is the code:
<div id="Items">
<ul>
<?php
// Grid sorted alphabetically
if (is_category('categoryName'))
{
$args = array( 'posts_per_page' => -1, 'orderby'=> 'title', 'order' => 'ASC', 'category' => 41 );
$categoryNameposts = get_posts( $args );
}
foreach( $categoryNameposts as $post ) : setup_postdata($post);
?>
<li><?php get_template_part( 'content', get_post_format() ); ?></li>
<?php endforeach; ?>
</ul>
</div><!-- #ItemsEnd -->
You should let wordpress know how much post you want to show per page in the query_posts. Replace your $args with these two lines:
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array( 'posts_per_page' => 18, 'paged' => $paged, 'orderby'=> 'title', 'order' => 'ASC', 'category' => 41 );
Now to show Next-Previous link:
<div class="paginationClass">
<?php next_posts_link(); ?>
<?php previous_posts_link(); ?>
</div>
Also in is_category function, use categorySlug, instead of categoryName.

Resources