Have access to a common class in a PHP MVC framework - php

I have read a lot of SO topics about this already, but still haven't found (or have been able to create) a proper answer.
I am working on a small MVC framework and I want some global class/object that I can call from my controllers (but maybe models too).
There are a couple of routes I can take:
Global variable
Static class/Registry
Dependency injection
The internet seems to agree that the DI is the best route to take. I think I have grasped the idea, but am not comfortable yet. So I want to throw in some background information; I will probably be the only one working on the project, it is a small project, all my controllers extend the main Controller (so I could just load one library like class there).
As a concrete example, I want to have an array of categories. So I started out with putting that array in the CategoryController. But now I noticed I kinda want to use that array in my frontview and in ProductController as well. Obviously I don't want to load all of CategoryController into ProductController.
You could also say I could put that array in some kind of configuration or settings file, because of the simpleness of this example, but that's why it's an example. I will probably expand on it with more functionality.
So to summarize: In PHP (specifically inside a MVC model) how can you give your classes (mainly Controllers) access to some kind of common class or other sharable functionality.

Your controllers are created by "something" (usually a front controller). So when the controller is created, you could inject a dependency injection container.
And in your configuration/bootstrap (before the controller is created), you should add you categories to the container.
That way you can access the categories from every controller.
Please note that this is a simple example that doesn't totally fit the spirit of dependency injection. The best solution would be to inject directly the categories (instead of injecting the container). But that can become a lot of work if you generalize that pattern (lots of dependencies to handle in your front controller).
A solution would be to use a dependency injection framework that could do that for you.
For example I work on a DI container that lets you inject stuff with annotations (PHP-DI), but there are several other libraries for DI so you have a choice.

My 2 cents:
In a small self-made mini-framework I have done some time ago, I have created a global singleton class named Application, and anything/everything which should be accessible from anywhere/everywhere was a property or method of this class.
In my case, there was a $db property for database access, a $user property to access the user data and methods, an $input property for a "powered" $_REQUEST access, and so on.
Of course, you have many other options, suitable for different scenarios. This approach simply worked fine for me on that occasion.
Now, if you want to access a controller from another controller, this really sounds strange. This "thing" that you want to access should be a model class, a library class, or anything else, but it should not be "locked" inside a controller class. Indeed, the controller should be "as thin as possible", and focus on calling the appropriated methods from other classes, based on the user input (request) and then calling some output method to generate and send the answer (response).
Finally, although I've read some criticism and complaints about it (as well as praises too), I do make use of static methods a lot, mainly for classes which are more "helpers" than anything else.

Related

Is there a good way to keep the number of parameters (dependencies) passed to a controller down?

So in Silex, I am attempting to get the $app parameter out of my controller actions and just pass in the dependencies that are relevant to the controller/action.
Generally my controllers have these shared dependencies:
Template engine
Session provider
Translation provider
URL generator
Validation provider
I've got a base Controller class to accept these on the constructor by default. The controllers inheriting from it also end up taking those parameters as well. Additionally they take other parameters, such as an object repository/store (such as a user repository in an authentication or user controller).
I end up registering the controllers in Silex with at least 5 parameters to the constructor when it seems like I don't see a lot of that in other applications. Feels like I'm doing it wrong.
I also realize that I'm complaining about the same thing that the Pimple DI container "fixes," but using it also seems not quite true to the DI philosophy.
My question: Is there a better way to do what I'm doing?
Yes there are alternative solutions.
The first one is to "group" your parameters into new classes like ControllerUtil or things of the sort. That's not always easy or possible though, so I'm not a particular fan of that.
Benjamin Eberlei explains this approach in this blog post: Extending Symfony2: Controller Utilities
The second is to use alternative to constructor injection, like property or setter injection. This is not as clean as constructor injection, but it is extremely practical.
Given controllers are generally not the kind of components you want to reinject, reuse or unit-test a lot, so this is an acceptable compromise IMO. I've been using that method for about a year and I can't go back.
Here is a related blog post I wrote on that subject: Controllers as services?

PHP MVC - Calling view functions from model, or controller?

