How to use translate method in view helper? - zend-framework2

Let say that we have example view helper code like this:
namespace Product\View\Helper;
use Zend\View\Helper\AbstractHelper;
class ProductType extends AbstractHelper
{
public function __invoke($id)
{
return $this->translate('Super extra product'); # How to use this method here
}
}
Now what it the best way to use translate in this view helper?
Regards,

The easiest way is translate view helper:
public function __invoke($id)
{
return $this->view->translate('Super extra product');
}
Also you can use ServiceManager to do translate or other actions.
In your Module.php change getViewHelperConfig to pass ServiceManager:
public function getViewHelperConfig()
{
return array(
'factories'=>array(
'ProductType'=>function ($helperPluginManager){
return new \Product\View\Helper\ProductType($helperPluginManager->getServiceLocator());
}
)
);
}
Now, you can use ServiceManager to translate in view helper:
class ProductType extends AbstractHelper
{
protected $serviceManager;
public function __construct($serviceManager)
{
$this->serviceManager = $serviceManager;
}
public function __invoke($id)
{
return $this->serviceManager->get('translator')->translate('Super extra product');
}
}

Related

Zend Framework 2 : unable to get servicelocator on a custom class

I am unable to load service locatior on a custom class, see my error code below, any advice would be appriciated
namespace Application\Helper;
use Zend\Mail\Message;
use Zend\Mail\Transport\Smtp as SmtpTransport;
use Zend\Mime\Message as MimeMessage;
use Zend\Mime\Part as MimePart;
use Zend\Mail\Transport\SmtpOptions;
use Zend\Mail\Transport\Sendmail;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class EmailHelper implements ServiceLocatorAwareInterface{
protected $serviceLocator;
public function testEmail($email){
$config = $this->serviceLocator->get('Config');
print_r($config); exit;
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
Call to a member function get() on null in
/var/www/html/engsvc_dev/module/Application/src/Application/Helper/EmailHelper.php
on line 23
In order to inject the ServiceManager instance which is an implementation of Zend\ServiceManager\ServiceLocatorInterface you need to instantiate the class like this:
$emailHelper = $this->getServiceLocator()->get('EmailHelper');
Also don't forget to register the class in Module.php
public function getServiceConfig()
{
return array(
'invokables' => array(
'EmailHelper' => 'Application\Helper\EmailHelper'
)
);
}

Struts2 & Java8 passing parameter to action using interface default method implementation - does not work

I'm passing parameter projectId to Struts action
http://localhost:8080/app/myaction.action?projectId=100
Simple action class is defined as:
public class MyAction extends AnyStrutsAction {
private ParamReader paramReader = new ParamReader();
public ParamReader getParamReader() {
return paramReader;
}
public void setProjectId(String id) {
getParamReader().setProjectId(id);
}
public void execute()
// ...
}
}
And everything works ok (/)
Next method setProjectId is extracted to interface and implemented as Java8 default method:
public interface ParamReaderAware {
ParamReader getParamReader();
default void setProjectId(String id) {
getParamReader().setProjectId(id);
}
}
public class MyAction extends AnyStrutsAction implements ParamReaderAware {
private ParamReader paramReader = new ParamReader();
#Override
public ParamReader getParamReader() {
return paramReader;
}
public void execute()
// ...
}
}
Now calling
http://localhost:8080/app/myaction.action?projectId=100
does not set parameter projectId. The default implementation is not visible for struts
My question is:
- does Struts2 support default interface method ?
- Is there any way to do so (any struts configuration, version (currentyly im using 2.3.16) )
Why I extract method to interface.
- I want to add reading parameter feature to multiple class actions

ZF2 TableGateway join

