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. **/
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.
Let's say I have 2 controllers, content and news:
class ContentController extends Symfony\Bundle\FrameworkBundle\Controller\Controller {
public function indexAction() {}
}
and
class NewsController extends ContentController {}
If the view for the indexAction does not exist for the news controller (the indexAction is inherited from the parent class), I want Symfony to use the view of the Content controller (indexAction). How can I achieve this?
Symfony always tries to render the view News/index.html.php but if this view does not exist I would like that Symfony renders Content/index.html.php.
Is it possible to tell the Symfony render engine something like this: If there exists the file News/index.html.php take this one, otherwise take Content/index.html.php
I'm using the PHP template engine, not twig.
We are currently using the Zend Framework and there you can simply add a script (view) path as described here View overloading in Zend Framework
I hope I understand you correctly and this could fix you problem:
class ContentController extends Symfony\Bundle\FrameworkBundle\Controller\Controller
{
/**
* #Route("/", name="content_index")
*/
public function indexAction()
{
// render Content/index.html.php
}
}
class NewsController extends ContentController
{
/**
* #Route("/news", name="content_news_index")
*/
public function indexAction()
{
parent::indexAction();
// render News/index.html.php
}
}
You have to adjust the routes to your needs.
Additional approach as requested in the comments:
use Symfony\Component\HttpFoundation\Request;
class ContentController extends Symfony\Bundle\FrameworkBundle\Controller\Controller
{
/**
* #Route("/", name="content_index")
* #Route("/news", name="content_news_index")
*/
public function indexAction(Request $request)
{
$routeName = $request->get('_route');
if ($routeName === 'content_index') {
// render Content/index.html.php
} elseif ($routeName === 'content_news_index') {
// render News/index.html.php
}
}
}
I have an array public variable loaded identically in every controller class that I have. The array variable contains language file to be passed to the view file.
Sample:public $data; $this->data = array('lbl_first_name'=>$this->lang->line('lbl_first_name'));. As language data goes plenty, so as the content of the array that holds the language file does also. How would I able to put this variable to a library or as a helper then loads it something like $this->load->library('language_data') or $this->load->helper('language_data') in every controller file? not the array variable with lots of language data anymore to be loaded in each controller I have. Thanks a lot. Sample codes are shown below:
Controller 1:
class Courses extends CI_Controller {
public $data;
public function __construct(){
parent::__construct();
$this->data =array(
//language file for menu item
'dropdown'=>$this->lang->line('dropdown'),
'dropdownedit'=>$this->lang->line('dropdownedit'),
'home'=>$this->lang->line('home'),
'menu_desc'=>$this->lang->line('menu_desc'),
'login'=>$this->lang->line('login'),
'login_desc'=>$this->lang->line('login_desc'),
'teacher'=>$this->lang->line('teacher'),
'logout'=>$this->lang->line('logout'),
'course_occasion'=>$this->lang->line('course_occasion'),
'courses'=>$this->lang->line('courses'),
'student'=>$this->lang->line('student'),
'tennant'=>$this->lang->line('tennant'),
'messages'=>$this->lang->line('messages'),
'sent_messages'=>$this->lang->line('sent_messages'),
//language file for forms
'course_edit_form_desc'=>$this->lang->line('course_edit_form_desc'),
'course_reg_form_desc'=>$this->lang->line('course_reg_form_desc'),
'course_view_list'=>$this->lang->line('course_view_list'),
'view_course_available_list'=>$this->lang->line('view_course_available_list'),
'lbl_course_name'=>$this->lang->line('lbl_course_name'),
'lbl_course_desc'=>$this->lang->line('lbl_course_desc'),
'lbl_tennant_name'=>$this->lang->line('lbl_tennant_name'),
'lbl_public'=>$this->lang->line('lbl_public'),
'lbl_not_public'=>$this->lang->line('lbl_not_public')
);
}
}
Controller 2: (Same as controller 1)
class Occasions extends CI_Controller {
public $data;
public function __construct(){
parent::__construct();
$this->data =array(
//language file for menu item
'dropdown'=>$this->lang->line('dropdown'),
'dropdownedit'=>$this->lang->line('dropdownedit'),
'home'=>$this->lang->line('home'),
'menu_desc'=>$this->lang->line('menu_desc'),
'login'=>$this->lang->line('login'),
'login_desc'=>$this->lang->line('login_desc'),
'teacher'=>$this->lang->line('teacher'),
'logout'=>$this->lang->line('logout'),
'course_occasion'=>$this->lang->line('course_occasion'),
'courses'=>$this->lang->line('courses'),
'student'=>$this->lang->line('student'),
'tennant'=>$this->lang->line('tennant'),
'messages'=>$this->lang->line('messages'),
'sent_messages'=>$this->lang->line('sent_messages'),
//language file for forms
'course_edit_form_desc'=>$this->lang->line('course_edit_form_desc'),
'course_reg_form_desc'=>$this->lang->line('course_reg_form_desc'),
'course_view_list'=>$this->lang->line('course_view_list'),
'view_course_available_list'=>$this->lang->line('view_course_available_list'),
'lbl_course_name'=>$this->lang->line('lbl_course_name'),
'lbl_course_desc'=>$this->lang->line('lbl_course_desc'),
'lbl_tennant_name'=>$this->lang->line('lbl_tennant_name'),
'lbl_public'=>$this->lang->line('lbl_public'),
'lbl_not_public'=>$this->lang->line('lbl_not_public')
);
}
}
Desired output:
Controller 1 and Controller 2:
$this->load->library('language_array');
or
$this->load->helper('language_array');
Not too sure I understand you, but I think this is what you want:
Firstly create a library or helper function return the array of lang.
create a controller like:
class MY_Controller extends CI_Controller {
public $data;
public function __construct(){
parent::__construct();
$this->load->library('language_array');
}
}
So now you have a controller which loads you lib or helper item right?
Then class Occasions extends MY_Controller and class Courses extends MY_Controller, so anything that you want all your controllers to have you put in MY_Controller which all you other controllers inherit from.
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.
I want to create two parent controllers: one for admin and one for user site. They have to extend a regular Controller class but each of them has to do different things.
I wrote up an article showing how you do this.
http://philsturgeon.co.uk/news/2010/02/CodeIgniter-Base-Classes-Keeping-it-DRY
You need to create an __autoload() function in your config.php or directly include the base controller above the class definition.
This is pretty easy. Do the following:
Go to the following directory: your_ci_app/application/core/ and create a php file called MY_Controller.php (this file will be where your top parent classes will reside)
Open MY_Controller.php and add your multiple classes, like so:
class Admin_Parent extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function test() {
var_dump("from Admin_Parent");
}
}
class User_Parent extends CI_Controller {
public function __construct() {
parent::__construct();
}
public function test(){
var_dump("from User_Parent");
}
}
Create your children controllers under this directory your_ci_app/application/controllers/ . I will call it adminchild.php
Open adminchild.php and create your controller code, make sure to extend the name of the parent class, like so:
class Adminchild extends Admin_Parent {
function __construct() {
parent::__construct();
}
function test() {
parent::test();
}
}