After reading a fair few posts on Stack, and also some material recommended to me on line, the MVC pattern is quite open to interpretation, so please don't answer with another explanation. Thanks!
I'm reaching the end of designing my own PHP MVC now, and have two possible ways to move forward with the views.
But first, my controllers are currently quite dumb, not containing any classes and simply call public methods from the suitable models, and render the appropriate view.
Views are included as necessary, so naturally the objects are available to them via the constructors, along with all the methods (inc delete/update etc).
My first option is to get data using something like this in the view
foreach($object->fetchData() as $data)
and then looping through the results. However some people do not agree with this, and have suggested that such methods should be excluded from the view. Instead it has been recommended that I assign this to a variable in the constructor, and then use this variable in the view
//constructor
$fetched_data = $object->fetchData()
// view
foreach($featched_data as $data)
I don't like this very much, as it seams messy and unnecessary.
With all my critical methods being made available to the view, could this be considered a problem?
So here's the question. Do I keep it how it is, and create new methods in the MODEL for rendering data (as above) OR can I create a class in the constructor, extend the model into it, protect the critical functions in the model, and then create my read only public methods in the CONSTRCUTOR?
Thanks!
I would create a class in the constructor. Not only would extending the model be a much safer approach, but it'd also minimize the calling of functions in the views. Am assuming you'll have several views, it's much easier to get access the constructor data than calling method functions each time in each view.
You can add classes to your controllers that will call the method functions and pass the data directly into the views, instead of clustering your constructor or bootstrap.

Confused About Objects and Classes in CodeIgniter?

I’m fairly new to CodeIgniter and have a question. I’m a bit confused about Classes, Libraries and Objects.
Does CodeIgniter replace the normal PHP way of usings objects i.e. $var = new car(); with libraries i.e. $this->load->library('some_library'); $this->some_library->some_function(); ?
If both are valid, is there a difference? If so, what are the differences and when do I use one over the other? Which is more common/proper?
I am asking because I created a class, but I'm not certain what is the correct manner in which to instantiate it.
Thanks in advance
I am not familiar with CodeIgnitier. But familiar with other PHP frameworks. Most of frameworks use this way for performance improvements, registering things, executing certain events, and making things simpler for developer...
For example if you want to create class "car" with is somewhere in library directory you would have to include the file first before you can create object of that class (miltiple lines of code, more room for error). The framework will create the class and includes related files in 1 line of code (easier and safer).
Framework way also works as a factory. Instead of recreating an object, it will create object only once and every time you call the method again it will return the reference to existing object.
More things are happening behind the scenes when you use framework. Things are getting registered, etc...
CI doesn't replace class behavior per se, it simply adds functionality that allows access to custom libraries/models/views as singleton objects via the core object for simplicity.
Nothing is stopping you from creating (as I have in one of my projects) additional files with classes for non-singleton entities and require them in a model for further use. On hindsight, I should probably have used helpers for this.
What the loader ($this->load) class does, among other things, is it creates a single object of the specified class (model, library or view - not helpers though, see below) and attaches it as a property of the core class that is normally accessible via $this.
Helpers are a bit different. They are not attached, but instead simply 'read' into the global namespace from the point where they are loaded.
To answer your question, it would be more proper to use the loader class in instances where you don't need more than one instance of a class created. If you need 'entity' classes, your best CI-compliant bet would be to create them as helpers.
Given only this context, this looks like Inversion of Control (maybe I'm wrong, I haven't looked too closely at CodeIgniter).
You don't want to rely on the type car as in new car(). What if later you want to make $var a racecar? $var can still do the same things, but it is forced to be a car because you constructed it directly. Or what if you are testing this class, but car is some complex object which calls some external service. You want to test your logic, but don't care if the car service isn't working. So you should be able to change $var to actually load a mockcar. You can't do that if you do $var = new car().
What is Inversion of Control?

Totally failed in OOP/MVC

