I've created 2 controllers in my Yii application: FirstController.php and SecondController.php in default controller path.
FirstController.php:
<?php
class FirstController extends Controller {
public static function returnFunc() { return 'OK'; }
}
SecondController.php:
<?php
class SecondController extends Controller {
public function exampleFunc() {
$var = First::returnFunc();
}
}
When I try to execute exampleFunc() in SecondController, Yii throw the error:
YiiBase::include(FirstController.php) [<a href='function.YiiBase-include'>function.YiiBase-include</a>]: failed to open stream: No such file or directory
Calling FirstController::returnFunc() similarly don't work.
I'm newbee in OOP and Yii framework. What's the problem?
I've solved this problem. The autoloader doesn't load controllers.
It was in config/main.php:
'import' => array(
'application.models.*',
'application.components.*',
),
All work with this:
'import' => array(
'application.models.*',
'application.components.*',
'application.controllers.*',
),
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
class ServiceController extends Controller
{
public function actionIndex()
{
Yii::import('application.controllers.back.CservicesController');
$obj =new CservicesController(); // preparing object
echo $obj->test(); exit; // calling method of CservicesController
When you create a Yii project, each of your controllers extend the Controller class, and that class extends the built in Yii class CController.
This is nice because Controller is a class within your application (it can be found in the components folder).
If you want a method to be accessible by both of your controllers, put that method in the Controller class, and since they both extend it. They'll both have access. Just make sure to declare it either public or protected.
Related
I'm using the latest 'master' branch of CodeIgniter 4
I have a Library that I'm trying to load automatically. Effectively, I want to have have 'one' index.php (that has meta, the basic html structure, etc) through which I can load views via my 'Template' Library.
My Library file: (~/app/Libraries/Template.php)
//class Template extends CI_Controller
class Template {
/* This throws an error, but I will open up a separte thread for this
public function __construct() {
parent::__construct();
}
*/
public function render($view, $data = array()) {
$data['content_view'] = $view;
return view('layout/index', $data);
}
}
I also have a controller set up:
class Locations extends BaseController
{
public function index()
{
return $this->template->render("locations/index", $view_data);
//return view('locations/index');
}
//--------------------------------------------------------------------
}
In ~/app/Config/ I added my Library
$classmap = [
'Template' => APPPATH .'/Libraries/Template.php'
];
I'm getting the following error:
Call to a member function render() on null
What am I doing wrong that's causing my library not to load?
In CI4 the BaseController is where you create things that you want to be used by multiple other controllers. Creating classes that extend others is so very easy in CI4.
It seems to me that the only thing you are missing is creating the Template class. (There are a couple of other minor things too, but who am I to point fingers?)
One big item that might be just that you don't show it even though you are doing it. That is using namespace and use directives. They are must-do items for CI 4.
Because of where you have put your files you don't need and should remove the following. See how I've used use which imports namespace already known to the autoloader.
$classmap = [
'Template' => APPPATH .'/Libraries/Template.php'
];
First, the BaseController
/app/Controllers/BaseController.php
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Libraries\Template;
class BaseController extends Controller
{
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [];
protected $template;
/**
* Constructor.
*/
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->template = new Template();
}
}
/app/Controllers/Locations.php
class Locations extends BaseController
{
public function index()
{
// set $viewData somehow
$viewData['someVar'] = "By Magic!";
return $this->template->render("locations/index", $viewData);
}
}
/app/Libraries/Template.php
<?php namespace App\Libraries;
class Template
{
public function render($view, $data = [])
{
return view($view, $data);
}
}
/app/Views/locations/index.php
This works as if... <strong><?= $someVar; ?></strong>
I know I haven't created exactly what you want to do. But the above should get you where you want to go. I hope so anyway.
It's tricky at first.
But I managed to run it successfully
Make sure you give it proper namespace
And then just "use" in your controller Location.
I dont change anything on Autoload.php.
app/Libraries/Template.php
<?php
namespace App\Libraries;
class Template {
public static function render($param) {
return 'Hello '.ucwords($param);
}
}
The proper way to call is put use App\Libraries\Template just before class Location extends BaseController
app/Controllers/Locations.php
<?php
namespace App\Controllers;
use App\Libraries\Template;
class Locations extends BaseController {
public function index() {
$template = new Template();
$renderedStuff = $template->render('World!');
echo $renderedStuff;
}
}
How does this work?
Notice in Template.php there is a namespace namespace App\Libraries;, so CI4 will automatically load that library properly also recognize the "Template" class. That is proper way to create CI4 libraries in my point of view.
How do we use that library?
Look at my example of Locations.php and then see this code use App\Libraries\Template;, that's how we call that libraries.
How do we call the function?
Look inside the index() function, here we call class Template using var $template = new Template();.
Then we call render() function in Template library with $template->render('World!');.
Just as simple as that.
I hope thats help, lemme know if it doesnt works. :)
Just a little hint, as my eye was hooked by the CI_Controller part.
You seems to use CI3 syntax within CI4, at least about loading the view, which translates to just:
$data = [
'title' => 'Some title',
];
echo view('news_template', $data);
See the CI3doc vs the CI4doc , the "static page" tutorial.
I have my normal mvc directory's at codeigniter like:
Models
Views
Controllers
But I use the wiredesigz "plugin" for hmvc support, so I have this structure:
Models
Views
Controllers
Modules
TestModule
Models
Views
Controllers
I have this code at my root controllers folder:
class Core_Test_Controller extends MX_controller
{
public function __construct()
{
parent::__construct();
}
public function getText() {
return "hi";
}
}
And this at the /Modules/TestModule/Controllers:
class InsertController extends MX_Controller
{
public function __construct(){
parent::__construct();
}
function testIt{
$coreTestController = new $this->Core_Test_Controller();
$text = $coreTestController->getText();
print_r($text);
}
}
But I get the error that class Core_Test_Controller is not found. Why can't I acces that controller from another controller? Is this even possible?
Fixed it:
Modules::load('../Core_Test_Controller/')->getText();
First off lower case for folder names. Only first letter must be upper case for controller names and models etc UCFIRST as explained here http://www.codeigniter.com/user_guide/general/styleguide.html#file-naming HMVC wont pick up CI_Controllers controllers only MX_Controllers
class Core_test_controller extends MX_controller {...}
class Insertcontroller extends MX_Controller {...}
As said here
<?php
/** module and controller names are different, you must include the method name also, including 'index' **/
modules::run('module/controller/method', $params, $...);
/** module and controller names are the same but the method is not 'index' **/
modules::run('module/method', $params, $...);
/** module and controller names are the same and the method is 'index' **/
modules::run('module', $params, $...);
/** Parameters are optional, You may pass any number of parameters. **/
I am trying to get my Facade class to work, however it seems Laravel is calling the method on my Facade class instead of calling it on my root class. So I get method undifined error. When I create the the feed class directly from the binding ( App::make('feed')->addArticle();) it works. So I think there is soemthing wrogn with my Facade. Any ideas? Thank in advance.
Controller
class RssController extends BaseController
{
public function getArticles() {
Feed::addArticle();
}
}
ServiceProvider
use Illuminate\Support\ServiceProvider;
class FeedServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('feed', function()
{
return new Feed;
});
}
}
Facade class
use Illuminate\Support\Facades\Facade;
class FeedFacade extends Facade {
protected static function getFacadeAccessor()
{
return 'feed';
}
}
Root Class
class Feed {
//vars
public function __construct()
{
}
public function make() {
return new Feed();
}
public function addArticle() {
return '#addArticle';
}
The problem seems to be you want both your Laravel Facade (Feed::), and the implementation class of your service provider (class Feed) to have the same name. Facades work because in app/config/app.php there's an alias section
'aliases' => array(
'App' => 'Illuminate\Support\Facades\App',
'Artisan' => 'Illuminate\Support\Facades\Artisan',
'Auth' => 'Illuminate\Support\Facades\Auth',
'Blade' => 'Illuminate\Support\Facades\Blade',
This aliasing means whenever you use, say, the App facade
`App::someMethod`
Laravel actually invokes the getFacadeAccessor on Illuminate\Support\Facades\App. There's no global class App in the system. If there were it would cause a similar problem with the facade.
Get an alias for Feed=>Illuminate\Support\Facades\Facade\FeedFacade into your system, and get your implementation class Feed out of the global namespace (moving the file to an appropriate place)
<?php
namespace My\Namespace;
class Feed
{
}
...
return new \My\Namespace\Feed;
and you should be all set.
Also, at the risk of confusing you, you don't need to drop your own classes in the Illuminate\Etc\... namespace, and you should probably put them in your own unless you're trying to get the core Laravel team to accept your classes as the official feed service.
I have a base controller as follows
<?php
use Phalcon\Mvc\Controller;
class ControllerBase extends Controller {
public function initialize() {
}
// wrapper function for debug purposes.
public function pr($data = null) {
echo '<pre>';
print_r($data);
echo '</pre>';
}
}
and a users controller as follows
<?php
use Phalcon\Mvc\Model\Criteria;
use Phalcon\Paginator\Adapter\Model as Paginator;
use Phalcon\Mvc\View;
class UsersController extends ControllerBase {
public function initialize() {
// initialize parent, here ControllerBase.
parent::initialize();
}
public function loginAction() {
// disable the main layout.
$this->view->disableLevel(View::LEVEL_MAIN_LAYOUT);
// disable the controller layout.
$this->view->disableLevel(View::LEVEL_LAYOUT);
}
.
.
.
.
other functions...
}
i was wondering if i could call all the required phalcon classes in base controller and extend then to all the child classes so that i dont need to call them individually on each controller.
in otherwords, can i add the below code
use Phalcon\Mvc\Model\Criteria;
use Phalcon\Paginator\Adapter\Model as Paginator;
use Phalcon\Mvc\View;
only in the base controller and acces them in other controllers. I tried putting them base controller but it gave error : Class not found.
Is this the right way or is there something wrong in my approach...please help.
If I understand your question correctly the answer is NO.
Namespaces are language feature and works this way. The use Phalcon\Mvc\Model\Criteria only declares that you'll use Criteria class from Phalcon\Mvc\Model\ namespace. So in your code you can write new Criteria() to create object instead of using its' full name new \Phalcon\Mvc\Model\Criteria().
You must declare each class in every file which instantiates object of that class so autoloader will know in which file given class exists.
First I created a project using Zend_Tool. Then created a controller AuthenticationController in default module.
Created Form in projectfolder/application/forms/Login.php
class Forms_Login extends Zend_Form {
public function _construct() {
// add elements
}
}
Accessing Form in myproject/application/controllers/AuthenticationController.php
public function loginAction() {
$this->view->form = new Form_Login();
}
I am getting following error:
Fatal error: Class 'Application_Forms_Login' not found in /var/www/student/application/controllers/AuthenticationController.php on line 19
How can I access it with same form class name without including this file in AuthenticationController??
May be I have to tell zend in Bootstrap.php about this but I wan unable to find a sample code.
Thanks
you should declare them in your bootstrap.php file like so:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAutoload()
{
$autoLoader=Zend_Loader_Autoloader::getInstance();
$resourceLoader=new Zend_Loader_Autoloader_Resource(array(
'basePath'=>APPLICATION_PATH,
'namespace'=>'',
'resourceTypes'=>array(
'form'=>array(
'path'=>'forms/',
'namespace'=>'Forms_'
)
)
));
$autoLoader->pushAutoloader($resourceLoader);
}
}