ZF2 Generate absolute URI from CLI - url

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 <?=)

Related

Octobercms disble fields in relation

I want to disable form fields in the update context, see the image:
I tried this, but it did not work
public function filterFields($fields, $context = null)
{
if($context == 'update') {
$fields->books->disabled = true;
$fields->user->disabled = true;
}
}
Seems you are trying to make relation manager field disable(read only)
But I am sure they are not following same pattern as normal widgets do.
they can not be disabled directly like that as I found another easy way.
you may have used partial for rendering this relational field ( book | user ) and your partial _books.htm is looking like this.
<?= $this->relationRender('comments', ['readOnly' => false]) ?>
You need to change it with this one
<?php if($this->widget->form->context == 'update'): ?>
<?= $this->relationRender('comments', ['readOnly' => true]) ?>
<?php else: ?>
<?= $this->relationRender('comments', ['readOnly' => false]) ?>
<?php endif; ?>
The magic config value is this readOnly property it will make list read-only or active working.
try this it will work , if not please comment.

zend framework 2 setTemplate not work on host : error Unable to render template ... resolver could not resolve to a file

it work ok on localhost ,but on host it error :
Zend\View\Renderer\PhpRenderer::render: Unable to render template "Application\Index\test"; resolver could not resolve to a file
my controller:
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
public function indexAction()
{
$view=new ViewModel();
$view->setTemplate('Application\Index\test');
$view->setVariable('view_chat', 'undercut');
return $view;
}
public function testAction(){
}
}
view folder:
--/application
----/index
------/index.phtml
------/test.phtml
Set the view/partial up in module.config.php:
yoursite\module\Application\config\module.config.php
In that file you set up aliases for your partials that you want to use in your site.
You do so like this:
<?php
// .... Other stuff above
'view_manager' => array(
'template_map' => array(
'test_view' => __DIR__ . '/../view/application/Index/test.phtml
)
)
Then, in your controller, you will be able to set your view to the alias "test_view" like so
$view->setTemplate('test_view');
Look for an existing template map because that is where your layout is referenced.

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 - Retain query from form using url helper in pagination

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)

Resources