Ok, it's my fault. I've never ever learned programming at a school and that's why i'm always ending up in a spaghetti code. I've always curious about different patterns and tried to understand them at least in a basic level.
MVC is my worst fear and i think i'll be never able to use it's advantages because of i don't understand it's fundamentals.
My actual question/problem looks like:
The front controller calls a 'Core' class which is doing some initialization then it calls the actual controller with the correct action/parameters. The controllers always extending the 'Core' class so i can acces it's variables, etc. They're working nicely together but here comes my real problem.
Some kind of methods (getting a database entry in most of the cases) are required in different cases. (e.g. a product needs it's manufacturer)
In this scenario i have two (bad) choices:
Inject the required method into the 'Core' class so it's getting bloated over time
Inject the required method into the actually called controller so i will end up a redundant codebase
I see a lot of possible problems in my approach:
Controllers are always extending 'Core' class
'Core' controller holds the database object so without it i cannot access my Db
Database functions (e.g. getting a product) are in the controllers but i cannot access them because they're always calling 'Core' first (extending problem again)
Please tell me:
Where is the biggest problem in my approach and where can i correct it?
Note:
Please don't treat this as a general question, i think this is an answerable thing. If you need some clarification, please ask for it and i'll try to lighten up things.
Thanks for your precious time, fabrik
Your data is represented to your Controller and View through the Model. The Model may be supported by a Repository but depending on the overhead you might want to provide your database access in your Model. The data architecture should be similar to this:
(Repository<===>)Model<===>Controller--->View
Your biggest problem is having the "Core" class, get rid of it asap.
By the way, the FrontController is not the only way to do things MVC things either.
Your second problem is that controller deals with database, it shouldn't. I suggest you use some abstract data layer, which you use only in your models. And controller should deal only with models, it shouldn't care how models get their data persisted and fetched.
Look into using a DI framework to automatically inject an instance of a repository into your controllers (or even better, a proxy class). Try to keep business logic outside of your controllers, but rather, refector it out into a helper or proxy class.
I tend to split my logic up into views => controllers (just for interaction between business later and view) => business logic => models (DTOs) => low-level data access at a minimum.
Also, if you need common helper functionality in your views, perhaps create several extensions to help.

Composing a Controller class with Dependency Injection in PHP

How to solve the problem of composing a Controller class in PHP, which should be:
easily testable by employing Dependency Injection,
provide shared objects for end programmer
provide a way to load new user libraries
Look down, for controller instantiation with a Dependency injection framework
The problem is, that derived Controllers may use whatever resources the programmer wants to (eg. the framework provides). How to create a unified access to shared resources (DB, User, Storage, Cache, Helpers), user defined Classes or another libraries?
Elegant solution?
There are several possible solutions to my problem, but neither one looks to be a elegant
Try to pass all shared objects by constructor? (may create constructor even with 10 placeholders)
Create getters, settters? (bloated code) $controller->setApplication($app)
Apply singletons on shared resources? User::getInstance() or Database::getInstance()
Use Dependency Injection container as a singleton for object sharing inside the controller?
provide one global application singleton as a factory? (this one looks very used in php frameworks, hovewer it goes strongly against DI principles and Demeter's law)
I understand, that creating strongly coupled classes is discouraged and banished for :), however I don't know how this paradigm applies to a starting point for other programmers (a Controller class), in which they should be able to access shared resources provided to the MVC architecture. I believe, that breaking up the controller class into smaller classes would somehow destroy the practical meaning of MVC.
Dependency Injection Framework
DI Framework looks like a viable choice. However the problem still persists. A class like Controller does not reside in the Application layer, but in the RequestHandler/Response layer.
How should this layer instantiate the controller?
pass the DI injector into this layer?
DI Framework as a singleton?
put isolated DI framework config only for this layer and create separate DI injector instance?
Are you developing a framework yourself? If not, your question does not apply, because you have to choose from already existing frameworks and their existing solutions. In this case your question must be reformulated like "how do I do unit testing/dependency injection in framework X".
If you are developing a framework on you own, you should check first how already existing ones approach this issue. And you must also elaborate your own requirements, and then just go with the simplest possible solution. Without requirements, your question is purely aesthetic and argumentative.
In my humble opinion the simplest solution is to have public properties which initialize to defaults provided by your framework, otherwise you can inject your mocks here. (This equals to your getters/setters solution, but without the mentioned bloat. You do not always need getters and setters.) Optionally, if you really need it, you may provide a constructor to initialize those in one call (as you suggested).
Singletons are an elegant solution, but again, you must ask yourself, is it applicable in your case? If you have to have different instances of the same type of object in your application, you can't go with it (e.g. if you wish to mock a class only in half of your app).
Of course it is really awesome to have all the options. You can have getters/setter, constructors, and when initialization is omitted, default are taken from a singleton factory. But having too many options when not needed, is not awesome, it is disturbing as the programmer has to figure out which convention, option and pattern to use. I definitely do not want to make dozens of design decisions just to get a simple CRUD running.
If you look at other frameworks you will see that there is no silver bullet. Often a single framework utilizes different techniques depending on the context. In controllers, DI is a really straightforward thing, look at CakePHP's $helpers, $components variables, which instruct to inject appropriate variables into the controller class. For the application itself a singleton is still a good thing, as there is always just a single application. Properties less often changed/mocked are injected utilizing public properties.
In case of an MVC, subclassing is perfectly viable option as well: just as AppController, AppView, AppModel in CakePHP. They are inserted into the class hierarchy between the frameworks's and all your particular Controller, View and Model classes. This way you have a single point to declare globals for your main type of classes.
In Java, because of dynamic class loaders and reflection, you have even much more options to choose from. But on the other hand, you have to support much more requirements as well: parallel requests, shared objects and states between worker threads, distributed app servers etc.
You can only answer the question what is right for you, if you know what you need in the first place. But actually, why do you write just another new framework anyway?
Singletons are frowned upon when Dependency Injection is viable (and I have yet to find a case where a Singleton was necessary).
More than likely you will have control of instantiation of controllers, so you can get away with the mentioned $controller->setApplication($application), but if necessary you can use static methods and variables (which are far less harmful to the orthogonality of an application than Singletons); namely Controller::setApplication(), and access the static variables through the instance methods.
eg:
// defining the Application within the controller -- more than likely in the bootstrap
$application = new Application();
Controller::setApplication($application);
// somewhere within the Controller class definition
public function setContentType($contentType)
{
self::$application->setContentType($contentType);
}
I have made of a habit of separating static and instance properties and methods (where necessary, and still grouping properties at the top of the class definition). I feel that this is less unwieldy than having Singletons, as the classes still remain quite compact.
How about refactoring?
Granted that was not one of your options, but you state the code is a largely coupled class. Why not take this time and effort to refactor it to more modular, testable components?
As far as I understand, the Application class of yours should be the dispatcher. If so, I would rather use the controller constructor to pass an instance of the Application, so the controller would know who's invoking it. At later point if you want to have a different Application instance depending on whether the code is invoked from within CLI, you can have an ApplicationInterface which the Application\Http and Application\Cli would implement and everything would be easy to maintain.
You could also implement some factory pattern to get a nice implementation of the DI. For example, check the createThroughReflection method here: https://github.com/troelskn/bucket/blob/master/lib/bucket.inc.php
I hope this makes sense.
Regards,
Nick
You could also use a ControllerFatory in which you would give to your Application or Router/Dispatcher
Sou you could call $controllerFactory->createController($name);
Your Application would have no idea how to create your controllers the Factory would. Since you ca inject your own ControllerFactory in to your DI container you can manage all dependencies you want depending on the controller.
class ControllerFactory {
public function __construct(EvenDispatcher $dispatcher,
Request $request,
ResponseFactory $responseFactory,
ModelFactory $modelFactory,
FormFactory $formFactory) {
...
}
public function createController($name = 'Default') {
switch ($name) {
case 'User':
return new UserController($dispatcher,
$request,
$responseFactory->createResponse('Html'),
$modelFactory->createModel('User'),
$formFactory->createForm('User'),...);
break;
case 'Ajax':
return new AjaxController($dispatcher,
$request,
$responseFactory->createResponse('Json'),
$modelFactory->createModel('User'));
break;
default:
return new DefaultController($dispatcher, $request, $responseFactory->createResponse('Html'));
}
}
}
So you just need to add this factory in your DI container and pass it to your Application.
Whenever you need a new controller you add it to the factory and if new dependencies are required you give them to the factory through your DI container.
class App {
public function __construct(Router $router,Request $request, ControllerFactory $cf, ... ) {
...
}
public function execute() {
$controllerName = $this->router->getMatchedController();
$actionName $this->router->getMatchedAction();
$controller = $cf->createController($controllerName);
if(is_callable($controller, $actionName)) {
$response = $controller->$action(request);
$response->send();
}
}
}
This is not production code, I haven't tested, but this is how you decouple your controllers from your application. Notice here though that there is one bad coupling here because my controller return's a response and I execute the response in the App. But like I said this is just a small example.
It is usually a good idea to pass factories for Models, Forms, and Controllers to their respective parents, because you will end up loading all your object Graph at bootstrap time wich is really bad and memory consuming.
I know this answer was already approved, but it's my 2 cents on the subject
There is a good article on the subject
http://miller.limethinking.co.uk/2011/07/07/dependency-injection-moving-from-basics-to-container/

Categories