I have an abstract base Controller class and all action controllers are derived from it.
Base Controller class at construction initializes View object. This View object is used by all action controllers. Each action controller have different dependencies (this is solved by using DI container).
The problem is that base Controller class also needs some dependencies (or parameters),
for example, path to view folder. And the question is - where and how to pass parameters to base Controller class?
$dic = new Dic();
// Register core objects: request, response, config, db, ...
class View
{
// Getters and setters
// Render method
}
abstract class Controller
{
private $view;
public function __construct()
{
$this->view = new View;
// FIXME: How / from where to get view path?
// $this->view->setPath();
}
public function getView()
{
return $this->view;
}
}
class Foo_Controller extends Controller
{
private $db;
public function __construct(Db $db)
{
$this->db = $db;
}
public function barAction()
{
$this->getView()->some_var = 'test';
}
}
require_once 'controllers/Foo_Controller.php';
// Creates object with dependencies which are required in __construct()
$ctrl = $dic->create('Foo_Controller');
$ctrl->barAction();
This is just a basic example. Why is the $view private? Is there a good reason?
class View {
protected $path;
protected $data = array();
function setPath($path = 'standard path') {
$this->path = $path;
}
function __set($key, $value) {
$this->data[$key] = $value;
}
function __get($key) {
if(array_key_exists($key, $this->data)) {
return $this->data[$key];
}
}
}
abstract class Controller {
private $view;
public function __construct($path)
{
$this->view = new View;
$this->view->setPath($path);
}
public function getView()
{
return $this->view;
}
}
class Foo_Controller extends Controller {
private $db;
public function __construct(Db $db, $path)
{
// call the parent constructor.
parent::__construct($path);
$this->db = $db;
}
public function barAction()
{
$this->getView()->some_var = 'test';
}
public function getAction() {
return $this->getView()->some_var;
}
}
class DB {
}
$con = new DB;
$ctrl = new Foo_Controller($con, 'main');
$ctrl->barAction();
print $ctrl->getAction();
Related
i have two class, one(controller class) extend from another, then in the controller class, I define a variable "load" (in the construct), but when i extend from another class i can't invoke this variable from the constructor, any ideas? (Apologies for my bad english).
Class Controller:
<?php
class Controller {
protected $load;
public function __construct() {
$this->load = new Loader();
if($_GET && isset($_GET['action']))
{
$action = $_GET['action'];
if(method_exists($this, $action))
$this->$action();
else
die('Method not found.');
} else {
if(method_exists($this, 'index'))
$this->index();
else
die('Index method not found.');
}
}
}
Class home ( Where does it extend):
<?php
class Home extends Controller
{
function __construct() {
parent::__construct();
$this->load->model("HomeModel");// this line doesn't work
}
public function index() {
$articles = new HomeModel();
$articles = $articles->getData();
$nombres = ['jona', 'juan', 'jose'];
$view = new Views('home/home', compact("nombres", "articles"));
}
}
Loader Class:
<?php
class Loader
{
function __construct() {
}
public function model($model) {
require('./models/'.$model.'.php');
}
}
The error "'HomeModel' not found" would lead me to believe that you are not requiring the file that contains the 'HomeModel' class in the 'Home' class file.
I'm working on forking an existing MVC PHP application and all normal page controllers are extended from controller.
class MyController extends Controller
The controller class is an abstract class with 2 magic methods, __set and __get and a constructor __construct
abstract class Controller {
protected $registry;
public function __construct($registry) {
$this->registry = $registry;
}
public function __get($key) {
return $this->registry->get($key);
}
public function __set($key, $value) {
$this->registry->set($key, $value);
}
}
I've searched all through the entire application and nowhere are __get or __set ever called manually. So I have to assume that these methods are indeed magical and are doing something with the registry that isn't available to see.
Dispatching is done through the Front class which already holds the registry as an object:
final class Front {
private $registry;
private $pre_action = array();
private $error;
public function __construct($registry) {
$this->registry = $registry;
}
public function addPreAction($pre_action) {
$this->pre_action[] = $pre_action;
}
public function dispatch($action, $error) {
$this->error = $error;
foreach ($this->pre_action as $pre_action):
$result = $this->execute($pre_action);
if ($result):
$action = $result;
break;
endif;
endforeach;
while ($action):
$action = $this->execute($action);
endwhile;
}
private function execute($action) {
$result = $action->execute($this->registry);
if (is_object($result)):
$action = $result;
elseif ($result === false):
$action = $this->error;
$this->error = '';
else:
$action = false;
endif;
return $action;
}
}
My thought was that replacing the abstract class Controller with an Interface would be a better solution, but I'm unsure about what these magic methods are actually doing.
How can I tell if I can/should make this change?
I try to inherit multiple classes from each other, but something wrong happens somewhere. The classes are the following:
Part of the MobilInterface class:
class MobileInterface
{
private $config;
private $errorData;
private $data;
private $output;
private $job;
public $dbLink;
public function __construct($config) {
$this->config = $config;
}
public function initialize($job) {
$this->dbLink = $this->createDbInstance($this->config);
require_once 'jobs/' . strtolower($this->config->joblist[$job]) .'.php';
$this->job = new $this->config->joblist[$job]($this);
}
public function run($params) {
$job = $this->job;
$this->data = $this->job->run($_GET);
}
}
Mobil Interface is the main interface, which calls the Kupon class based on a string in the $config. My problem is that i want more Kupon like classes and wanted to make a BaseJob class to be able to write each Job class without the constructor.
The problem is that the Kupon class can't see the $dbLink and the $config variables.
The BaseJob class:
<?php
class BaseJob
{
public $interface;
public $dbLink;
public $config;
public function __construct(MobileInterface $interface) {
$this->interface = $interface;
$this->config = $this->interface->get('config');
$this->dbLink = $this->interface->get('dbLink');
}
}
?>
And the Kupon class:
function __construct(){
parent::__construct(MobileInterface $interface);
}
}
?>
I have this code and i´m trying to use a object
<?php
class Controller {
public $_view;
public function __construct() {
$this->_view = new View();
return $this->_view;
}
}
class View {
public $_params = array ();
public function set_params($index_name,$valores) {
$this->_params[$index_name] = $valores;
}
public function get_param($index_name){
return $this->_params[$index_name];
}
}
?>
i would like to do this:
class Index extends Controller {
public function index() {
$model = Model::get_estancia();
$usuarios = $model->query("SELECT * FROM usuarios");
$this->_view->set_params(); // cant be used.
$this->load_view("index/index");
}
}
i would like to use the set_parms function.
but i can't see the View Function, then i can not use.
Can someone explain and advise me a good and safe way?
Correction from Phil: If a __construct() method isn't found, PHP will revert to legacy constructor syntax and check for a method with the same name as the object. In your case the method index() is being treated as the constructor, and is preventing the parent's constructor from loading the view object into the $_view property.
You can force a class to inherit a parent's constructor by defining __construct() in the child and calling the parent's constructor:
public function __construct() {
parent::_construct();
}
Here is the fixed code:
<?php
class Controller {
public $_view;
public function __construct() {
$this->_view = new View();
return $this->_view;
}
}
.
class View {
public $_params = array ();
public function set_params($index_name,$valores) {
$this->_params[$index_name] = $valores;
}
public function get_param($index_name){
return $this->_params[$index_name];
}
}
.
class Index extends Controller {
public function __construct() {
parent::__construct();
}
public function index() {
$model = Model::get_estancia();
$usuarios = $model->query("SELECT * FROM usuarios");
$this->_view->set_params(); // cant be used.
$this->load_view("index/index");
}
}
I wrote a class for module creating. That run correctly except that model object.
Model class :
class Model{
public static $db;
protected $_table_name;
public function __construct() {
self::$db =& DB::singleton();
}
public function get($rows="*",$where=null,$page_no=null,$limit=null,$order_by=null,$table_name=null){
if(!isset($table_name)||empty($table_name)){
self::$db->table=$this->_table_name;
}else{
self::$db->table=$table_name;
}
self::$db->rows = $rows;
self::$db->limit=$limit;
self::$db->where=$where;
self::$db->page_no=$page_no;
self::$db->order_by=$order_by;
return self::$db->read();
}
public function delete($id,$table){
self::$db->table = $table;
self::$db->where ="id='{$id}'";
self::$db->delete();
return 1;
}
public function drop_table($table){
self::$db->table=$table;
self::$db->drop_table();
return 1;
}
public function get_module_name(){
return $this->_table_name;
}
public function set_table($table_name){
$this->_table_name=$table_name;
}
}
Extended class :
class m_publication_categories extends model
{
protected $_table_name = 'publication_categories';
}
Controller :
class Controller{
public $db;
public $model;
public function __construct(){
core::$theme->setup();
$model_class_name = "m_".get_called_class();
$this->model=new $model_class_name();
}
public function listAction(){
$module_name = $this->model->get_module_name();
$module_model = new m_modules();
/**moduleinfo*/
$module = $module_model->get("*","table_name='{$module_name}'");
$module = $module[0];
$module_columns = $module_model->list_fields($module->id);
$data = $this->model->get();
print_r($data);die;
$this->assign('data',$data);
$this->assign('module_columns' , $module_columns);
$this->assign('module',$module);
$this->display('list_module_data','modules');
}
}
I want use model::get method from controller $this->model->get but that not work correctly. But if i print_r $this->model in controller , return result like that :
m_publication_categories Object ( [_table_name:protected] => publication_categories )
This means code in extends model class, but why not enter main model class ?
thanks.