Hello I need to use evalmath.class.php within a Yii application. How can I include it from my controller?
Something like this:
public function actionFormulas() {
include('models/evalmath.class.php');
$m = new EvalMath;
...
}
But the above code does not work. How can I include an external class within a controller?
In your example, to use include/require you probably need to add some path info with dirname(__FILE__).'/../models/...' or similar, but to do it within the Yii framework, you would first create an alias (usually in your main config file) with setPathOfAlias :
Yii::setPathOfAlias('evalmath', $evalmath_path);
Then you can use Yii::import like so:
Yii::import('evalmath', true);
and proceed as you were:
$m = new EvalMath();
..etc...
class ServiceController extends Controller
{
public function actionIndex()
{
Yii::import('application.controllers.back.ConsolidateController'); // ConsolidateController is another controller in back controller folder
echo ConsolidateController::test(); // test is action in ConsolidateController
Related
In my app, I was testing Google Directions API with ajax, but since I was just testing all the logic was in the routes.php file. Now I want to do things the proper way and have three layers: route, controller and service.
So in the routes I tell Laravel which method should be executed:
Route::get('/search', 'DirectionsAPIController#search');
And the method just returns what the service is supposed to return:
class DirectionsAPIController extends BaseController {
public function search() {
$directionsSearchService = new DirectionsSearchService();
return $directionsSearchService->search(Input::all());
}
}
I created the service in app/libraries/Services/Directions and called it DirectionsSearchService.php and copied all the logic I developed in routes:
class DirectionsSearchService {
public function search($input = array()) {
$origin = $input['origin'];
$destination = $input['destination'];
$mode = $input['mode'];
// do stuf...
return $data;
}
}
I read the docs and some place else (and this too) and did what I was supposed to do to register a service:
class DirectionsAPIController extends BaseController {
public function search() {
App::register('libraries\Services\Directions\DirectionsSearchService');
$directionsSearchService = new DirectionsSearchService();
return $directionsSearchService->search(Input::all());
}
}
// app/libraries/Services/Directions/DirectionsSearchService.php
use Illuminate\Support\ServiceProvider;
class DirectionsSearchService extends ServiceProvider {
}
I also tried adding libraries\Services\Directions\DirectionsSearchService to the providers array in app/config/app.php.
However, I am getting this error:
HP Fatal error: Class
'libraries\Services\Directions\DirectionsSearchService' not found in
/home/user/www/my-app-laravel/bootstrap/compiled.php on line 549
What am I doing wrong? And what is the usual way to use your own services? I don't want to place all the logic in the controller...
2 main things that you are missing:
There is a difference between a ServiceProvider and your class. A service provider in Laravel tells Laravel where to go look for the service, but it does not contain the service logic itself. So DirectionsSearchService should not be both, imho.
You need to register your classes with composer.json so that autoloader knows that your class exists.
To keep it simple I'll go with Laravel IoC's automatic resolution and not using a service provider for now.
app/libraries/Services/Directions/DirectionsSearchService.php:
namespace Services\Directions;
class DirectionsSearchService
{
public function search($input = array())
{
// Your search logic
}
}
You might notice that DirectionsSearchService does not extend anything. Your service becomes very loosely coupled.
And in your DirectionsAPIController.php you do:
class DirectionsAPIController extends BaseController
{
protected $directionsSearchService;
public function __construct(Services\Directions\DirectionsSearchService $directionsSearchService)
{
$this->directionsSearchService = $directionsSearchService;
}
public function search()
{
return $this->directionsSearchService->search(Input::all());
}
}
With the code above, when Laravel tries to __construct() your controller, it will look for Services\Directions\DirectionsSearchService and injects into the controller for you automatically. In the constructor, we simply need to set it to an instance variable so your search() can use it when needed.
The second thing that you are missing is to register your classes with composer's autoload. Do this by adding to composer.json's autoload section:
"autoload": {
"classmap": [
... // Laravel's default classmap autoloads
],
"psr-4": {
"Services\\": "app/libraries/Services"
}
}
And do a composer dump-autoload after making changes to composer.json. And your code should be working again.
The suggestion above can also be better with a service provider and coding to the interface. It would make it easier to control what to inject into your controller, and hence easier to create and inject in a mock for testing.
It involves quite a few more steps so I won't mention that here, but you can read more in Exploring Laravel’s IoC container and Laravel 4 Controller Testing.
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.
So i have been designig an application to run on the Zend Framework 1.11 And as any programmer would do when he sees repeated functionalities i wanted to go build a base class with said functionalities.
Now my plan is to build a library 'My' so i made a folder in the library directory in the application. So it looks like this
Project
Application
docs
library
My
public
test
So i created a BaseController class in the My folder and then decided to have the IndexController in my application extend the BaseController.
The Basecontroller looks like this :
class My_BaseController extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->test = 'Hallo Wereld!';
}
}
And the IndexController looks like this :
class WMSController extends My_BaseController
{
public function indexAction()
{
parent::indexAction();
}
}
As adviced by a number of resources i tried adding the namespace for the library in the application.ini using the line
autoloadernamespaces.my = “My_”
But when i try to run this application i recieve the following error
Fatal error: Class 'My_BaseController' not found in
C:\wamp\www\ZendTest\application\controllers\IndexController.php
Am i missing something here? Or am i just being a muppet and should try a different approach?
Thanks in advance!
Your original approach will work for you in application.ini, you just had a couple of problems with your set up.
Your application.ini should have this line:-
autoloadernamespaces[] = "My_"
Also, you have to be careful with your class names, taking your base controller as an example, it should be in library/My/Controller/Base.php and should look like this:-
class My_Controller_Base extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->test = 'Hello World!';
}
}
You can then use it like this:-
class WMSController extends My_Controller_Base
{
public function indexAction()
{
parent::indexAction();
}
}
So, you had it almost right, but were missing just a couple of details. It is worth getting to know how autoloading works in Zend Framework and learning to use the class naming conventions
I don't know about .ini configuration, but I add customer libraries like this (index.php):
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance()->registerNamespace('My_');
I have a layout loader plugin which looks like this:
class Controller_Action_Helper_LayoutLoader extends Zend_Controller_Action_Helper_Abstract
{
public function preDispatch()
{
$config = Zend_Registry::get("config");
$module = $this->getRequest()->getModuleName();
if (isset($config->$module->resources->layout->layout) && !$this->getRequest()->format)
{
$layoutScript = $config->$module->resources->layout->layout;
$this->getActionController()->getHelper('layout')->setLayout($layoutScript);
}
}
}
In a controller plugin I then want to get the whole of the response like so
$this->getResponse()->getBody()
This however only returns the output from the action, not the output from the layout too.
How can I get the whole output, layout and action together?
Thanks!
I believe that Zend_Layout operates at postDispatch() with a high stack index. So, to get the content, you might need to do your access later, at dispatchLoopShutdown().
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.