How to modify parameters in Guzzle middleware? - middleware

I want to write a middleware for Guzzle that adds a specific key to the form_params and populates it with a value. In the docs I have read how to modify the headers but have not found anything about other properties of the $request object. Following the example from the docs this is what I have:
$key = 'asdf';
$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$stack->push(Middleware::mapRequest(function (RequestInterface $request) use ($key) {
// TODO: Modify the $request so that
// $form_params['api_key'] == 'default_value'
return $request;
}));
$client = new Client(array(
'handler' => $stack
));
The middleware should modify the request so that this:
$client->post('example', array(
'form_params' => array(
'foo' => 'some_value'
)
));
has the same effect as this:
$client->post('example', array(
'form_params' => array(
'foo' => 'some_value',
'api_key' => 'default_value'
)
));

Having done something similar to this, I can say it is very easy.
If you reference GuzzleHttp\Client two things happen when you pass an array into the request in the 'form_params' input option. First, the contents of the array become the body of the request after being urlencoded using http_build query() and secondly, the 'Content-Type' header is set to 'x-www-form-urlencoded'
The snippet below is akin to what you are looking for.
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
// perform logic
return new GuzzleHttp\Psr7\Request(
$request->getMethod(),
$request->getUri(),
$request->getHeaders(),
http_build_query($added_parameters_array) . '&' . $request->getBody()->toString()
);
}));

Related

Autocomplete with ajax in Symfony2

I'm using jQueryUI autocomplete to get a list of cities. I'm using a json array to display cities, but I just can't get the list to appear.
here is my Ajax function :
/**
* #Route("/ajax", name="ajax")
*/
public function ajaxAction(Request $request)
{
$value = $request->get('term');
$em = $this->getDoctrine()->getEntityManager();
$branches = $em->getRepository('AOFVHFlyBundle:City')
->findByName($value);
// Get branches by user if non-admin
$json = array();
foreach ($branches as $branch) {
$json[] = array(
'label' => sprintf('%s (%s)', $branch['name'], $branch['departement']),
'value' => $branch['id']
);
}
$response = new Response();
// better way to return json - via header?
$response->setContent(json_encode($json));
return $response;
}
and here is the form input :
->add('reqdeparture', 'genemu_jqueryautocompleter_entity', array(
'class' => 'AOFVH\FlyBundle\Entity\City',
'property' => 'name',
'route_name' => 'ajax',
'attr' => array(
'placeholder'=>'Départ',
'autocomplete' => 'on')
))
Whatever I type in the input, nothing appears.
Any idea why ? (at first I thought it was because collection was too big, but I barely have 50 cities)
You can use JsonResponse object. The Content-Type header will be 'application/json'. Symfony manage the chars to escape automatically and others conditions to return a JSON normalized correctly.
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* #Route("/ajax", name="ajax")
*/
public function ajaxAction(Request $request)
{
$value = $request->get('term');
$branches = $this->get("doctrine.orm.default_entity_manager")
->getRepository("NamespaceMyBundle:Entity")
->findByName($value);
$json = array();
foreach ($branches as $branch) {
$json[] = array(…);
}
return new JsonResponse($json);
}

How to change layout in controller in ZendFramework2?