I am in the process of trying to learn OO/Zend Framework over standard PHP.. I want to scream and write a mysql query instead of using the TableGateway method.
I have been following tutorials and have successfully printed out a table and some fields, although with the way I have gone about doing this, I am totally lost in how I should make this a join with another table and print out some fields there.
For example.
Table Fields
customer Idx, Company
contact Idx, First_Name
This is my customersController where I assume the work is carried out
namespace Customers\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\DB\TableGateway\TableGateway;
class CustomersController extends AbstractActionController
{
protected $customersTable;
public function indexAction()
{
return new ViewModel(array('customer' => $this->getCustomersTable()->select()));
//return new ViewModel(array('customers' => $this->fetchJoin()->select()));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
public function getCustomersTable()
{
if (!$this->customersTable) {
$this->customersTable = new TableGateway (
'customer', //table name
$this->getServiceLocator()->get('Zend\DB\Adapter\Adapter')
);
}
return $this->customersTable;
}
}
Am I on the right track here?
If you need to make joins read about Zend\Db\Sql and Zend\Db\Select
which you can read about here
http://framework.zend.com/manual/2.0/en/modules/zend.db.sql.html
An example would be:
In your model(that extends the TableGateway or the AbstractTableGateway)
in Some function you can have something like(this is from a project) :
$sql = new \Zend\Db\Sql\Sql($this->getAdapter());
$select = $sql->select()
->from('event_related_events')
->columns(array())
->join('event_invitees', 'event_invitees.event_id =
event_related_events.related_event_id')
->where(array('event_related_events.event_id' => $eventId));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $this->getAdapter()->query($selectString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
Then you can loop over the results and do what you need to.
Taking a look at more powerful ORM like Doctrine or Propel may also help, but may be an overkill for a small/hobby project.
EDIT: Answer for what was asked in comments
For Using expression(if, case etc) directly you can use something like :
$sql->select()
->from('table')
->columns(array(
'sorter' => new Expression('(IF ( table.`something` >= 'otherthing', 1, 0))'),
'some_count' => new Expression('(count(*))'),
)
)
Explaining the last line in SQL terms, it would be:
count(*) AS some_count
So this is my controller, basically from the Album example but now it will display customers from the customer table.
<?php
namespace Customers\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Customers\Model\Customers;
use Customers\Form\CustomersForm;
class CustomersController extends AbstractActionController
{
protected $customersTable;
public function indexAction()
{
return new ViewModel(array(
'customer' => $this->getCustomersTable()->fetchAll(),
));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
public function getCustomersTable()
{
if (!$this->customersTable) {
$sm = $this->getServiceLocator();
$this->customersTable = $sm->get('Customers\Model\CustomersTable');
}
return $this->customersTable;
}
}
?>
The indexAction calls the getCustomersTable method which goes to the model (CustomersTable) and executes the "query" there.
<?php
namespace Customers\Model;
use Zend\Db\TableGateway\TableGateway;
class CustomersTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function getCustomers($id)
{
}
public function saveCustomers(customers $customers)
{
}
public function deleteCustomers($id)
{
}
}
?>
So from your example, I should be trying to implement this into the fetchAll in the model?
Thanks for the help.
$sql = new \Zend\Db\Sql\Sql($this->getAdapter());
$select = $sql->select()
->from('customer')
->columns(array())
->join('contact', 'contact.Idx = customer.Idx')
->where(array('contact.Idx' => $eventId));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $this->getAdapter()->query($selectString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);

Silex passing app and request to controller classes

I want a simple way to access $app and $request in my controller classes. The document says to do this,
public function action(Application $app, Request $request) {
// Do something.
}
but it doesn't look right to have to inject $app and $request to every method. Is there a way to include $app and $request to every controller by default, maybe using the constructor? I'd like to be able to use it as $this->app.
Thanks.
In the Controllers as Services part of the documentation you can see how to inject dependencies to controller classes via the constructor - in that case a repository.
It's possible :
Create a ControllerResolver.php somewhere in your project and put this inside :
namespace MyProject;
use Silex\ControllerResolver as BaseControllerResolver;
class ControllerResolver extends BaseControllerResolver
{
protected function instantiateController($class)
{
return new $class($this->app);
}
}
Then register it in your app (before $app->run();):
$app['resolver'] = function ($app) {
return new \MyProject\ControllerResolver($app, $app['logger']);
};
Now you can create a base controller for your app, for example :
namespace MyProject;
use Silex\Application;
use Symfony\Component\HttpFoundation\Response;
abstract class BaseController
{
public $app;
public function __construct(Application $app)
{
$this->app = $app;
}
public function getParam($key)
{
$postParams = $this->app['request_stack']->getCurrentRequest()->request->all();
$getParams = $this->app['request_stack']->getCurrentRequest()->query->all();
if (isset($postParams[$key])) {
return $postParams[$key];
} elseif (isset($getParams[$key])) {
return $getParams[$key];
} else {
return null;
}
}
public function render($view, array $parameters = array())
{
$response = new Response();
return $response->setContent($this->app['twig']->render($view, $parameters));
}
}
And extend it :
class HomeController extends BaseController
{
public function indexAction()
{
// now you can use $this->app
return $this->render('home.html.twig');
}
}

Inline Interface implementation in Actionscript

Is something like this possible in Actionscript?
Java:
URLFetcherFactory.setCreator(
new IURLFetcherCreator() {
public IURLFetcher create() {
return new URLFetcher();
}
}
);
Actionscript:
?
I've been wondering about this and have been unable to find anything that indicates it's possible. Figured if it was possible, I'd be able to find an answer here. Thanks! Stackoverflow rocks!
You cannot create an instance of an interface. You can, however, create a factory class:
public class URLFetcherCreator : IURLFetcherCreator {
private var _cls : Class;
public URLFetcherCreator(Class cls) {
this._cls = cls;
}
public function create() : IURLFetcher
{
return new cls();
}
}
Alternatively, change setCreator to accept a Function that returns an IURLFetcher:
URLFetcherFactory.setCreator(
function() : IURLFetcher {
return new URLFetcher();
}
);
Try this:
URLFetcherFactory.setCreator(
new IURLFetcherCreator() {
public function create():IURLFetcher {
return new URLFetcher();
}
}
);
You can't use anonymous inner classes in AS3.
For special cases like callbacks you can use Function instead of anonymous inner classes.
Java:
interface Callback {
void done(String info);
}
class Service {
void process(Callback callback);
}
...
myService.process(new Callback() {
void done(String info) {
// trace(info);
}
}
AS3:
class Service {
public function process(callback:Function):void;
}
...
myService.process(function(info:String):void {
trace(info);
});

Resources