I've developed My Own MVC Framework using php.
I call view files in controller like:
include('../view/home.php');
but I want to use it like:
$this->view('home');
How can I define common function for that where I can just pass view name i.e home only and it will do include view file without passing the full file path?
No one could answer you without seeing your codes really. But this should be my approach.
You should have a class that all your controllers extend. Lets say that you have class Controllers and all your controllers extend it.
Then you may have a method inside the class named view($view_name).
public function view($view_name){
include $some_path . '/' . $view_name . '.php';
}
then whenever you call view by $this->view it will include the view if it exists.
This is not the best approach and I did not test the code. I just wanted to show you the path
I don't know Your MVC file/directory/namespace and etc structure.
But for beginner who tries to learn MVC and Frameworks by "reinventing wheel" (: I can give such example:
1) Create common abstract controller class in app/controllers folder:
namespace App\Controllers;
abstract class Controller {
public function view($name) {
include(__DIR__.'/../views/'.$name.'.php';
}
}
2) Create Your own controller i.e. PagesController and use it:
namespace App\Controllers;
class PagesController extends Controller {
public function home() {
$this->view('home');
}
}
p.s. You may omit namespace-ing, abstract word depending on autoloader logic
Related
Hi I have a file called payment.php it contains some functions related to payments and some multiple classess. So I want to include that file in my symfony2 Controller to access its all methods and classless. I am trying it as follows:
//File location is in src/AppBundle/Controller/payment.php
namespace AppBundle\Controller;
require_once __DIR__.'/./payment.php';
//My controller
class ApiServicesController extends Controller
{
$this->payment(array('txnId'=>1112548));
}
But I am not able to access the file and its methods.
I am using this approach because keeping it in /vendor directory it also not able to access because this file contains multiple classless in same files.
Please advice me how can I access this file in my controller.
thanks in advance
If paymant.php have classes you need to make instance of that class to call method from it, that's like basic OOP stuff.
class ApiServicesController extends Controller
{
$this->payment(array('txnId'=>1112548));
}
First of all, where is the method in this controller where you want to call your method? Then, why you are calling payment on $this if it comes from diffrent class. It should be something like this
class ApiServicesController extends Controller
{
public function indexAction()
{
$somePaymentClass = new SomePaymantClass(); //whatever class you want from payment.php
$somePaymentClass->payment(array('txnId'=>1112548));
}
}
But iI strongly recommend to use it as a service and put it in some autoloader namespace.
You have to make a Payment class as a service and then you can use all functions of Payment class in controller. Please refer this document.
http://symfony.com/doc/current/service_container.html
My question is: If we create any object of one class, that class file should be included in our file .In zend frame work. How is this possible without including that file?
example:
If I have indexcontroller in controller folder and Article model with name Article.php in model folder then how is articale.php available in index controller?
class IndexController extends Zend_Controller_Action {
private $_model;
public function indexAction() {
$model=new Model_Article();/*how it is possible where and when this file include in index controller */
}
}
?>
sorry for my poor English
assuming you are using zf1 version not zf2 , you can do it with,
$model = new Application_Model_Article();
where article.php is under model folder.
you can call this in any of the controller and any of the action.
then you can use for example $model->fetchAll(); to Invoke any function of your model..
Zend Autoloader is responsible for automatic class loading. It uses __autoload. You can read more about it here and here.
All I'm trying to do is something fairly simple :
Create a class (let's say brandNewClass - NOT MY_Controller) which extends CI_Controller
Create other controllers which extend brandNewClass
E.g.
class brandNewClass extends CI_Controller {
public function index()
{
}
public function info()
{
}
}
used like (in a file under /controllers) :
<?php
class newController extends brandNewClass
{
}
?>
The thing is, although it works when I'm copying the file under /application/core and naming it as MY_Controller, when I change the name to something more... self-explanatory, it doesn't.
Fatal error: Class 'brandNewClass' not found in .... on line ..
I've even tried using the __autoload function mentioned here, but without any luck.
Any ideas?
Have a look at this excellent tutorial - I hope it helps
http://codeigniter.tv/a-10/Extending-the-core-MY_Controller-and-beyond
The autoloader doesn't automaticly include other controllers. you will have to include it manually like this:
if (!defined('BASEPATH'))exit('No direct script access allowed');
include_once(APPPATH . 'controllers/brandnewclass.php');
If you want to create a custom base controller and make other controllers extend there, you can do it in following ways:
Create MY_Controller extending CI_Controller in application/core/ folder and make other controllers extend MY_Controller as MY_Controller will be autoloaded from core (This I guess you already know but want other alternatives.
Create MY_Controller in application/core/. Then create other level of Controllers that can primarily be Admin_Controller and Frontend_Controller. Now, one of these controllers will make base for your actual used controllers.
e.g. in application/core/MY_Controller.php
class MY_Controller extends CI_Controller {
public function __construct(){
parent::__construct();
}
}
Then Admin and Frontend controllers will be created in application/libraries/ and will extend MY_Controller like
class Admin_Controller extends MY_Controller {
public function __construct(){
parent::__construct();
}
}
Now, Any controller can extend one of these 2 controllers but for doing that you will have to autoload them. For autoloading in this case there can be a confusion because setting autoload['libraries'] in config/autoload.php will not work . That autoload works inside a controller but here we need to autoload before that i.e. in the class declaration. Will need to set this code in config/config.php
function __autoload($class)
{
$path = array('libraries');
if(strpos($class, 'CI_') !== 0) {
foreach($path as $dir) {
$file = APPPATH.$dir.'/'.strtolower($class).'.php';
if (file_exists($file) && is_file($file))
#include_once($file);
}
}
}
Now you can create your own controller
class newController extends Admin_Controller
{
}
This is the most suggested method making your structure quite clean and effective. May take some effort in understanding for the first time but is definitely worth it.
Third method is just a tweak of the second one, just based on the condition you mentioned of not using MY_Controller
You can make Admin_Controller or Frontend_Controller extend CI_Controller directly and not extend MY_Controller
That may just lead to some duplicity of code in both these controllers if that may be the case
http://philsturgeon.co.uk/blog/2010/02/CodeIgniter-base-Classes-Keeping-it-DRY
I suspect you're trying something similar?
There's an autoload function that you can add to the config file so that you needen't require_once() the class all the time.
You should declare the class as abstract, since it shouldn't be instantiated directly.
You'll need to modify the CodeIgniter autoloader configuration file and add your class to it, or change the actual autoloader.
You really should consider not using CodeIgniter :)
In my CI system\libraries directory I have a new class named DD_Controller.php. This file looks like this:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class DD_Controller extends Controller
{
protected $ddauthentication;
function __construct()
{
parent::Controller();
$this->ddauthentication = "Authenticated";
}
}
?>
My application controller is defined like this:
class Inquiry extends DD_Controller
{...}
The Inquiry class works fine when I extend Controller, but I get a
Fatal error: Class 'DD_Controller' not
found in
C:\development\localhost\applications\inquiry\controllers\inquiry.php
on line 4
When I extend DD_Controller. In the config file I have the prefix defined as such:
$config['subclass_prefix'] = 'DD_';
Any idea of what I'm missing?
TIA
This is a better approach. 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 this the file you just created 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();
}
}
DD_Controller.php should be in /system/application/libraries/
If you're using the same CI for multiple apps, and you want them all to be able to extends their controllers to your custom one then you can extend the base Controller class in the same file.
In system/libraries/Controller.php below the Controller class:
class Mega_Controller extends Controller {
function Mega_Controller()
{
parent::Controller();
// anything you want to do in every controller, ye shall perform here.
}
}
Then you'll be able to do this in your app controllers:
class Home extends Mega_Controller {
....
Since the extended controller class you created will be available. I think this is better then overwriting the base controller, but that would work as well.
I recommend to avoid "cracking" CodeIgniter core files.
Better use its native extending possibilities and try to fit into them.
The same rule I would recommend for any PHP library / CMS.
This rule has few reasons:
- ability to quiclky upgrade without takint into account thousands of notes where and how was cracked in core files;
- portability;
- possibility to share your code - eg, this will be usable by both you and your friends in case of need, and it will help them to keep their library up to date, the same as you.
In other words, this is much more professional and it pays to you in the future by usability, portability and by update application possibility.
Regarding your personal question...
As for me, there is nothing bad to create your own library with everything you need to extend native CodeIgniter Controller, then load this library in Controller's constructor and you are done. The only thing to make better usability is to give short name to your library.
This way you can even divide what you need in different pieces and put into separate libraries:
WebFeatures
AdminFeatures
etc.
Then you just load needed libraries in your controller's constructor and you are done.
P.S. I know that proposed way does not fit into "right" OOP concept, but in the same time you must never forget about the integrity of the libraries used.
Everything above is just one more view of mine 7-years experience in professional web development, so I hope it will be helpful if not to follow, then at least to take into account.
Regards,
Anton
I'm trying to extend my controllers with a global base controller as such:
class BaseController extends Zend_Controller_Action {
// common controller actions
public function listAction() {
// do stuff
}
}
class IndexController extends BaseController {
// index controller specific actions
}
class LoginController extends BaseController {
// login controller specific actions
}
But I get this error:
PHP Fatal error: Class 'BaseController' not found in /var/www/Zend/project/application/controllers/IndexController.php on line 3
Any ideas on how to get Zend to "see" this controller?
Autoloader
Setup the autoloader and register your library which should be besides the Zend library with the autoloader like so (in your bootstrap.php after setting the include path):
//AutoLoad loads classes automatically if they are used
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$loader->registerNamespace('Mylibrary_');
Zend naming conventions
Then you should rename your BaseController as follows
/Zend (folder)
/Mylibrary (folder)
/Controller (folder)
Action.php <-- this is your basecontroller file
which contains:
class Mylibrary_Controller_Action extends Zend_Controller_Action
{
}
and your normal controllers in the controller folder:
class IndexController extends Mylibrary_Controller_Action
{
}
so basically when you want to extend the framework you keep a parallel structure in your own library.
I would separate it into your own library, i.e. create the file library/YourApp/Controller/Action.php, and consequently name it YourApp_Controller_Action extends Zend_Controller_Action. From there you could place controllers where they should be and let them extend YourApp_Controller_Action in favor of Zend_Controller_Action.
To find the file you should rely on the autoloader to look not just inside of library/Zend, but also in library/YourApp. I.e. look for the set_include_path in your bootstrap.
With this technique you should keep in mind that your custom "basecontroller" might get bloated with methods that not all of your controllers needs to inherit.
the quick solution that does not take advantage of the autoloader functionality is to
require_once '/path/to/BaseController.php' in the index-controller file.
If you have set-up autocontroller, then it can not find it, so you should consider checking what's wrong. Try the previous approach and inform on results.
Even more quicker solution (and conceptually more correct) is NOT to create base controllers at all:)
You have common action? Use action helpers. You have some functionality that must be autorun? Use controller plugins.
By design ZF controllers were made as flexible as possible, and limiting yourself by inheritance (and coupling it brings) is just not the best possible strategy.