Variables available in all controllers? - zend-framework

Where and how to set variable value that is available in all controllers. I don't wont to use zend registry and don't want to extend Zend_Controller_Action. Is there is another way? I just want for example to set:
$a = "test";
and in Index controller to dump it:
class IndexController extends Zend_Controller_Action {
public function indexAction(){
var_dump($a);
}
}

Global vars ruin the purpose of object oriented programming... use namespace or custom configs.
Solution 1
Use session Zend_Session_Namespace, here is documentation on how to Zend_Session_Namespace.
Set set the value in namespace in bootstrap or something (wherever you see fit)
Retrieve the value from namespace in you controller/model/other
Solution 2
Alternatively, you can create some new class with static properties and use it's setters/getters to set and retrieve values.
E.g.
class SomeClass
{
static $hello = 'world';
}
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
var_dump(SomeClass::$hello);
}
}

You can add variables to the request object:
$this->getRequest()->setParam('a', 'hello');
Then retrieve it using:
$this->getRequest()->getParam('a);
But that is not the best way of doing it as you might accidentally overwrite a parameter a needed parameter.

Related

Typo3 Extension Scheduler Command Controller

here is a problem I encountered in TYPO3 Extension Development.
I've written an TYPO3-extension. It will display in browser the news in the DB. But I'd like to configure a scheduler task to recurrently update the news in the DB to be displayed.
In writing this scheduler task I've used a Command Controller.
namespace Vendor\Extension\Command;
class CheckNewsCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController
{
public function simpleCommand()
{
$newsRepository = $this->objectManager->get( \Vendor\Extension\Domain\Repository\NewsRepository::class );
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($newsRepository);
$all_news = $newsRepository->findAll();
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($all_news);
}
}
But the variable $all_news contains nothing, it equals to NULL !!! That means, the findAll() Function of the NewsRepository does NOT work at all !!!
In comparison, I've also used this NewsRepository in a normal Controller Class: Vendor\Extension\Controller\NewsController
namespace Vendor\Extension\Controller;
class NewsController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
public function listAction()
{
$newsRepository = $this->objectManager->get( \Etagen\EtSocNewsSt\Domain\Repository\NewsRepository::class );
$all_news = $newsRepository->findAll();
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($all_news);
}
And, in the NewsController, the function NewsRepository::findAll() DID really work, and returned all records in the DB.
So, who can tell me, why the Repository function will ONLY work in the class Vendor\Extension\Controller\NewsController, but NOT work in the class Vendor\Extension\Command\CheckNewsCommandController ?
The answer is EASY: You need to define the storagePid for your news records in the CommandController OR change the settings of the NewsRepository to IGNORE the storagePid.
How to set the storagePid for CommandController:
https://worksonmymachine.org/blog/commandcontroller-and-storagepid
How to set the repository to ignore storagePid:
http://typo3.sascha-ende.de/docs/development/database/how-to-ignore-the-page-id-pid-in-repository-database-query/

Symfony2 get public services in controller

Much ink has flowed about Sf2 controller/container. I face with follow situation:
app/console container:debug security
...
> 4
[container] Information for service security.token_storage
Service Id security.token_interface
Class Symfony\Component\Security\Core\Authentication\Token ...
...
Public yes
LoginBundle\DefaultController.php
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction()
{
dump(Controller::get('security.token_storage'));
...
works OK, obviously.
LoginBundle\UserUtilsController
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UserUtilsController extends Controller
{
public function getRoleById()
{
dump(Controller::get('security.token_storage'));
...
throw: Error: Call to a member function get() on a non-object
In Sf2 Book - Service container I found:
In this example, the controller extends Symfony's base Controller, which gives you access to the service container itself. You can then use the get method to locate and retrieve the my_mailer service from the service container.
The misunderstanding is:
- Both controllers extends basic controller which itself extends ContainerAware which implements ContainerAwareInterface which set container.
- Both controllers access same public service container.
So, why the second controller it doesn't work?
I know that the question is old but I don't want to inject a controller as service and I think it is redundant and wrong to redeclare a public service in services.yml
Thank you in advance.
I found the answer myself and I want to share for every one is in same situation...
The UserUtilsController doesn't work because it's not working in this manner. The Symfony architecture is interesting if you get to know it.
LoginBundle\Controller\UserUtilsController
// For this job we don't need to extends any class..
class UserUtilsController
{
// but we need a property for injecting the service in it
private $token;
// Now let's inject service into our property $token
public function __construct($token)
{
$this->token = $token;
}
// It's not done but let pretend it is and let's use it
public function getRoleById()
{
...
return $this->token->getToken()->getRoles();
...
services.yml
#here it's the magic
services:
# this is a new services container
user.loggeduser_utils:
# this is my class (second class)
class: LoginBundle\Controller\UserUtilsController
# this is how I feed my _construct argument
arguments: ["#security.token_storage"]
So I just inject an existing service in my new class.
Now, to use this we must to call in first class:
LoginBundle\Controller\DefaultController.php
class DefaultController extends Controller
{
public function indexAction()
{
// because my class is now a service container we call in this way
$userRoleId = $this->get('user.loggeduser_utils');
...
This solution above is almost trivial simple AFTER understanding the Sf2 DI model.

Zend Framework - How can i share common code between some of a controller's actions?

To keep my controllers as DRY as possible i need to share some common code (a big chunk of code) between say 2 of my controller's actions and not all of them and i need access variables in this shared code in my actions.
For example:
class FirstController extends Zend_Controller_Action {
public function firstAction() {
//common code here: contains an array $columns
}
public function secondAction() {
//common code here: contains an array $columns also
}
//other actions
}
so how can I refactor this to put the common code in one place and be able to access $columns and in firstAction() and secondAction().
Thanks.
I don't recommend you to use a base controller. It's overkilling and heavy for such a small task. Since you want to share common code within one controller, use instead an action helper and a class attribute $columns that you can send as argument to your action helper.
Read more about action helpers here.
Action Helpers allow developers to inject runtime and/or on-demand
functionality into any Action Controllers that extend
Zend_Controller_Action. Action Helpers aim to minimize the necessity
to extend the abstract Action Controller in order to inject common
Action Controller functionality.
You can create new class and extend Zend_Controller_Action then extend your newly created class not Zend_Controller_Action
example:
class CommonactionsController extends Zend_Controller_Action {
public function firstAction() {
//common code here : contains an array $columns
}
public function secondAction() {
//common code here : contains an array $columns also
}
//other actions
}
and then:
class FirstController extends CommonactionsController {
// here you can use all your common actions...
}
second controller..
class SecondController extends CommonactionsController {
// here you can use all your common actions...
}
and so on...

Zend Framework: How to inject a controller property from a Zend_Controller_Plugin

I wrote a plugin that needs to set a property on the controller that's currently being dispatched. For example, if my plugin is:
class Application_Plugin_Foo extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
// Get an instance of the current controller and inject the $foo property
// ???->foo = 'foo';
}
}
I want to be able to do this:
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->foo = $this->foo;
}
}
}
Any help is greatly appreciated!
The action controller is not directly accessible directly from a front-controller plugin. It's the dispatcher that instantiates the controller object and he doesn't appear to save it anywhere accessible.
However, the controller is accessible from any registered action helpers. Since action helpers have a preDispatch hook, you could do your injection there.
So, in library/My/Controller/Helper/Inject.php:
class My_Controller_Helper_Inject extends Zend_Controller_Action_Helper_Abstract
{
public function preDispatch()
{
$controller = $this->getActionController();
$controller->myParamName = 'My param value';
}
}
Then register an instance of the helper in application/Bootstrap.php:
protected function _initControllerInject()
{
Zend_Controller_Action_HelperBroker::addHelper(
new My_Controller_Helper_Inject()
);
}
And, as always, be sure to include My_ as an autoloader namespace in configs/application.ini:
autoloaderNamespaces[] = "My_"
Then, in the controller, access the value directly as a public member variable:
public function myAction()
{
var_dump($this->myParamName);
}
One thing to note: Since the helper uses the preDispatch() hook, I believe it will get called on every action, even an internal forward().
Browsing through the API, I didn't find a way to reach the controller directly (I'm guessing this loop is performed before the controller exists). What I could find is almost as easy to access, albeit with a bit different syntax.
Via request params
class Application_Plugin_Foo extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$yourParam = 'your value';
if($request->getParam('yourParam')) {
// decide if you want to overwrite it, the following assumes that you do not care
$request->setParam('yourParam', $yourParam);
}
}
}
And in a Zend_Controller_Action::xxxAction():
$this->getParam('yourParam');
Via Zend_Controller_Action_Helper_Abstract
There's another way mentioned in MWOP's blog, but it takes the form of an action helper instead: A Simple Resource Injector for ZF Action Controllers. His example would let you access any variable in Zend_Controller_Action as $this->yourParam.

How to automatically set and attribute to controller

Maybe the question is not self-explanatory, so I will explain it through.
The deal is: I got the variable $conn in the bootstrap class file. I'd like to make it global for every controller so that I just have to call $this->conn in the controller action scope in order to access the data inside. How would I do it?
Thx
One fairly straightforward way is to create your own base class form which your controller's inherit:
<?PHP
class My_Controller_Action extends Zend_Controller_Action {
public $conn;
public function init(){
//set $this->conn
}
}
class Some_Real_Controller extends My_Controller_Action {
//$this->conn exists!
}
class Some_Other_Real_Controller extends My_Controller_Action {
//$this->conn exists here too!
}
Matthew Weier O'Phinney posted a blog entry recently with some examples of how to use action helpers to do this, see:
http://weierophinney.net/matthew/archives/235-A-Simple-Resource-Injector-for-ZF-Action-Controllers.html
this will achieve the same thing without having to use a base controller class.