I'm only interested in handling GET or POST requests, so I designed this abstract class to determine which request has been made and to subsequently call the appropriate function. I would really appreciate feedback on this. Thanks!
PS I think this should be a community wiki, but I'm not sure how to set it as that.
abstract class AHttpRequestHandler
{
public function handleRequest()
{
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$this->handlePostRequest();
} else if($_SERVER['REQUEST_METHOD'] == 'GET') {
$this->handleGetRequest();
} else {
$this->handleIllegalRequest();
}
}
abstract protected function handleGetRequest();
abstract protected function handlePostRequest();
protected function handleIllegalRequest()
{
throw new Exception('Illegal request detected in HttpRequestHandler::handleIllegalRequest().');
}
}
In response to comments:
I will only be handling one or the other (GET or POST), never both at the same time.
Either an HTML form will be submitted via POST, or a redirect will be made with a query string, which will be a GET request. I am not familiar with how a mixed request could be made (both GET and POST), but since this is a personal project I have control over whether it happens or not.
I use the AHttpRequestHandler class (above) by implementing the handleGetRequest() and handlePostRequest() methods in a sub-class, which is and abstract controller, AController. Then, for each page of my CMS, I create a sub-class of AController, such as ImageUpload or ImageDetailsEditor. I can provide more details if it will help.
Here are the AController, Controller, and View classes:
AController
abstract class AController extends AHttpRequestHandler
{
protected $view;
public function __construct()
{
$this->handleRequest();
}
protected function handleGetRequest()
{
throw new Exception('handleGetRequest not yet implemented.');
}
protected function handlePostRequest()
{
throw new Exception('handlePostRequest not yet implemented.');
}
abstract protected function initView();
}
Controller
class Controller extends AController
{
protected $content;
public function __construct()
{
$this->view = new View();
parent::__construct();
}
protected function handleGetRequest()
{
$this->content = 'GET Request';
$this->initView();
}
protected function handlePostRequest()
{
$this->content = 'POST Request';
$this->initView();
}
protected function initView()
{
$this->view->content = $this->content;
$this->view->display();
}
}
View
//An over-simplified view for example use only
class View
{
public $content;
public function display()
{
echo "<p>$this->content</p>";
}
}
The actual use:
require_once 'Controller.php';
$controller = new Controller();
First of all you can make a GET request and a POST request in the same time. Think of a form that you post but the url has some variables in the query ( get ).
1.I don't understand the need for such a class but the first thing you could do is make two separate classes for post and get that extend the AHttpRequestHandler class. That way you only need an abstract function handleRequest that you will implement in the child classes.
2.You should apply "Intention Revealing Names". Your class should be RequestHandler and your methods should not contain Request in them. You know that from the class name.
3.Think about this: you might need to handle the post request in one controller. So you will have to add the second abstract method each time just to respect the abstract class.
4.You should not make circular calls between classes ( The Hollywood principle ). handleRequest is called from the child class, and then the parent calls handleGetRequest or handlePostRequest from the child.
Like I said, you are the developer, you know each controller what will use:POST or GET ( what about COOKIEs? ), so you can handle them at controller level without the need to extra classes just for the sake of it.
see ref
see ref
see ref
see ref
And the Controller should receive a request (command), not extend the request to keep things apart. Have no catch phrase for that, perhaps seperation of concerns. That's an extension to 1. above but only if you really need a request object.
Having an abstract class for requests is a good idea and it is there in all frameworks. But I dont think its good to extend this class by all controllers. A better solution will be to separate this to two, an abstract request class and base controller class. In request class you can have methods to identify whether it is a get request or post request, like
class Request{
public function isPost() {
return ($_SERVER['REQUEST_METHOD'] == 'POST');
}
public function isGet() {
return ($_SERVER['REQUEST_METHOD'] == 'GET');
}
}
Also we will have a base controller class with at least the following options
class Controller
{
public $request;
public function __construct() {
$this->setRequest(new Request());
}
public function setRequest(Request $request) {
$this->request = $request;
}
}
All our client controllers will extend the base controller as usual. The advantage of this method is client controllers will have the freedom to determine the request type. if they want to make use of GET and POST request at a time, that also will be possible. The above given is of course an incomplete one. You need to add more methods to the base classes or not is your choice.
Related
Lets say I am building an OOP-based user authentication system, and I would like to incorporate the following principles: Direct Injection, Inheritance, Encapsulation, Polymorphism and the Single Responsibility Principle.
My background in programming is has always relied on procedural programming, and thus, am finding it difficult to really put these practices into correct use.
Assume I have these classes:
class Config
{
public function set($key, $value);
public function get($key, $default = null);
}
class User
{
public function __construct(PDO $dbh, $id = null);
public function setProfile(Profile $profile);
}
class Auth
{
public function __construct(Config $config);
public function login($username, $password, $keepLoggedIn = true);
public function isLoggedIn();
public function getLoggedInUser();
public function logout();
public function register(array $data);
}
class Session
{
public function start($sessionName = null);
public function write($key, $value);
public function read($key, $default = null);
}
class Profile
{
public function setAddress(Address $address);
public function setName($name);
public function setDOB(DateTime $date);
public function getAge();
}
class Validator
{
public function validate($input);
}
I have intentionally left off the function bodies to keep things simple.
To the best of my knowledge, I believe I'm using the principles correctly. However, I am still unclear as to how you would connect classes like: the Validator to the User model, the User model to the Auth and the Session to the Auth class. All of which depend on each other.
You are on the right track. The way these classes connect to each other is called extending. I tend to go towards an MVC setup, meaning Model, View, Controller.
Your logic goes into the controller, all your DB queries and concrete back end methods go in the model. The controller receives requests and returns responses. It's the middleman. It talks to the back end after a request has been made to it, and feeds the front in via response.
So you have a core controller (keep it bare minimal), then each class you make extends the core controller. So your controller is where you tie all this together.
<?php
//your main core controller, where you load all these things you need avilable, so long as this class is extended
class CoreController {
public $auth
public $session;
public $view;
function construct__ ()
{
$this->auth = instantiateAuthClassHere();
$this->session = instantiateSessionClassHere();
$this->view = instantiateViewClassHere();
}
public function anotherHelperForSomething(){
//helper stuff for this method
}
}
//index, page, or content controller, depending on how many you need, i.e. if you want a controller for each page, thats fine, e.g indexController, etc..
//this is the middle man, has logic, receives requst, returns response to view.
class Controller extends CoreController {
public function index (){
$userModel = new userModel();
//do something with this
$session = $this->session;
$content = 'some html';
$userInfo = $userModel->getUsers();
$view = $this->view->render( array(
'content' => $content,
'userInfo' => $userInfo,
));
return $view;
}
}
//Core LIbraries
class Validator {
//your validator stuff
}
//Core LIbraries
class Session {
//your validator stuff
}
//Core LIbraries
class Auth {
//your validator stuff
}
class CoreModel{
public $validator;
function __construct(){
$this->validator = instantiateValidatorClassHere();
}
}
//a user model class (back end). you want a model class for each db table pretty much.
class UserModel extends CoreModel {
// if you need the validator anywhere inside this class, its globally available here inside any class that extends the CoreModel, e.g. $this->validator->methodName()
public function getUsers (){
$sql = 'SELECT * from users';
$result = $db->get($sql);
return $result;
}
}
Notice, on the Controller, this is a generic name for something like indexController, or anything custom. Also, I have the word extends there. It inherits all the objects from the parent that it extends. Inside it, now they will be available via $this->. See my example where I get $this->session.
Try to avoid constructs - you probably don't need them anywhere except for the core, and under special circumstances, which you might then need to check for yourself before you do even that. I dont use constructs much anymore. It can be a bit clunky and unmanageable.
this supposed to be an MVC framework
(i am learning by doing)
class load{
public function model(){
// some code...
[...] = model[$modelName] = new $modelName();
}
}
this class handles all load option in to the controller..
class _framework{
public $load; // object
public $model; // array
function __construct(){
//some code...
$this->load = new load();
}
}
this is the framework of the controllers
the controller extends this class.
edit:
it should use like this:
class newController extends _framework{
public function index(){
$this->load->model('modelName'); // for loading the model.
$this->model['modelName']->modelMethod(); // for use the model method.
}
}
my problem is where the [...].
how can I get the new model to the array in the framework class??
If you want to get an array out of your model object,
you can define its public method toArray:
class modelName {
public function toArray () {
$array = ...; // get your array here
return $array;
}
}
Then you can call it from outside and get your array:
$myArray = $myModel->toArray();
Your model should encapsulate its data and make them accessible via API like that.
I would not call an array a model though. A model is a layer with many classes serving the purpose of the model - storing your data, peforming their validation, whatever other data-related business logic and providing API to access the data.
Also it is common to capitalize your classes.
I recently watched this video and wanted to change my Laravel controllers so that they had their dependencies managed with Laravel's IoC container. The video talks about creating an interface for a Model and then implementing that interface for the specific data source used.
My question is: when implementing the interface with a class that extends Eloquent and binding that class to the controller so that it is accessible from $this->model, should I also create interfaces and implementations for the Eloquent models which may be returned when calling methods such as $this->model->find($id)? Should there be different classes for the Model and the ModelRepository?
Put it another way: how do I do new Model when my model is in $this->model.
Generally, yes, people doing that pattern (the repository pattern) have an interface which have some methods defined that your app will use:
interface SomethingInterface {
public function find($id);
public function all();
public function paged($offset, $limit);
}
Then you create an implementation of this. If you're using Eloquent, then you can make an Eloquent implementation
use Illuminate\Database\Model;
class EloquentSomething {
protected $something;
public function __construct(Model $something)
{
$this->something = $something;
}
public function find($id)
{
return $this->something->find($id);
}
public function all() { ... }
public function paged($offset, $limit) { ... }
}
Then you make a service provider to put it all together, and add it into app/config/app.php.
use Something; // Eloquent Model
use Namespace\Path\To\EloquentSomething;
use Illuminate\Support\ServiceProvider;
class RepoServiceProvider extends ServiceProvider {
public function register()
{
$app = $this->app;
$app->bind('Namespace/Path/To/SomethingInterface', function()
{
return new EloquentSomething( new Something );
});
}
}
Finally, your controller can use that interface as a type hint:
use Namespace/Path/To/SomethingInterface;
class SomethingController extends BaseController {
protected $something;
public function __construct(SomethingInterface $something)
{
$this->something = $something;
}
public function home() { return $this->something->paged(0, 10); }
}
That should be it. Apologies on any errors, this isn't tested, but is something I do a lot.
Downsides:
More code :D
Upsides:
Able to switch out implementations (instead of EloquentSomething, can use ArraySomething, MongoSomething, whatever), without changing your controller code or any code that uses an implementation of your interface.
Testable - you can mock your Eloquent class and test the repository, or mock your constructor dependency and test your controller
Re-usable - you can App::make() to get the concrete EloquentSomething anywhere in your app and re-use the Something repository anywhere in your code
Repository is a good place to add additional logic, like a layer of cacheing, or even validation rules. Stock mucking about in your controllers.
Finally:, since I likely typed all that out and STILL DIDN'T ANSWER YOUR QUESTION (wtf?!), you can get a new instance of the model using $this->model. Here's an example for creating a new Something:
// Interface:
public function create(array $data);
// EloquentSomething:
public function create(array $data)
{
$something = this->something->newInstance();
// Continue on with creation logic
}
Key is this method, newInstance().
I've used $newModel = $this->model and it's worked for me.
I have been working on my own library/framework for the learning experience for a while. MVC is one of those things that took me a while to really understand but I do finally "Get it".
Below is some sample code for a basic MVC setup in PHP. I think I am in the right direction so far, where I need a little help is down in the "Example controller" near the bottom, you will see where I can create a view, I just need to figure out how to best get my data from a model file into that controller class. Please help with example code if you can, hopefully I am making sense.
Also I am welcome to any comments/suggestions on any of the code
Abstract Controller class...
/**
* MVC Example Project
*/
/**
* Extend this class with your Controllers
* Reference to the model wrapper / loader functions via $this->model
* Reference to the view functions via $this->view
*/
abstract class Core_Controller {
protected $view;
protected $model;
function __construct($dependencyContainer){
$this->view = new Core_View();
//$this->view = $dependencyContainer->get(view);
}
}
Abstract Model class...
/**
* Extend this class with your models and reference to the database object via $this->$db
*/
abstract class Core_Model {
protected $db;
protected $session;
function __construct($dependencyContainer) {
$this->db = $dependencyContainer->get(database);
$this->session = $dependencyContainer->get(session);
}
}
View class, might make it abstract as well...
class Core_View {
protected $data;
# Load a view file (views/$view.php);
# $param data this gets extracted and be thus be used inside the view
# When loading another view from inside the view file the data is 'cached' so you
# don't have to pass them again
public function load($view,$data = null) {
if($data) {
$this->data = $data;
extract($data);
} elseif($this->data != null) {
extract($this->data);
}
require(APP_PATH . "Views/$view.php");
}
public function set($data = null) {
if($data) {
$this->data = $data;
extract($data);
} elseif($this->data != null) {
extract($this->data);
}
}
}
Example putting it together...
/**
* Example Controller
*/
class User_Controller extends Core_Controller {
public function profile()
{
$profileData = array();
$profileData = //GET from Model
$this->view->load('userProfile', $profileData);
}
}
?>
My suggestion is not to tie view and model to the controller at all. Let them be instantiable from controller code, just like any other classes. You can then get the model data (and pass it to the view) in standard object oriented way.
Will you use a Data access layer (DAL) / Object-relational mapping (ORM)? Take a look at Zend_Db, Doctrine or Propel
I'd say that you're missing the part of the application that manipulate your models. It could be your controller, but isn't a good practice. So we need a model mapper.
The best way to get model data from your controller is simply calling it. But generally we use a kind of "pointer" which knows how to populate your object model. This pointer is called "Mappers" (Data Mapper Pattern):
$MyModelMapper = new MyModelMapper();
$Profile = $MyModelMapper->getProfileById($id); // return Core_Model.
This function will perform a database query and will populate one specific model with the data. You could also get an array of objects for a "list" action for example.
Then you'll pass this model to your view.
I think you should take a look at the Zend Framewok quick start. It will give you some ideas.
See this question too: What's the difference between DAO and Data Mapper
My Dispatcher is "choosing" correct Controller; then creating Controller's instance (DependencyInjectionContainer is passed to Controller constructor); then calling some Controller's method...
class UserController extends Controller
{
public function __construct(DependencyInjectionContainer $injection) {
$this->container = $injection;
}
public function detailsAction() {
...
}
}
DependencyInjectionContainer contains DB adapter object, Config object etc.
Now let's see what detailsAction() method contains...
public function detailsAction() {
$model = new UserModel();
$model->getDetails(12345);
}
As you see I'm creating new instance of UserModel and calling getDetails methods.
Model's getDetails() method should connect to db to get information about user. To connect to DB UserModel should be able to access DB adapter.
What is the right way to pass DependencyInjectionContainer to the UserModel?
I think that this way is wrong...
public function detailsAction() {
$model = new UserModel($this->container);
$model->getDetails(12345);
}
Instead of injecting the entire DI Container into your classes, you should inject only the dependencies you need.
Your UserController requires a DB Adapter (let's call this interface IDBAdapter). In C# this might look like this:
public class UserController
{
private readonly IDBAdapter db;
public UserController(IDBAdapter db)
{
if (db == null)
{
throw new ArgumentNullException("db");
}
this.db = db;
}
public void DetailsAction()
{
var model = new UserModel(this.db);
model.GetDetails(12345);
}
}
In this case we are injectiing the dependency into the UserModel. In most cases, however, I would tend to consider it a DI smell if the UserController only takes a dependency to pass it on, so a better approach might be for the UserController to take a dependency on an Abstract Factory like this one:
public interface IUserModelFactory
{
UserModel Create();
}
In this variation, the UserController might look like this:
public class UserController
{
private readonly IUserModelFactory factory;
public UserController(IUserModelFactory factory)
{
if (factory == null)
{
throw new ArgumentNullException("factory");
}
this.factory = factory;
}
public void DetailsAction()
{
var model = this.factory.Create();
model.GetDetails(12345);
}
}
and you could define a concrete UserModelFactory that takes a dependency on IDBAdapter:
public class UserModelFactory : IUserModelFactory
{
private readonly IDBAdapter db;
public UserModelFactory(IDBAdapter db)
{
if (db == null)
{
throw new ArgumentNullException("db");
}
this.db = db;
}
public UserModel Create()
{
return new UserModel(this.db);
}
}
This gives you better separation of concerns.
If you need more than one dependency, you just inject them through the constructor. When you start to get too many, it's a sign that you are violating the Single Responsibility Principle, and it's time to refactor to Aggregate Services.
I'd use a singleton object for all config parameters :
You set it up in your bootstrap, then choose to use it directly or pass it as parameter in your objects.
The idea being to have one method all around to retrieve your config data.
You may then provide an abstract class for db manipulation which uses your config. singleton.
DependancyInjection can still be used to override your default data.
The above link in the comment (possible 'duplicate') concludes on using constructor injection : this is close to your current method.
However if I try to figure how your model works, I guess you will have many other model classes other than "userModel". Thus an abstract class using a config singleton might be a good solution : all your next model classes will just extend this abstract class, and you don't have to worry about your config.
On the other hand, your solution is good to me as long as your dependanceInjectionContainer changes often.