How to call DB2 stored procedure in Zend Framework 2 placed in IBM i - zend-framework2

I have configured Zend Framework2 in my local machine (ubuntu 14.04 LTS) with IMB_db2 driver as below.
global.php
$conn_string = "DATABASE='';HOSTNAME='xxx';PORT='xxx';PROTOCOL=TCPIP;UID='xxx';PWD='xxx'";
return array(
'db' => array(
'driver' => 'ibmdb2',
'database' => $conn_string,
'username' => '',
'password' => '',
'hostname' => '',
'port' => '',
'driver_options' => array(
'DB2_ATTR_CASE' => DB2_CASE_LOWER
),
'platform_options' => array(
'quote_identifiers' => false
)
),
'service_manager' => array(
'factories' => array('Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory'),
),
);
local.php
return array('db' => array('username' => 'xxx','password' => 'xxx',));
Using zend adapter I have called the stored procedure placed in a iseries box as below.
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
$stmt = db2_prepare($this->adapter, 'Call <Procedure name>("xxx","xxx","?","?")');
if (!$stmt) {
die('Preparing Statement failed.' . db2_stmt_error());
}
From the above snippet I am getting 'Preparing Statement failed.' with out any error message.
When I print $this->adapter, it is giving connection object.
Can any one help me on this, please?

Related

Zend 2: Unit tests for form class

I'm just starting using PHPUnit with Zend and need little help to figure out how these tests should work.
I want to test if form return any error message if I do not pass any POST parameters.
The problem is that one field from my form is using Doctrine's DoctrineModule\Form\Element\ObjectSelect
...
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'user',
'attributes' => array(
'id' => 'user-label',
),
'options' => array(
'object_manager' => $em,
'target_class' => 'Application\Entity\User',
'property' => 'username',
'label' => 'User:',
'display_empty_item' => true,
'empty_item_label' => '---',
'label_generator' => function($entity) {
return $entity->getUsername();
},
),
));
...
I get following error:
Fatal error: Call to a member function getIdentifierFieldNames() on null
I tried override this field with mocked object, however Zend doesn't allow objects in type, just class name (string), so this code doesn't work:
public function testIfFormIsValid()
{
$objectSelect = $this->getMockBuilder('DoctrineModule\Form\Element\ObjectSelect')
->disableOriginalConstructor()
->getMock();
$objectSelect->expects($this->any())
->method('getValueOptions')
->will($this->returnValue(array()));
$form = new \AppModuleComment\Form\Comment('form', array(
'em' => $this->em // Mocked object
));
$form->add(array(
'type' => $objectSelect,
'name' => 'user',
'attributes' => array(
'id' => 'user-label',
),
'options' => array(
'object_manager' => $this->em,
'target_class' => 'Application\Entity\User',
'property' => 'username',
'label' => 'User:',
'display_empty_item' => true,
'empty_item_label' => '---',
'label_generator' => function($entity) {
return $entity->getUsername();
},
),
));
$data = array(
'id' => null,
'user' => null
);
$form->setData($data);
$this->assertTrue($form->isValid(), 'Form is not valid');
}
What am I doing wrong? How should I test such code?
It seems you are testing functionality of Zend or Doctrine (or both) and not your own code. When you use libraries you should trust these libraries.
What happens is: Form\Form::add() uses Form\Factory::create() to create from the array an element. Form\Factory::create() uses Form\FormElementManager::get() to get an element from the given type.
Your type is an object and because Form\FormElementManager::get() can not handle objects your script will fail.
It seems you want to test that if post is empty Form::valid() calls ObjectSelect::valid() but this does not verify if the value is null. That's code from Doctrine / Zend not yours. Don't test it.
More interesting it gets when you want to mock the result of an select from within Doctrines ObjectSelect. But that's another question.

Zend Framework 2, Event Manager, SharedManager, Form Init

I have event added to onBootstrap()
$e->getApplication()->getEventManager()->getSharedManager()->attach('\Application\Form\Presentation\Edit', 'init', function($e) {
exit(print_r('<pre>') . var_dump($e));
}, 1);
How I can run this event after call form method init ?
I have solution,
In onBootstrap()
$services = $e->getApplication()->getServiceManager();
$sharedEventManager = $e->getApplication()->getEventManager()->getSharedManager();
$sharedEventManager->attach('PresentationEdit','init', function($event) use ($services) {
$form = $event->getTarget();
$form->add(array(
'type' => '\Zend\Form\Element\Text',
'name' => 'title2',
'attributes' => array(
'type' => 'text',
'class' => 'form-control',
'autocomplete' => 'off',
),
'options' => array(
'label' => 'presentation.title',
)
));
}, 100);
In form:
use Zend\EventManager\EventManager;
In init method:
$event = new EventManager('PresentationEdit');
$event->trigger('init', $this);
It works, but is this the correct approach?

Access result of other field validation in a Zend Framework 2 validator

