ZF2 convert empty posted fields to Null - zend-framework2

I'm using fieldsets in order to fill forms in ZF2. If an empty field is postedm, the field is also empty in the db. How do I force a Null in the db for empty fields?

In ZF2 I think you need to use Zend\Filter\Null or Zend\Filter\ToNull depending on which version of ZF2 you are using, Zend\Filter\Null became deprecated in ZF2.4.
In your fieldset, assuming you are using the Zend\InputFilter\InputFilterProviderInterface use:
public function getInputFilterSpecification()
{
return array(
'your_field' => array(
'filters' => array(
array('name' => 'ToNull'),
),
),
);
}

Related

Symfony 4 + Select 2 - add more options to entityType

I'm working on app based on Symfony 4 with Select2 library.
In my src/Form/PostType.php file I declared field tag, where user should be able to set one of predeclared Tag or add new one (by type tag name and press enter).
$builder
->add('tags', EntityType::class, [
'class' => Tag::class,
'choice_label' => 'name',
'mapped' => false,
'expanded' => false,
'multiple' => true,
'required' => false,
]);
From the frontend side I'm using select2 library to handle with displaying tags field.
In below example fist tag was chosen from the existed entity in database, the second one should be saved in this second.
Any idea what should I changed into filed declaration to make this field valid also for new tags?
Controller is ready, only issue is to pass form validation :)
EDIT:
Relations in ORM looks like this:
class Company {
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Tag", mappedBy="companies")
*/
private $tags;
}
class Tag
{
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Company", inversedBy="tags")
*/
private $companies;
}
and there is no other validation than in code above
You have set the field to be mapped = false. If a field is unmapped you have to handle form validation manually. Can you share your Entities code , any validation code if it's written?

where do addElement method defined zend 2?

$form = new Zend_Form();
$form->addElement('text', 'fname', array('belongsTo' => 'user'));
I need to know where is addElement method defined? I have searched \vendor\ZF2\library\Zend([\Form]) directory but could not find this method!. If there is no such method then please help me to understand how this above two line work and what are other array conf & parameter of this method.
Edit: thanks Crisp. Actually I am trying to make an input array in zf2 like
<input name="val[one]" type="text" />
<input name="val[two]" type="text" />
<input name="val[three]" type="text" />
Or at least... like this
<input name="val[0]" type="text" />
<input name="val[1]" type="text" />
<input name="val[2]" type="text" />
I have found a example with above code and its not working as it is zf1.
In ZF2, programmatic form creation has changed from ZF1. There is no more addElement function, instead you add an element using $form->add($element);
The basic steps to create a form in ZF2 are:
Create a form element
Create a form
Add element to the form
Create a form element:
use Zend\Form\Element;
use Zend\Form\Form;
$name = new Element('name');
$name->setLabel('Your name');
$name->setAttributes(array(
'type' => 'text'
));
$send = new Element('send');
$send->setValue('Submit');
$send->setAttributes(array(
'type' => 'submit'
));
Create a form:
$form = new Form('contact');
Add element to the form:
$form->add($name);
$form->add($send);
However in ZF2, another way would be to use a Factory to generate the form from an array configuration:
use Zend\Form\Factory;
$factory = new Factory();
$form = $factory->createForm(array(
'hydrator' => 'Zend\Stdlib\Hydrator\ArraySerializable',
'elements' => array(
array(
'spec' => array(
'name' => 'name',
'options' => array(
'label' => 'Your name',
),
'type' => 'Text',
)
),
array(
'spec' => array(
'name' => 'send',
'type' => 'Submit',
'attributes' => array(
'value' => 'Submit',
),
),
),
),
));
The form is then referenced from the view and is rendered using form view helpers.
References:
http://framework.zend.com/manual/2.3/en/modules/zend.form.quick-start.html
https://zf2.readthedocs.org/en/develop/modules/zend.form.advanced-use-of-forms.html
http://akrabat.com/category/zend-framework-2/

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

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