In Java EE, I would use Spring to instantiate and reuse my services. Now I've created a small framework in PHP to support my application, using services, repositories and DAOs.
However, how can I instantiate, but more importantly, re-use these objects, without having to instantiate a new object every time?
It's tempting to just start using singletons, but then my code would turn into a mess pretty quickly.
In fact, I'm having trouble with using good OO practices and design patterns with PHP in general. Is there any good resource on this?
I personally use the Singleton approach in PHP all the time and in my opinion, my code isn't a mess - yet. A lot of other projects (e.g. Typo3) use global arrays to store objects. I don't like that approach, as an array item can be easily overwritten.
But if you are using namespaces and order your project files in folders (like in Java), the Singleton approach is pretty clean. And with a getInstance() method, you're much more on the safe side than with $globalArray['myInstance'].
I believe that what You're looking for is the Service container (IoC container). There are some PHP implementations out there that You can use in Your application. The one I've used so far is called the Dependency Injection component provided by the Symfony framework. The documentation can be found here.
There is another implementation available in PHP I'm aware of called Zend DI. It's provided by another big PHP framework since version 2.0, which is still in the beta stage though. Some examples on the Zend DI component can be found here.
In php we use the lazy loading technique used also by important framewokr
You need to build an autoload strategy, because in php you should always include the file in which the class is written to instantiate an object
Symfony uses the namespaces so for example
\DB\Repository\Classes\Product
for example is registered in a
/DB/Repository/Classes/Product.php file
and you make directly a
$product = new Product()
Without taking care of including file and other kind of operations like this.
Related
I am using my own home grown PHP framework and it is heavily based on components mostly from pear and Zend but lately there are some better components coming up at Composer
As my apps are growing it becomes harder to switch between components, and I am wondering if there is a way I can design my programs differently. In a way that would allow me to use components like the opposite of abstract classes.
I am thinking there should be a way for me to create my own classes, which in turn just hook in to pear or zend and use those classes like as if they wore interfaces or abstract classes. Of course they would be doing the actual work and I would just link to them.
Hypothetically if I have been using pear Config/Lite, which can only work with ini and array files, and now I like to switch to pear config or Zend config to get the benefit of saving the data in a database then there should be an easy way to switch without changing all my code since what they implement is exactly the same thing.
I am asking because I been using pears Net/URL/Mapper, which isn't bad but I found something that would also take care of the dispatching, and is being actively developed. Also I am sure that this kind of situation will come up again and again.
You want to look for something like the facade design pattern, or just use delegation / composition. However beware, using something like a facade can lead to a lot of unneeded complexity as you add layers of abstraction. I recommend you read some php design patterns, especially delegation / composition of objects to get a feel for how that might fit your case.
You should use composition for this IMO. Have the classes in your library expose their own public interface, which the rest of your code depends on. If you ever change the underpinnings of a component from say PEAR to Zend, just ensure all the original public methods still honor the previous version and you should be golden. You can formalize these interfaces with the interface keyword if you wish, but that is beyond the scope of this answer ;)
I have almost completed a PHP project, using MVC, jQuery and Ajax. It is pure PHP project. I don't use any frameworks in the code right know. I would like to change that.
Doing some research, I found, that Yii turns out to be one of the best frameworks out there.
Is it possible to somehow migrate pure PHP project to Yii?
If so, then how to do this? Which steps should I follow in order to reduce the workload and enjoy the benefits the Yii framework presents?
I'm a total Yii newbie, any insights appreciated.
TL;DR : Don't do it. It's a really horrible idea.
The Rant ..
"Framework" is not a magic sauce, that you add to a project, to make it better and shinier.
Doing some research i found Yii turns out to be one of the best frameworks out there.
What a strange research you have done .. I would love to see the materials. Especially, since I would rank it as 3rd worst PHP framework. Only surpassed in it's awfulness by CodeIgniter and CakePHP.
And the reason for it is the extremely bad quality of code, that this framework displays, combined with the bad practices, that it perpetuates.
Why avoid migration?
From your description is obvious, that you are NOT familiar with this framework and have no previous experience with it.
In management of projects there a subject: risk management. And in this case, adding a previously unused framework in final stages of project would constitute a high probability an high impact risk which also, due to the sage of project, is completely unmitigated.
It means that there is a really good chance that something will go wrong. And when it does, it most likely will sink the project. Or at least push back the release data by significant length of time.
In a perfect world frameworks are used to simplify the repetitive tasks of development, at the cost of some performance. Those are the tasks you do at the start of the project. You are not at the start of a project. This means that you will gain no benefits from this "maneuver".
Why not Yii?
As I noted before, there are also reasons not only for avoiding adding framework to an existing project, but also reasons why to avoid Yii in particular.
The inheritance nightmare
All your controller will extend class CController, which extends CBaseController, which extends CComponent
All your "models" will extend ether CActiveRecord or CFormModel, which extends CModel, which extends CComponent.
Both of there chains contain static variables and execute static methods on multitude of different other classes. Combination of these factors will make debugging extremely difficult and tedious.
Global state
There are several forms of global state. One that people in PHP usually know are global variables. But that is not the only form. Every time you have a class that contains a static variable, it also creates a global state, that can (and almost always - will) cause seemingly unrelated instance mysteriously interact.
Use of global state is a core mechanic. You will see static calls all over the codebase, and the Yii's configuration file would not function without global state.
And every time you call Yii::app() you are accessing and/or changing it.
This makes unittesting impossible for Yii applications. And debugging turns into exercise of using grep on your whole project.
Tight coupling
When you create an application in Yii. It becomes bound to it. You cannot execute parts of your application without launching the full framework. Mostly it is due to the static call, that you end up adding to your code.
Every time you add a static call in your own code, that piece of code becomes tied to the name of the class. That essentially is tight coupling.
As you might have noticed (hopefully), there is another way how to achieve the same effect - the use of new operator. That is another way of coupling some code of yours to a specific name of a class.
No interfaces .. none .. whatsoever
No matter how horrible the configuration of a Yii project is, the configuration file was a well intended gesture. The least harmful way to introduce external code and replace existing components in so messed up codebase.
But unfortunately it brings in the focus the problems caused by lack of interfaces and the existing coupling.
One of the component that developers will try to replace is the CUrlManager. Mostly due to way how you can pass additional parameters.
An interface in OOP specifies the contract between two instances. It lets you define the capabilities of an instance, the methods that can be used by others. When it's not there, in a large codebase, you are left guessing, which methods are required and which are not.
In case of Yii components the problem is compounded even further due to static call and deep inheritance. The above mentioned CUrlManager extends CApplicationComponent, which extends CComponent. Also the same file defines CUrlRule and CBaseUrlRule classes.
When you are writing a replacement, you have to write some code, plug it in the configuration and then test it by running your applications. That way you know which method (or parameter) next you need to add.
Basically, it's the "save-an-see-what-blows-up" method of development.
That's not MVC!
Yii does not implement MVC or any of MVC-inspired design patterns. What it calls "MVC" could be described as ActiveRecord-Template-Logic pattern.
Instead of having proper model layer (yes, it should be a layer), the creator(s) of Yii opted for collection of active record and form wrappers. This forces the application logic to be forced in the "controllers".
On the other hand you have glorified templates, instead of proper view instances for containing presentation logic. It is somewhat mitigated by use of widgets, but those instead suffer from SRP violations, because widgets are forced to contain bits of presentation logic and perform partial rendering. The rest of presentation logic ends up again in the controllers.
And to make it all worse, the "controllers" also have to deal with authorization. This usually will mean, that whenever you change the access scheme, you will have to go through every single instance of CController to check whether it needs to be changed too.
It's not MVC. It's a mess with names taken from MVC design pattern and slapped on some components.
All the small things ..
The framework also comes with few minor issue, that do not deserve a separate section:
Defining more then one class per file:
This will get annoying quite fast, because there will be classes that are shoehorned at the class files with completely unrelated filenames. This will mean, that debugging will quite often require use of search.
Slapped on "modules":
By the looks of it, the modules where added to the framework after the fact. Which is why, when you need to set default module, you will have to set it in the configuration files parameter, that is called 'defaultController'.
I actually recently converted a MVC pattern website I had built from the ground up into Yii. It did take some time to set it all up but in all honesty it was well worth it. I was able to throw away a lot of code because there were already Yii extensions doing what I needed. I would also suggest that you keep your database because you can create the controllers and Models using Gii which will save you a ton of time.
I don't know of any quick solutions to this. It depends upon how the code was written. You have the database and your views so it is not really a complete new project when you take into yii. Yii will generate the database models for you. You already have the views from the existing project. Write the controller and actions and modify the views if necessary.
try these links as they refer to the same problem.
How do you convert an old oop project into Yii
tips on migrating an existing site to Yii
Drupal to Yii Migration
Since you already have a code in mvc, things will be much easier for you to migrate. However, while migrating to Yii, since it can generate controller and model very easily using gii, you can take the advantage of it.
So, first generate controller and model using gii, then you can replace your existing code (by replace I mean, substitute your code to the specific function in the controller and model) to the built in controller and model so that the functionality of your site still works. You can modify your view accordingly. But that won't be much of a work.
You can simply register your script for ajax, jquery and css. Those will work as well.
And yes, Yii is the best framework out there so take as much benefit as you can.
Thanks,
Ujjwal
In this project you converted php to yii framework. Its really easy for you if you do following step.
Since you already have a code in mvc, things will be much easier for you to migrate. However, while migrating to Yii, since it can generate controller and model very easily using gii, you can take the advantage of it.
second, If your database is accurate then 50% work complete.when you create CRUD operation using gii then automatically model-view-controller create.if you create mvc in php then it benifit for you.
third,You can simply include your script for ajax, jquery and css. Those will work as well you create a folder in themes(CSS,JS,AZAX,BOOTSTRAP).
four-Protected->view->layout, where you can change your theme..thats all
you also help www.yiiframework.com/doc-2.0/guide-intro-yii.html
if you think my answer is help you then rating me...thank you.
I'm currently developing a framework which uses an object of a Core class (this class has huge functionality & makes the framework working). The framework follows MVC architecture & has loosely coupled Model, Control, View classes. Theses classes need a reference to the Core class heavily. What I've done so far is: creating single object of the Core class & referencing to it by PHP keyword global in Model, Control, View classes.
I don't like using this approach mainly because:
This way is not true object oriented way in my sense
The IDE (netbeans) can't provide documentation to the object of the Core class - a pain for developers who will be using this framework.
I'm really worried about performance issues - have no idea whether global is slower or whatever.
I've searched & did not find any information regarding performance issue. I've also searched stackoverflow & found Does using global create any overhead? & The advantage / disadvantage between global variables and function parameters in PHP? etc links but they don't contain much information. Right now my main concern is performance, so please help.
I must agree with NevilleK, that you Core` class sounds line an God Object antipattern.
And for anyone dumb enough to suggest use of singletons/registries i would suggest to do a little research on the subject. They create the same global state as your classical global variables.
Global state is not so much matter of performance ( though in php it has some minor impact ), but it created untestable and tightly coupled code.
You really should look into the Dependency Injection. That might show you another way , which does not require to have such a Core class in your code.
Some additional videos for you:
Global State and Singletons
Don't Look For Things!
Advanced OO Patterns
Cake is a Lie
Clean Code: Arguments
I've solved a similar problem in Agile Toolkit by creating a different pattern for adding object and using it system-wide. This passes a property to a newly created objects called "api" which always references Application class.
Application class is not really a God class but it delegates all sorts of functionality to system controllers, pages etc. This screencast explains how the very basic objects are structured, it might be something you are also looking for:
http://www.youtube.com/watch?v=bUNEHqYVOYs
Firstly, whilst you are concerned with performance, you may want to read http://en.wikipedia.org/wiki/God_object first - your "core" class sounds like a "God object", which is a fairly well-established anti pattern.
In terms of performance - the best way to find out is to test it. If you're writing a framework, I'm assuming you're writing unit tests to validate it's behaviour; it's not hard to extend that unit testing to include simple performance metrics. You might also invest in test scripts using JMeter or similar to exercise a "reference implementation" of a few pages built using the framework. You'll get far better information on your specific situation from doing this than by trying to optimize the design based on Stack Overflow's collective knowledge of the general way things work.
In general, I'd say that having a global class shouldn't impact performance too much, as long as it isn't doing much work. Simply loading the class into memory, parsing it, etc. does have a performance impact - but it's not likely to be measurably slower than any other routes you might take.
If, however, your "core" class does lots of initialization logic when it's accessed by the page, it's obviously going to impact performance.
My team have to maintain a large php application that was very poorly written. It is a mix of html, javascript and SQL on top of a large poorly designed database (ex. it has a table with few hundreds of columns). The only advantage of the codebase is that it works.
We are constantly bug fixing and rewriting parts of it.
I would like to give a structure to the rewrites we do, so I've though about integrating an mvc framework in to the codebase. Could you suggest any good framework for environment?
Here is a list of things that the I would expect from such framework:
The API must be very stable. We can't afford to rewrite the code on each release.
Custom session management or at least working on standard $_SESSION[] (To be able to talk with old code).
Custom authentication.
Using the raw SQL should be well supported (The database is hard to represent in terms of objects).
It shouldn't assume that I will have a table per controller.
I suggest Zend Framework for this purpose because it is a glue framework. With ZF you are not forced into the harness of how the framework expects you to work with it. You can pick what you want and gradually replace your legacy code with code from ZF. It also supports all the things you mentioned.
In addition, I suggest to run the various QA Tools found at phpqatools.org to support you in debugging and refactoring.
Framework comparisons
http://www.phpframeworks.com/
http://php-frameworks.net/
I'm echoing Zend just to list how it fits your specific requirements:
The API must be very stable. We can't afford to rewrite the code on each release.
As mentioned, the API tends to be stable between minor releases. Major releases with changes shouldn't be hard to integrate.
Custom session management or at least working on standard $_SESSION[] (To be able to talk with old code).
Zend_Session does exactly what you want. The default session store is $_SESSION to which Zend adds a namespace concept. Your existing code should be fine, and any new code can use the Zend object to ensure there are no variable name overlaps.
Custom authentication.
Zend_Auth has a few authentication backends, but it is designed to allow you to implement your own auth.
Using the raw SQL should be well supported (The database is hard to represent in terms of objects).
Zend_DB implements the table gateway pattern which will allow you to access the data via object; however, you can also just use SQL directly and get the results as arrays.
It shouldn't assume that I will have a table per controller.
Zend_Controller and the rest of Zend's MVC implementation make no assumptions about the Model, leaving that completely up to you. I'm sure some people don't like that, but it is the one area of MVC design that varies greatly from project to project - so that's left completely to the developer. You could extend some of the DB classes, or just use the existing DB access code.
That's an example of the pick-and-choose mentality of the Zend Framework. You really can use any of the library by itself. That should work well with your project. For example, you could use Zend_View without the rest of the MVC classes just to move your presentation into templates. Or just use Zend_Auth to replace the existing Auth system. With Zend you can slowly move your project into a more structured state, little by little.
I've been using the CodeIgniter framework, however after learning Java and awesome features like Interfaces, Abstract classes, packages, and that PHP 5 also supports most of these features, I'm ready to graduate and build a real OO framework in PHP which uses all of these features (including namespaces), so I can build much more elegant designs.
What I'm thinking of is that rather than everything in the system sharing a single $this-> object like its done in CodeIgniter, e.g:
$this->load->model('box');
$this->box->something();
You would do the following to load the Box model and to call its something() method.
$box = new Framework\Models\Box();
$box->something();
Or the following
abstract class BaseController
{
public function getModel($name)
{
$model = new Framework\Models\$model(); //Is this valid code?
return $model;
}
}
class MyController extends BaseController
{
public function index()
{
$box = $this->getModel('box');
$box->something();
}
}
Are there any suggestions/pointers for building this, such as which minimum system classes I would need for the framework, what namespaces I should have, or any other features?
One thing I've noticed is that a framework is usually built for a specific purpose. Generic frameworks (like CodeIgniter) are good for smaller sites and getting things up and running quickly. However once you have specific things, which fall outside of the generic framework building your own does become a reality.
The only thing I would suggest is to be consistent. That is relentlessly consistent. If you decide to name things in camelCase then don't deviate from that. Or if you decide to use the NounVerb convention of naming methods i.e. spaceJump then don't switch to jumpSpace even if it 'sounds' better at the time.
Choose how you'll accept parameters and be consistent on that. Will you accept only parameters or associative arrays of parameters? Choose and stick with it.
I would also not over-engineer before you've written anything. The consistency thing will take you pretty far before you'll need to refactor... but I wouldn't be afraid to do that as well. (A unit test or two should ease those fears).
Yup, there's usually no right or wrong way to do things as long as you're consistent. Did I mention...
Be Consistent!
A lot of experience is needed to build a technical framework (no offense) and there are already 1'000's of CMS/basic objects (session management, ORM, etc.) framworks/libraries.
Instead of wasting precious time (no offense again), you better have to:
Evaluate and select the framework that better suits your needs (some have a really good OO architecture).
Learn will using this good framework.
Build your own OO business/application framework. (This is where you can learn, differentiate and create value).
You can build your own but why not make use of the vast libraries included with frameworks available and if required extend their functionality.
Why don't you take a look at the Zend framework.
It's fairly quick to get started and includes a lot of useful libraries and classes as standard. It's good for personal projects if your just looking to gain more experience with OOP.
http://framework.zend.com/
I would look at Kohana. It came out of CodeIgnitor, and loading Models etc is done just the way you proposed.
Check out their core features, many of which relate directly to your question (I've highlighted those):
How is Kohana Different?
Although Kohana reuses many common design patterns and concepts, there are some things that make Kohana stand out:
Community, not company, driven. Kohana development is driven by a team of dedicated people that need a framework for fast, powerful solutions.
Strict PHP 5 OOP. Offers many benefits: visibility protection, automatic class loading, overloading, interfaces, abstracts, and singletons.
Extremely lightweight. Kohana has no dependencies on PECL extensions or PEAR libraries. Large, monolithic libraries are avoided in favor of optimized solutions.
GET, POST, COOKIE, and SESSION arrays all work as expected. Kohana does not limit your access to global data, but offers filtering and XSS protection.
True auto-loading of classes. True on-demand loading of classes, as they are requested in your application.
No namespace conflicts. All classes are suffixed to allow similar names between components, for a more coherent API.
Cascading resources offer unparalleled extensibility. Almost every part of Kohana can be overloaded or extended without editing core system files. Modules allow multi-file plugins to be added to your application, transparently.
Library drivers and API consistency. Libraries can use different "drivers" to handle different external APIs transparently. For example, multiple session storage options are available (database, cookie, and native), but the same interface is used for all of them. This allows new drivers to be developed for existing libraries, which keeps the API consistent and transparent.
Powerful event handler. Observer-style event handlers allow for extreme levels of customization potential.
Rapid development cycle. Rapid development results in faster response to user bugs and requests.