How to call on view on dyanmic actions in zf2 - zend-framework2

Hello friends I am new in zf2. I stuck at one place. In my project I want to to call one view on many action.
My url is "baseurl/g/any-thing-from-from-database"
I want to call a view on "any-thing-from-from-database" action from another module or same.
My G module have this code on module.config.php
return array(
'controllers' => array(
'invokables' => array(
'G\Controller\G' => 'G\Controller\GController',
),
),
'router' => array(
'routes' => array(
'g' => array(
'type' => 'segment',
'options' => array(
'route' => '/g[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'G\Controller\G',
'action' => 'g',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'g' => __DIR__ . '/../view',
),
),
);
on GController.php
namespace G\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Stdlib\ResponseInterface as Response;
use Zend\View\Renderer\PhpRenderer;
use Students\Form\StudentsForm;
use Students\Model\Students;
class GController extends AbstractActionController
{
public function dispatch(Request $request, Response $response = null)
{
$controller = $this->params('controller');
$nicname = $this->params('action');
if($nicname !== false){
$hosts = $this->getServiceLocator()->get('Manager\Model\HostsTable');
if(($data = $hosts->findByNicname($nicname)) !== null){
$captchaService = $this->getServiceLocator()->get('SanCaptcha');
$form = new StudentsForm($captchaService);
return array('from'=>$form);
}
}
return $this->redirect()->toRoute('home',array('controller'=>'application','action'=>'index'));
}
public function gAction()
{
return new ViewModel();
}
}
To get different actions from url I have used dispatch function that is working correctly. When i get this action from database I want to show a form with some content from different module named Students or G. But this code only showing header and footer and nothing else without any error.Please help me out.Thanks in advance.

I think overwriting dispatch method cannot be very good.
I'm sure you don't see anything, because you don't ever render a ViewModel, so no data are there. This is because you disabled default dispatch behaviour and overwrite the action argument in your route. So if you open http://my.website/g/foobar then foobarAction() would be called - if your dispatch will work correctly.
So what you could do is simple rename your action param to (for example) foo, take your logic to gAction() and do what ever you have to do with $this->param('foo').

Related

ZF2 I would like to pass json string

I would like to pass json to action, something similar to passing simple variable:
/** module.config.php
'mobileapplication-topup' => array(
'type' => 'segment',
'options' => array(
'route' => '/mob/topup[/:voucherID]',
'constraints' => array(
'voucherID' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Mob\Controller\Topup',
'action' => 'index',
),
),
and TopupController.php
public function indexAction()
{
echo ($this->params('voucherID'));
$result = new ViewModel();
$result->setTerminal(true);
return $result;
}
//** no layout //
$response = $this->getResponse();
$response->setStatusCode(200);
$response->setContent("Error");
return $response;
}
something similar to this, but just a json string instead of voucherID. What kind of constraints should be added to this json variable?
** Is there any way how to POST the form from other domain to ZF2?
I have found solution, but I don't think it is a perfect one...
What I was thinking that there is some way of passing variables using route
mvc.com/controller/param1/param2
and into this for example just pass a json and decode it in one of the controllers...
but at the moment I'm using basing _GET method
mvc.com/controller/param1/param2?"Json"={"p1":"value1","p2":"value2"}

How to pass the paramter values to another controller's action in ZF2

Hello friends I am new in zf2. I am creating an action in controller, all things are working correctly. When the form is valid, i would like to pass some of the values to redirect page. how can i do this? Please help me out.
My controller action is
public function studenteditAction(){
$id = (int) $this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('manager', array(
'action' => 'students'
));
}
$form = new StudentsForm();
$request = $this->getRequest();
if ($request->isPost()) {
$students = new Students();
$form->setData($request->getPost());
if ($form->isValid()) {
$students->exchangeArray($form->getData());
$table = $this->getServiceLocator()->get('Students\Model\StudentsTable');
$table->profileStudents($students);
return $this->redirect()->toRoute('manager',array('controller'=>'manager','action'=>'student-view','id'=>$id,'status' => 'profile-ready'));
}
}
return array(
'id' => $id,
'form' => $form,
);
}
I am unable to get the passed status value on controller's view.
'status' => 'profile-ready'
Thanks in advance
You need to modify your routing configuration to accept both 'id' and 'status' values.
'manager' => array(
'type' => 'Segment',
'options' => array(
'route' => '/manager[/:id][/:status]',
'defaults' => array(
'controller' => 'Application\Controller\Manager',
'action' => 'studentView',
),
'constraints' => array(
'id' => '[0-9]*',
'status' => '[a-z-]*'
),
),
),
Controller:
public function studentViewAction()
{
$id = $this->params()->fromRoute('id');
$status = $this->params()->fromRoute('status');
return new ViewModel(array('id' => $id, 'status' => $status));
}
View
<?php
echo $this->id;
echo $this->status;
?>
This is how i pass the required values to another controller's action

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",
),
),
),

ZF2: Controller's Forward plugin doesn't work. How to make it work?

I need to forward the ajax request to the other Action method of current controller. I use the Forward plugin but it doesn't work. There is an example in the manual about how to use the Forward Plugin:
$foo = $this->forward()->dispatch('foo', array('action' => 'process'));
return array(
'somekey' => $somevalue,
'foo' => $foo,
);
My code:
// From Ajax on the page. I apply to the indexAction of FooController,
// I use RegEx route
xhr.open('get', '/fooindex', true);
// My Controller
namespace Foo\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
// I extend the AbstractActionController, the manual says it's important for the Forward Plugin to work
class FooController extends AbstractActionController {
// This is the action I send my request from Ajax
public function indexAction() {
// if the request if Ajax request I forward the run to the nextAction method
if ($this->getRequest()->isXmlHttpRequest()) {
// I do as manual says
$rs = $this->forward()->dispatch('FooController', array('action' => 'next'));
}
}
public function nextAction() {
// And I just want to stop here to see that the Forward Plugin works
// But control doesn't reach here
exit('nextAction');
}
}
The error I get in the Console is:
GET http://test.localhost/fooindex 500 (Internal Server Error)
If I do not use Forward everything works fine, the request comes to the indexAction just fine. Only Forward throws an error.
From the manual, about The Forward Plugin:
For the Forward plugin to work, the controller calling it must be
ServiceLocatorAware; otherwise, the plugin will be unable to retrieve
a configured and injected instance of the requested controller.
From the manual, about Available Controllers:
Implementing each of the above interfaces is a lesson in redundancy;
you won’t often want to do it. As such, we’ve developed two abstract,
base controllers you can extend to get started.
AbstractActionController implements each of the following interfaces:
Zend\Stdlib\DispatchableInterface
Zend\Mvc\InjectApplicationEventInterface
Zend\ServiceManager\ServiceLocatorAwareInterface
Zend\EventManager\EventManagerAwareInterface
So my FooController extends AbstractActionController, which implements ServiceLocatorAwareInterface, so the Forward has to work, but it doesn't. What did I miss? How to make it work?
You should remember that the dispatch plugin gets the controller to dispatch to from the service manager by name. You should therefore use the correct name and not just the classname.
Look in your configuration for the controllers.invokables array. That should contain which name of the service maps to what FQCN.
It might be you name IS FooController, then forget what I just said
You should use fully qualified name when calling the controller, so 'FooController' should be namespaced as well.
Also, you should add the controller in the list of the invokables in the module config files, for example:
return array(
'controllers' => array(
'invokables' => array(
'FooController' => 'Namespace/Controller/FooController'
...
),
)
)
try this:
class FooController extends AbstractActionController {
public function indexAction() {
return $this->forward()->dispatch('Bar\Controller\Bar',
array(
'action' => 'process',
'somekey' => $somevalue,
));
}
}
here invokable is: 'Bar\Controller\Bar' => 'Bar\Controller\Bar'
try this:
class FooController extends AbstractActionController {
public function indexAction() {
return $this->forward()->dispatch('Foo',
array(
'action' => 'process',
'somekey' => $somevalue,
));
}
}
Your module.config.php file is like this:
'controllers' => array(
'invokables' => array(
'Foo' => 'Foo\Controller\FooController', // <----- Module Controller
),
),
'router' => array(
'routes' => array(
'foo' => array(
'type' => 'segment',
'options' => array(
'route' => '/foo[/:action][/:id]', // <---- url format module/action/id
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Foo', // <--- Defined as the module controller
'action' => 'index', // <---- Default action
),
),
),
),
),

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