I have a form with two dates, start and stop. I have a validator for start and I want to validate stop and also that stop is after start. But the after validation only makes sense if start is valid.
isValid($value, $context = null) could be passed the other values in the context variable, but then I have to do the start check again.
So is there a possibility to check the result of the start validation in the stop validator's isValid() function?
You can use Callback
Or just write your own validator
------ Edit - my proposed answer - Input filter with callback or validator ------
I do that like this.
First create a filter with all params:
namespace MyGreatNameSpace\Filter;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
class MyDateFilter extends InputFilter
{
public function __construct($myGreatClass)
{
$factory = new InputFactory();
$this->add($factory->createInput(array(
'name' => 'start_date',
'required' => true,
'validators' => array(
array(
'name' => 'Date',
'options' => array(
'format' => '2000-10-10',
),
)
),
)));
$this->add($factory->createInput(array(
'name' => 'end_date',
'required' => true,
'validators' => array(
array(
'name' => 'Date',
'options' => array(
'format' => '2000-10-10',
),
),
array(
'name' => 'Callback',
'options' => array(
'callback' => array($myGreatClass, 'isDateNewer'),
'messages' => array(
'callbackValue' => "The end date is Older then the start date",
),
),
),
),
)));
} // End of __construct
}
Create the callback function
public function isDateNewer($date, $params)
{
$date2 = $params['start_date'];
if ($date > $date2) { // Over simplistic
return TRUE;
}
}
Implant in the controller (I used services to pull the form/filter class)
// Get the form / validator objects from the SM
$form = $this->getServiceLocator()->get('date_form');
$filter = $this->getServiceLocator()->get('date_filter');
// Inject the input filter object to the form object, load the form with data and bind the result to the model
$form->setInputFilter($filter);
$form->setData($post);
$form->bind($myModel); // (if you wish to bind the data to whatever)
if (!$form->isValid()) {
return $this->forward()->dispatch.... (or whatever)
}
Another slightly diffrent way (though cleaner) is to write a validator. Check the Zend\Validator\Identical (note the token)
array(
'name' => '\Application\Validator\myNewNamedValidator',
'options' => array(
'token' => 'start_date',
'messages' => array(
'older' => "The end date is Older then the start date",
),
),
),

ZFCUser extend form

I am using Zendframework 2 with ZfcUser and ZfcUserDoctrineORM.
I extended the normal user with some additional information.
Now i want to adapt the registerForm. Therefor i created this form in the ZfcUser\Form folder:
class UserRegister extends ZfcUser\Form\Register {
public function init(){
$this->add(array(
'name' => 'firstName',
'options' => array(
'label' => 'First Name',
),
'attributes' => array(
'type' => 'text'
),
));
$this->add(array(
'name' => 'name',
'options' => array(
'label' => 'Last Name',
),
'attributes' => array(
'type' => 'text'
),
));
}
}
In the Next step I changed adapted the getServiceConfig() function in the Module.php in the ZfcUser folder:
'zfcuser_register_form' => function ($sm) {
$options = $sm->get('zfcuser_module_options');
$form = new Form\UserRegister(null, $options);
//$form->setCaptchaElement($sm->get('zfcuser_captcha_element'));
$form->setInputFilter(new Form\RegisterFilter(
new Validator\NoRecordExists(array(
'mapper' => $sm->get('zfcuser_user_mapper'),
'key' => 'email'
)),
new Validator\NoRecordExists(array(
'mapper' => $sm->get('zfcuser_user_mapper'),
'key' => 'username'
)),
$options
));
return $form;
},
When calling the register url this error message is shown:
Fatal error: Cannot redeclare class UserRegister in C:\xampp\htdocs\THWDiver\vendor\zf-commons\zfc-user\src\ZfcUser\Form\UserRegister.php on line 24
What am I making wrong?
Realize this is an old question, but just stumbled onto it. You need to edit your Entity module's bootstrap and attach to 'ZfcUser\Form\Register' at 'init'.
I've got a blog article here that details the solution in depth:
http://circlical.com/blog/2013/4/1/l5wftnf3p7oks5561bohmb9vkpasp6
Hope it helps you!
I think that the answer is to override the service factory "zfcuser_register_form" and inside of it declare your own RegisterForm.

Zend Framework 2 Di creates class without parameters

I have the following code in config:
<?php
return array(
'di' => array(
'instance' => array(
'alias' => array(
'sms_message' => 'Sms\Message',
),
'sms_message' => array(
'parameters' => array(
'from' => 'SENDER',
),
),
),
),
);
And in Message.php class I have a setter (I dont want to use contructor):
/**
* From
* #var string
*/
protected $from;
/**
* #param string $from
*/
public function setFrom($from)
{
$this->from = $from;
}
But when I try to load it I get unconfigured object:
var_dump($this->getLocator()->get('Sms\Message'));exit;
object(Sms\Message)[596]
protected 'to' => null
protected 'from' => null
protected 'body' => null
How do I can make it work?
For setter-injection you have to use the injections keyword:
array(
'di' => array(
'instance' => array(
'alias' => array(
'sms_message' => 'Sms\Message'
),
'Sms\Message' => array(
'injections' => array(
'setFrom' => array(
'from' => 'SENDER'
),
),
),
),
),
);
I'm not sure if the instance configuration is supposed to work with aliases. Better use the FQCN instead.
I also discovered that currently injections are not executed when requesting an alias while reproducing your example:
// The will call setFrom(...)
$di->get('Sms\Message);
// This will not call setFrom(...)
$di->get('sms_message');
I don't know if this behavior is intended or not. (I'll report this test which is currently failing)

Resources