I have a simple php code and I want to split it into model,view,helper. Model should access some methods from helper class and helper class should access some methods from model class.
I am not sure if the below pattern is correct. I guess it is not because in this example model,view,helper will be initialized multiple times. Which is the most simple way to accomplish something like I am trying to do with the below code?
lib/main.php
require_once('lib/model.php');
require_once('lib/helper.php');
require_once('lib/view.php');
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'show';
switch($action){
case "show":
$class->showAction();
break;
case "another":
$class->anotherAction();
break;
}
class main extends abstract{
public function showAction(){
if($this->helper->getParam('browse')){
//something
}else{
$profiles= $this->model->getProfiles();
}
echo $this->view->toHtml($profiles);
}
}
lib/abstract.php
class abstract{
public function __construct(){
$this->model = new model();
$this->view = new view();
$this->helper = new helper();
}
}
lib/model.php
class model extends abstract{
public function getProfiles(){
if($this->helper->someMethod(){
//some code
}
//some code
return $profiles;
}
}
lib/helper.php
class helper extends abstract{
public function someHelperMethod(){
if($this->model->someAnotherMethod(){
//some code
}
//some code
return $profiles;
}
}
First problem is that you are nesting your classes like russian dolls. You shouldn't have your Abstract class both contain model/view/helper, and be the parent of model/view/helper.
I'd caution against using extension just to ensure a class is in-scope.
Generally you can think of it this way: use extension when your class has shared behaviors or properties as it's parent, but it either needs additional functionality, or modifications to existing functionality.
The "abstract" class you defined shares no attributes or methods between Model/View/Helper, so Model/View/Helper should not probably extend from it.
If however you want a "container" class that contains instances of each of these class types, just make it a standalone class, don't extend it, for example:
class Container{
public $model;
public $view;
public $helper;
public function __construct(){
$this->model = new model();
$this->view = new view();
$this->helper = new helper();
}
public function showAction(){
if($this->helper->getParam('browse')){
//something
}else{
$profiles= $this->model->getProfiles();
}
echo $this->view->toHtml($profiles);
}
Then instantiate it only once at the start someplace:
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'show';
$class = new Container();
Then, if you want to call something from Model inside Helper, this can be done a number of ways.
One option, pass a reference to this class and keep it inside Helper:
// Inside Container
public function __construct(){
$this->model = new model();
$this->view = new view();
$this->helper = new helper($model);
}
The Helper class would look like:
class Helper{
protected $model;
public function __construct($model){
$this->model = $model;
}
public function someHelperMethod(){
if($this->model->someAnotherMethod()){
//some code
}
//some code
return $profiles;
}
}
Related
i have multiple controller like registerController, loginController, boardController
and those controllers have same dependency of authentication.
in code
$registerController = new Register($authentication);
$loginController = new Login($authentication);
$shopController = new Shop();
$boardController = new Board($authentication);
so im trying to make parent class for those contorllers that named BaseController.
so child Controllers can inherite same authentication instance.
class BaseController {
public $authentication;
public function __construct($authentication) {
$this->authentication = $authentication;
}
}
one of my ChildController looks like this
class Shop extends BaseController{
public function __construct() {}
public function checkParentAuth(){
var_dump($this->authentication); // it shows NULL
}
}
i wish the code look like this
new BaseController($authentication);
$registerController = new Register();
$loginController = new Login();
$shopController = new Shop();
$boardController = new Board();
what should i do for this?
i thought it will surely works...
It looks like you're missing call the parent contructor, which will run all stuff necessary to activate and fill values the properties/variables
class Orders extends Site_Controller
{
public function __construct()
{
//first, call the parent constructor
parent::__construct();
...
//your code goes here.
}
}
I am new in learning MVC, I want to use private Model object stored inside View from outside class, like below example:
class Model{
private $data
}
class View{
private $model
public function __construct($model) {
$this->model = $model;
}
}
// outside
$m = New Model;
$v = New View($m);
echo $v->m->data; // How to get it
i know setter/getter method, but it can can much more bigger MVC code.please help.
You would probably want to access the view from within the controller like this:
class Controller
{
public function __construct($model, $view)
{
$this->model = $model;
$this->view = $view;
}
public function show()
{
return $this->view->render($this->model->getData());
}
}
$controller = new Controller();
$controller->show();
You want the controller to receive all of the dependencies that it has ideally in the constructor. That way it doesn't need to search for them. This is inversion of control or DI (dependency injection).
I found something about this error but I think this is little bit different. I defined a public variable.
Class Controller{
public $model;
And I'm trying add extra word(model) between $model_name and $this.
public function call_model($model_name){
$this->model->$model_name = new $model_class;
What is the solution?
EDIT:
Warning: Creating default object from empty value in C:\xampp\htdocs\alisveris\project_library\Controller.php on line 16
You can create static factory method to create different models like this:
abstract class Model {
static function CallModel($name) {
switch ( $name ) {
case 'Naomi': return new NaomiCampbell();
case 'Anja': return new AnjaRubik();
default: return new $name;
}
}
}
class NaomiCampell extends Model {}
class AnjaRubik extends Model {}
Then use:
$MyModel = Model::CallModel($name);
You can do it by assigning $model variable to $this
class Db
{
public function great()
{
echo 'great';
}
}
class Controller{
public $model;
public function __construct()
{
$this->model = $this;
$model_name = 'Db';
$this->model->$model_name = new $model_name;
}
}
$cc = new Controller();
echo $cc->model->Db->great();
Output
great
I have a hard time figuring out how to add a variable value to an instantiated class in php,
I've been looking at the reflectionClass and tried to return an assigned variable, and now I'm ended up with a getter setter.
I would really appreciate some help, here's an example of my code:
class controller
{
public $models;
private $load;
public function __construct()
{
$this->load = new loader();
}
public function action_being_run()
{
$this->load->set_model('model_name');
}
}
class loader
{
public function set_model($name)
{
{controller_class}->models[$name] = new model();
}
}
The controller class is instantiated without assigning it to a variable, but just:
new controller();
And then the action is executed from within the controller class.
You could pass a reference to $this into set_model()
class controller
{
public $models;
private $load;
public function __construct()
{
$this->load = new loader();
}
public function action_being_run()
{
$this->load->set_model('model_name', $this);
}
}
class loader
{
public function set_model($name, &$this)
{
{controller_class}->models[$name] = new model();
}
}
You also need to change public $model to public $models. There are probably other ways to achieve what you want, by either extending a class or just using magic methods to access the model.
Like this:
class tester{
public function lame(){
return 'super lame';
}
}
function after(){
return 'after function';
}
$tst = new tester; $tst->afterVar = 'anything'; $tst->afterFun = 'after';
echo $wh->afterVar;
echo $wh->afterFun();
I've got to implement a database connection pattern. I created two classes:
ConnectionFactory
MySQLService
ConnectionFactory:
<?php
class ConnectionFactory {
protected static $connection;
public function getConnection() {
if (!self::$connection) {
self::$connection = new PDO('mysql:host=localhost;dbname=sapienter', "root", "admin");
}
return self::$connection;
}
}
?>
MySQLService:
<?php
class MySQLService {
protected $connectionFactory;
public function __construct(ConnectionFactory $factory) {
$this->connectionFactory = $factory;
}
public function listItemsForSharerSQL() {
$conn = $this->connectionFactory->getConnection();
$items = ...
return $items;
}
}
?>
I call these methods in my controller ItemController:
<?php
require_once ROOT_DIR . "/models/Item.php";
require_once ROOT_DIR . "/ConnectionFactory.php";
require_once ROOT_DIR . "/MySQLService.php";
class ItemController {
private $data;
public function listItemsForSharer() {
$connFactory = new ConnectionFactory();
$service = new MySQLService($connFactory);
$items = $service->listItemsForSharerSQL();
$this->data = ['items' => $items];
return 'itemslistforsharer-view';
}
}
?>
I don't like the fact that I've got to instantiate a new ConnectionFactory in my Controller. Is it a mistake? Should I change my code design?
It is mistake that you are using a Database in a Controller at all. If talking about a Controller from the MVC Architecture pattern, then its Models job to interact with the database. There should be only instances of the Models in the controllers, but not instances of the Database.
Basically in the modern MVC frameworks that Models are extending the base Model class, which has the instantiation of the database.
As I understand, MySQLService is something like a model since you are returning some items, it seems like you are doing DB operation and want to handle it from a controller. Instead of every model having its own constructor, you should use a base class. I would suggest something like:
class Model {
protected function getAdapter() {
$connection = new ConnectionFactory();
return $connection->getConnection();
}
}
class MySQLService extends Model {
public function listItemsForSharerSQL() {
$this->getAdapter();
$items = ...
return $items;
}
}
So now your controller will only need
$service = new MySQLService();
Ofcourse you base class can have the getAdapter() method as a constructor, without any params, so you won't need to pass anything to the MySQLService and won't need to call getAdapther() in each method of MySQLService. Depends on your needs.