Is it common practice to append use '.class.php' extension for PHP classes?
On PHP.net here: http://php.net/manual/en/function.spl-autoload-register.php there are some examples like this:
// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.class.php';
});
which use a .class.php extension.
Should PHP code be written like this? I've never seen it before, is it something new? This is a kind of new feature in PHP so maybe it is?
EDIT: 'feature' was not a good word! Perhaps I should have asked whether it's some standard or convention.
Thanks.
It's not a feature, it's just a convention that you see come up every now and then. Whether to follow it or not is the choice of you and your team.
My personal opinion is that since the choice is arbitrary and this particular style contradicts with the PSR-0 autoloader specification you should pass because:
PSR-0 is more widely used, so all other things being equal it would be a better convention to follow
following the ".class.php" style means cannot take a PSR-0 compliant autoloader (there are many online) and use it without modifications
This is mostly used to assure its a class file the autoloader targets, you often have other .php files like templates, scripts like bootstrapping or config files that are .php files, but should never be interpreted as classes
It's not a feature as such, it's just a very simple, and practical way to keep your code organized and, more importantly, to avoid issues with autoloading.
Suppose you've got some class called User, and your site has a page, that is generated by a script: User.php. If you need an instance of the User class, the autoloader function will be called, and get User as an argument. When looking for a file simply called User.php, you might include a file, other than the class definition. That's why you can (and should) give class definition a little extra in their names. Then you can write your autoloader to look for [[class name]].class.php, neatly avoiding the User.php file.
That's the bottom line of it. There's -of course- also namespaces to consider, and that most modern way of all to keep your code organized: directories (set_include_path)
It is all for better understanding what this files all about. So, when you see filename.class.php, you know, this file contains Class filename.
There isn't any kind of special language support that gets triggered if you name your classes 'class.php'; it's just a convention, like whether you use spaces or tabs for indentation.
In one of the projects I worked on, classes where named *.inc.php, and templates *.tpl.php.
If I was coding php circa 1999, this would be an excellent convention to follow. You can name files whatever you want, but I recommend just naming them after the classname inside the file, with '.php' appended.
This is more of a personal preferences, but I would actually probably look into the PSR-0 standards which provide a standard way for you to name and namespace your classes to provide better compatibility with other peoples code in the same format.
In the PSR-0 standards PHP files are named after the class and put into folders related to the namespace.
I would recommend adopting this method over the .class.php method mentioned in the PHP.net manual.
Related
This is my project path configuration
./create.php
/Install/Install.php
create.php
<?php
use Install\Install;
echo "Starting";
$install = new Install();
This gives me the error
PHP Fatal error: Uncaught Error: Class 'Install\Install' not found in /project/create.php:6
Install.php
<?php
namespace Install;
class Install
{
//whatever
}
Can someone explain me what is happening there ?
Obviously I guess that using a require_once line with my filename would probably fix the issue...but I thought using namespace and use import could prevent me from doing that like we do in classic framework like symfony / magento ?
I've seen some post speaking about autoloading, but i'm a little bit lost. Haven't been able to find a clear explanation on the other stack topic neither.
PHP compiles code one file at a time. It doesn't have any native concept of a "project" or a "full program".
There are three concepts involved here, which complement rather than replacing each other:
Namespaces are just a way of naming things. They allow you to have two classes called Install and still tell the difference between them. The use statement just tells the compiler (within one file) which of those classes you want when you write Install. The PHP manual has a chapter on namespaces which goes into more detail on all of this.
Require and include are the only mechanisms that allow code in one file to reference code in another. At some point, you need to tell the compiler to load "Install.php".
Autoloading is a way for PHP to ask your code which file it should load, when you mention a class it hasn't seen the definition for yet. The first time a class name is encountered, any function registered with spl_autoload_register will be called with that class name, and then has a chance to run include/require to load the definition. There is a fairly brief overview of autoloading in the PHP manual.
So, in your example:
use Install\Install; just means "when I write Install, I really mean Install\Install"
new Install() is translated by the compiler to new Install\Install()
the class Install\Install hasn't been defined; if an autoload function has been registered, it will be called, with the string "Install\Install" as input
that autoload function can then look at that class name, and run require_once __DIR__ . '/some/path/Install.php';
You can write the autoload function yourself, or you can use an "off-the-shelf" implementation where you just have to configure the directory where your classes are, and then follow a convention for how to name them.
If you want to Use class from another file, you must include or require the file.
Use require('Install.php'); before use Install\Install;.
If you are planning to do a big project I would recommend to use PHP frameworks rather than coding from scratch.
I have been trying to learn about classes in PHP and part of my learning process has been looking at various libraries and stuff out there. Of course I am left with many questions, here is one of them.
When looking at some libraries, the main file that you call to invoke the library, they call each of the libraries files by invoking them directly by name, for example this is how the PHP chart library does it:
<?php
require_once 'model/ChartConfig.php';
require_once 'model/Point.php';
require_once 'model/DataSet.php';
require_once 'model/XYDataSet.php';
require_once 'model/XYSeriesDataSet.php';
require_once 'view/primitive/Padding.php';
require_once 'view/primitive/Rectangle.php';
require_once 'view/primitive/Primitive.php';
require_once 'view/text/Text.php';
require_once 'view/color/Color.php';
require_once 'view/color/ColorSet.php';
require_once 'view/color/Palette.php';
require_once 'view/axis/Bound.php';
require_once 'view/axis/Axis.php';
require_once 'view/plot/Plot.php';
require_once 'view/caption/Caption.php';
require_once 'view/chart/Chart.php';
require_once 'view/chart/BarChart.php';
require_once 'view/chart/VerticalBarChart.php';
require_once 'view/chart/HorizontalBarChart.php';
require_once 'view/chart/LineChart.php';
require_once 'view/chart/PieChart.php';
?>
However, I look at another library, and they just automate the process by calling each file in the directory using the PHP autoload method like this(From the php manual):
function __autoload($name) {
echo "Want to load $name.\n";
throw new Exception("Unable to load $name.");
}
I was just wondering if there is any advantage or disadvantage to doing it the autoload way?
I don't believe __autoload only has advantages. But there are some indeed.
Pros for __autoload
You don't need to maintain that long list of includes, which can be a pain to keep up tidy (which means there's no forgetting an include)
You only include what you really need: some classes might only be needed in some special scenario, you can avoid it
Pros for the normal way
It's very easy to understand for anybody
Looking at the includes will tell you what kind of things the file is doing
You control the list of classes you're importing (if you don't want a class because it's huge or doesn't work, it will never get included)
There's no complexity in the __autoload function. If your classes are in a complex hierarchy, you just need to type the name, and don't need to write complex code to find the correct file.
Easier to debug: the scope of the code that could be worrying is limited to the includes you did.
It's really a matter of coding style.
I think I would agree most with Cygal but would like to amend the response taking PSR-0 into account. I don't think it makes much sense using autoloading if you don't adhere to that standard.
Pro Autoloading
No need to maintain the include list.
You only include what you really need.
Code remains readable.
You follow a standard adopted by all major PHP frameworks so you can expect that people are familiar with this approach.
Pro old style
The dependencies are easily visible in the header of the code files.
There is no mapping between class names and file paths necessery. If you use autoloading a lot it might be necessary to reduce the time wasted for repeatedly calculating this mapping by using a cache.
To summarize: I don't see any reason to avoid autoloading as long as you follow PSR-0!
Using an autoloader is always advantageous.
You don't need massive collections of includes at the top of every
file
You don't have to worry about forgetting an include
Autoloader
only includes files that are necessary, and as they are needed
Potential drawbacks
Clash between your aotoloader and autoloaders used by libraries you want
Potential drawback can be avoided by registering your autoloader with spl
What Mark said. Also, you can keep your code DRY, if that's important to you.
The advantage if autoloading files is you don't need to worry about loadng the files yourself. And the files only gets loaded when they are needed.
An even better autoload function would be the newer: http://php.net/manual/en/function.spl-autoload-register.php
PHP's __autoload() (documentation) is pretty interesting to me. Here's how it works:
You try to use a class, like new Toast_Mitten()(footnote1)
The class hasn't been loaded into memory. PHP pulls back its fist to sock you with an error.
It pauses. "Wait," it says. "There's an __autoload() function defined." It runs it.
In that function, you have somehow mapped the string Toast_Mitten to classes/toast_mitten.php and told it to require that file. It does.
Now the class is in memory and your program keeps running.
Memory benefit: you only load the classes you need. Terseness benefit: you can stop including so many files everywhere and just include your autoloader.
Things get particularly interesting if
1) Your __autoload() has an automatic way of determining the file path and name from the class name. For instance, maybe all your classes are in classes/ and Toast_Mitten will be in classes/toast_mitten.php. Or maybe you name classes like Animal_Mammal_Weasel, which will be in classes/animal/mammal/animal_mammal_weasel.php.
2) You use a factory method to get instances of your class.
$Mitten = Mitten::factory('toast');
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Therefore, you can start out using a generic mitten throughout your code, and when the day comes that you need special behavior for toast, you just create that class and bam! - your code is using it.
My question is twofold:
(Fact) Do other languages have similar constructs? I see that Ruby has an autoload, but it seems that you have to specify in a given script which classes you expect to use it on.
(Opinion) Is this too magical? If your favorite language doesn't do this, do you think, "hey nifty, we should have that" or "man I'm glad Language X isn't that sloppy?"
1 My apologies to non-native English speakers. This is a small joke. There is no such thing as a "toast mitten," as far as I know. If there were, it would be a mitten for picking up hot toast. Perhaps you have toast mittens in your own country?
Both Ruby and PHP get it from AUTOLOAD in Perl.
http://perldoc.perl.org/perltoot.html#AUTOLOAD:-Proxy-Methods
http://perldoc.perl.org/AutoLoader.html
Note that the AutoLoader module is a set of helpers for common tasks using the AUTOLOAD functionality.
Do not use __autoload(). It's a global thing so, by definition, it's somewhat evil. Instead, use spl_autoload_register() to register yet another autoloader to your system. This allows you to use several autoloaders, what is pretty common practice.
Respect existing conventions. Every part of namespaced class name is a directory, so new MyProject\IO\FileReader(); should be in MyProject/IO/FileReader.php file.
Magic is evil!
The Mitten::factory method can say to itself, "let's see, do I have a subclass called Toast_Mitten()? If so, I'll return that; if not, I'll just return a generic instance of myself - a standard mitten. Oh, look! __autoload() tells me there is a special class for toast. OK, here's an instance!"
Rather such tricky code, use simple and verbose one:
try {
$mitten = new ToastMitten();
// or $mitten = Mitten::factory('toast');
} catch (ClassNotFoundException $cnfe) {
$mitten = new BaseMitten();
}
I think this feature comes in very handy, and I have not seen any features like it else where. Nor have I needed these features else where.
Java has something similar. It's called a ClassLoader. Probably other languages too, but they stick with some default implementation.
And, while we're at this. It would have been nice if __autoload loaded any type of symbols, not just classes: constants, functions and classes.
See Ruby's Module#const_missing
I just learned this: Ruby has a method on Module called const_missing that gets called if you call Foo::Bar and Bar isn't in memory yet (although I suppose that Foo has to be in memory).
This example in ruby-doc.org shows a way to use that to implement an autoloader for that module. This is in fact what Rails uses to load new ActiveRecord model classes, according to "Eloquent Ruby" by Russ Olsen (Chapter 21, "Use method_missing for flexible error handling", which also covers const_missing).
It's able to do this because of the "convention over configuration" mindset: if you reference a model called ToastMitten, if it exists, it will be in app/models/toast_mitten.rb. If you could put that model any place you wanted, Rails wouldn't know where to look for it. Even if you're not using Rails, this example, and point #1 in my question, shows how useful it can be to follow conventions, even if you create them yourself.
i have seen a lot of coders choosing this filename convention:
file.class.php.
is this a standard of naming class files?
just curious. so i know if i should follow it for all class files in the future.
thanks
There is no standard per se for naming class files, however file.class.php sends the message that it contains class files, opposed to file.php which may give the impression of a regular file.
My suggestion is to use one convention and be consistent with it.
Update:
A good point to note, as AJ, had stated, the *.php file extension is preferred over *.inc file extensions. Reason being that *.inc files are displayed on the client's browser as plain text and if you were to store any configuration files or private information (especially in relation to your database, yikes) it could potentially be accessed by anyone.
Actually this method of naming files came from developers who combines both procedural & OOPs in a same built. To differentiate procedural files and class files they did this. There is no standard convention. But I will suggest you to use filename.php and name the class as same as file name, just as Java convention. Keep only one class definition in a file.
#Derk: It can also be like this, there is no benefit of adding class. in file name ;)
function __autoload ($class) {
require_once $class . '.php';
}
$pizza = new pizza ();
I see this topic is over 10 years old, however, in my Delphi days, we named all class names starting with a T (e.g. TFiles). I am using the same technique for Php, THtml.php for the THtml class, etc. I also have one class per file.
More common is to capitalise class files.
so class Blah would be saved as Blah.php
What I want to do is this:
When I write a class and the class instantiates another class, I want to import that class with an require_once. Just the way I do so in Objective-C. But instead of using plain require_once function and messing around with paths and string concatenation, I would prefer something like:
importClass('myclass');
but I'm afraid that it's impossible to write a function that will include code. If I would do that in the importClass() function, I would include the class code into the implementation block of the function, which of course is nonsense. So what options do I have here?
The cleanest way to do what you want looks to be to use the Autoloader
It's not impossible at all. You can write this function:
function importClass($class) {
require_once "$class.class.php";
}
The only caveat is that any global variables declared or used inside that file will now be local to importClass(). Class definitions however will be global.
I'm not sure what this really gives you however but you can certainly do it.
In my application I have a system base class which has a similar function. The import function takes a class name, looks in a couple of related directories and finds a matching name (I also did some stuff with extensions to libraries but you may not need that) and instantiates a class inside with the same name. Then it takes that new instance and sets it as an object in the system base class.
using autoload as other answers have suggested would probably work better in your situation but this is just another way to look at it.
You can accomplish something similar using a class autoloader. I would also make sure that your include_path is set properly and that you are using a directory structure that makes sense for your classes - it's generally a good practice to NOT depend on class autoloaders, and instead include classes based on their relative path to your include_path.
I'd highly recommend browsing through Zend Framework, particularly Zend_Loader, for a good (if not over-architected) implementation. Also notice that Zend Framework will work without an autoloader in place - each file calls require_once on its direct dependencies, using their nice, organized directory structure.