I found this topic and answer: Change layout in the controller of Zend Framework 2.0 :: Answer
I am trying to do this:
public function loginAction() {
if ($this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcadmin');
}
$this->layout('layout/login');
return new ViewModel();
}
But it doesn't work.
Sure I have file MODULE_DIR/view/layout/login.phtml.
I tried to var_dump($this->layout()); before setting layout and after it and it shows, that layout is changed after $this->layout('layout/login'); line. But it is not.
How to set different layout in controller?
Also, why I don't get any messages if layout is changed? Why standart layout loaded, instead of error?
I think, I have to set up layout somewhere (like I set routes, for example). Possibly in config ['view_manager']['template_map'] by adding something like:
$config = array(
'view_manager' => array(
'template_path_stack' => array(
__DIR__ . '/../view'
),
'template_map' => array(
'layout/login' => __DIR__ . '/../view/layout/login.phtml',
),
),
);
— like said there:
Of course you need to define those layouts, too... just check
Application Modules module.config.php to see how to define a layout.
That didn't helped me :(
Update 1
Tried this:
public function loginAction() {
if ($this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcadmin');
}
$layout = $this->layout();
$layout->setTemplate('layout/login');
return new ViewModel();
}
as #alex suggested. Doesn't work :'(. Same result without return new ViewModel(); line.
You review files by yourself:
AdminController.php (loginAction)
module.config.php (to be sure I added layout/login correctly
Update 2
I tried to debug as you suggest.
I updated __invoke functioN:
public function __invoke($template = null)
{
var_dump($template);
die();
if (null === $template) {
return $this->getViewModel();
}
return $this->setTemplate($template);
}
There are some cases:
With code, you suggested:
$layout = $this->layout();
$layout->setTemplate('layout/login');
it displays NULL. So method is called, but $template is null variable.
With code, from post, I had given in the start of my post:
$this->layout('layout/login');
return new ViewModel();
It shows string(12) "layout/login".
Without any code (so layout layout/admin loaded (default for ZfcAdmin), it shows: string(12) "layout/admin".
If I load / of my site it page is loaded with standart layout (in both cases with or without layout/layout in module config.
Update 3
I tried this:
$layout = $this->layout();
var_dump($layout->getTemplate());
$layout->setTemplate('layout/login');
var_dump($layout->getTemplate());
die();
in controller. It shows: string(13) "layout/layout" string(12) "layout/login". So layout is changed. But standart layout layout/layout rendered instead of layout/login. :(
Because you're using ZfcAdmin and have the use_admin_layout option enabled in that module and the login route you're attempting to set a layout on is a child route of ZfcAdmin, the admin layout listener is kicking in and over-writing the template you're attempting to set in your controller action.
It's perhaps easiest to disable zfcadmin layout, write your own listener and handle the specific case of login layout there. You can do that using essentially the same method that ZfcAdmin uses in Module.php with a tweak or two ...
Be sure to disable ZfcAdmin layout
'zfcadmin' => array(
'use_admin_layout' => false,
),
then, using your module name as a config key, set up your own version of the same config ...
'myzfcadmin' => array(
'use_admin_layout' => true,
'admin_layout_template' => 'layout/admin',
// you could even define a login layout template here
'login_layout_template' => 'layout/login',
),
Next in MyZfcAdmin/Module.php add a listener, almost exactly like the one in ZfcAdmin only have it check your myzfcadmin config values instead ...
public function onBootstrap(MvcEvent $e)
{
$app = $e->getParam('application');
$em = $app->getEventManager();
$em->attach(MvcEvent::EVENT_DISPATCH, array($this, 'selectLayoutBasedOnRoute'));
}
public function selectLayoutBasedOnRoute(MvcEvent $e)
{
$app = $e->getParam('application');
$sm = $app->getServiceManager();
$config = $sm->get('config');
if (false === $config['myzfcadmin']['use_admin_layout']) {
return;
}
$match = $e->getRouteMatch();
$controller = $e->getTarget();
if (!$match instanceof \Zend\Mvc\Router\RouteMatch
|| 0 !== strpos($match->getMatchedRouteName(), 'zfcadmin')
|| $controller->getEvent()->getResult()->terminate()
) {
return;
}
if ($controller instanceof \MyZfcAdmin\Controller\AdminController
&& $match->getParam('action') == 'login'
) {
// if you'd rather just set the layout in your controller action just return here
// return;
// otherwise, use the configured login layout ..
$layout = $config['myzfcadmin']['login_layout_template'];
} else {
$layout = $config['myzfcadmin']['admin_layout_template'];
}
$controller->layout($layout);
}
As you can see, I added code to check the controller is your specific AdminController instance and login action, and if so, set the alternate template otherwise use the default, no need to worry about it in your controller now.
Add your layout in the template map of your view manager in the module.config.php
Like so:
// View file paths
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array
'layout/login' => 'path_to_layout_file'
)
)
Then, in your controller try setting the layout like this, using the setTemplate() method:
$layout = $this->layout();
$layout->setTemplate('layout/login');
EDIT, the following is code from the Zend library:
Inside Zend\Mvc\Controller\Plugin\Layout notice this method:
/**
* Invoke as a functor
*
* If no arguments are given, grabs the "root" or "layout" view model.
* Otherwise, attempts to set the template for that view model.
*
* #param null|string $template
* #return Model|Layout
*/
public function __invoke($template = null)
{
if (null === $template) {
return $this->getViewModel();
}
return $this->setTemplate($template);
}
If you don't provide a template it will call this method:
/**
* Retrieve the root view model from the event
*
* #return Model
* #throws Exception\DomainException
*/
protected function getViewModel()
{
$event = $this->getEvent();
$viewModel = $event->getViewModel();
echo '<pre>' . print_r($viewModel, true) . '</pre>';die;
if (!$viewModel instanceof Model) {
throw new Exception\DomainException('Layout plugin requires that event view model is populated');
}
return $viewModel;
}
Notice the print_r statement, if you look at it, it will show you this:
Zend\View\Model\ViewModel Object
(
[captureTo:protected] => content
[children:protected] => Array
(
)
[options:protected] => Array
(
)
[template:protected] => layout/layout
[terminate:protected] =>
[variables:protected] => Zend\View\Variables Object
(
[strictVars:protected] =>
[storage:ArrayObject:private] => Array
(
)
)
[append:protected] =>
)
Notice the [template:protected] => layout/layout that why I was saying I think Zend defaults to that layout.
So go into that file, in the __invoke method and do echo $template;die; when you are setting your layout with $this->setTemplate('layout/login') in your controller and see if its even getting passed there. Then you might be able to trace it better.
EDIT: Setting up multiple layouts.
Here is one way you could set up layouts for your modules in an effort to reduce the likelihood of a conflict or something being overwritten.
// where $sm is the service manager
$config = $sm->get('config');
$config = array_merge($config, include '/path_to_config/layouts.config.php');
if (isset($config['module_layouts'][$moduleNamespace]))
{
$controller->layout($config['module_layouts'][$moduleNamespace]);
}
And your layouts config could look something this:
'module_layouts' => array(
'_default' => 'layout/layout',
'admin' => 'layout/admin',
'foo' => 'layout/foo',
'login' => 'layout/login' // etc, etc
),

Zend2: Specify currency prefix?

In Zend2 you can do this:
<?php echo $this->currencyFormat(120, 'ZAR'); ?>
This will result in:
ZAR 120.00
However, I want to end up with:
R 120.00
How can I set the prefix to rather be the currency symbol, as apposed to the code? The following doesn't work (obviously):
<?php echo $this->currencyFormat(120, 'R'); ?>
Figured it out myself. Easy as this:
$helper->setCurrencyPattern('R #0.#');
So the complete code which allows me to control everything in one place (Module.php) is as follows:
class Module
{
public function getConfig()
{
return array(
'view_helpers' => array(
'factories' => array(
'currencyFormat' => function($sm)
{
$helper = new \Zend\I18n\View\Helper\CurrencyFormat;
$helper->setCurrencyCode("ZAR");
$helper->setLocale('us_ZA');
$helper->setCurrencyPattern('R #0.#');
return $helper;
},
)
),
);
}
}
Enjoy...

How to add a class to all labels in a ZF2 form

I'm using a jQuery plugin that takes the text from labels associated with form elements and puts them as default text for the fields themselves. (You can find the plugin here.)
Here's the catch: it can only do this if the label has the class "inline". Now, I know I can use the following code to do this:
$this->add(array (
'name' -> 'name',
....
'options' => array (
'label' => 'Name',
'label_attributes' => array (
'class' => 'inline'
)
)
));
This will work fine, and if it has to be done item by item, then so be it. But I was wondering if there's some way I can add the class to ALL labels associated with text and text area form elements without using JavaScript. I'm thinking this would either done by a plugin, or by looping through all the elements in the form, but I don't know how to do either.
You could extend the FormRow view helper.
Here is a little example:
use Zend\Form\View\Helper\AbstractHelper;
use Zend\Form\View\Helper\FormRow;
class CustomFormRow extends FormRow
{
public function render(ElementInterface $element) {
...
$label = $element->getLabel();
if (isset($label) && '' !== $label) {
// Translate the label
if (null !== ($translator = $this->getTranslator())) {
$label = $translator->translate(
$label, $this->getTranslatorTextDomain()
);
}
$label->setAttribute('class', 'inline');
}
...
if ($this->partial) {
$vars = array(
'element' => $element,
'label' => $label,
'labelAttributes' => $this->labelAttributes,
'labelPosition' => $this->labelPosition,
'renderErrors' => $this->renderErrors,
);
return $this->view->render($this->partial, $vars);
}
...
}
You could probably leave the rest as it is and you should be good to go once you add some configuration in your Module.php for your view helper.
public function getViewHelperConfig() {
return array(
'factories' => array(
'CustomFormRow' => function($sm) {
return new \Application\View\Helper\CustomFormRow;
},
)
);
}
In your template files you now have to use your viewHelper instead.
<?php echo $this->CustomFormRow($form->get('yourelement')); ?>

ZF2 addChild ViewModel of another module

I'm trying to add a view of another module in my layout, so I did this:
$layoutTestdrive = new ViewModel();
$layoutTestdrive->setTemplate('testdrive6');
$view = new ViewModel();
$view->addChild($layoutTestdrive);
return $view;
In my module.config.php I did this:
'Zend\View\Resolver\TemplateMapResolver' => array(
'parameters' => array(
'map' => array(
'testdrive6' => __DIR__ . '/../../Testdrive/view/layout/testdrive6.phtml'
),
),
),
Is this correct?
Hi i think you need to use forward first
public function commentAction(){
$list = $this->forward()->dispatch('comment_controrller', array('action' => 'list'));
$add = $this->forward()->dispatch('comment_controrller', array('action' => 'add'));
$view = new ViewModel();
$view->addChild($list, 'list');
$view->addChild($add, 'add');
return $view;
}
I hope this will help
or if you want just to change template see Different layout file for different controller

Resources