You are viewing revision #9 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.
- Creating helper classes
- Creating helper functions
- Setting/Verifying the Autoload Path
- Multiple classes in one file
- Manual autoloads
Many Yii users ask how to create helper classes and functions, and though there are numerous approaches spread out among the forum and wiki articles, this Tutorial tries to bring it all together in one place.
Creating helper classes ¶
You might wish to create helper classes for several reasons:
- to extend and customize existing Yii classes
- to create classes to implement business objects not covered by Model objects
- to reuse helpful classes from other projects
Yii handles this particularly efficiently by smart use of Autoloading; when an unknown class is used, Yii automatically loads a file of the same name, but with a .php
extension.
One only need create a class file in the components/
directory, define the class itself, and Yii will find it:
<?php
// protected/components/MyClass.php
class MyClass {
...
}
Then, if the class name MyClass
is mentioned (including the use of static references), Yii loads it automatically.
IMPORTANT: Autoloading requires that the class name and the filename match exactly in spelling and case; being off just a little bit will produce an error. If you define class MyClass
in the file `Myclass.php, you will receive the error:
PHP ERROR
include(MyClass.php): failed to open stream: No such file or directory
Rename the file to MyClass.php
, matching the class name, to fix this error (unless this is an autoload path issue - see final section).
Note: Because Windows filesystems maintain but do not respect case, misspellings like this may still work, but the application will break if ported to Linux/UNIX.
Creating helper functions ¶
Almost all experienced PHP programmers have written small helper or utility functions, ones that are essentially standalone (not related to any particular objects), with string functions being particularly popular.
Though it's possible to create your helpers as static functions inside an autoloaded class:
<?php
// protected/components/Helpers.php NOT RECOMMENDED!
class Helpers {
// does the first string start with the second?
public static function startsWith($haystack, $needle)
{
return strpos($haystack, $needle) === 0;
}
...
and then use it with:
...
if ( Helpers::startsWith(...) )
but this is tedious: it's much more convenient to use regular ordinary functions to do this, and it's easy to achieve in Yii (though it does not involve the autoloader).
1. Create helpers function file ¶
I usually define helpers in protected/components/helpers.php
:
<?php
// protected/components/helpers.php
function startsWith($needle, $haystack)
{
...
}
...
2. "Require" the helper file in the config file ¶
Now that the helpers file is in place, we need a place to include it early in the application so that it's available throughout.
Though Qiang recommends putting it in webroot/index.php
, I recommend putting it in the protected/config/main.php
file instead, mainly because I usually want to apply the same treatment in protected/config/console.php
for console-mode applications. Doing the same change in the same way feels cleaner.
Add the require_once
directive near the top of the file so that the config file itself can get the benefit of your helper functions.
<?php
// protected/config/main.php
require_once( dirname(__FILE__) . '/../components/helpers.php');
...
This done, any part of the application can use the helper functions defined here:
if (startsWith(...))
Note that Qiang has written about this topic as well, though from a somewhat different angle: Qiang's wiki article
Setting/Verifying the Autoload Path ¶
Unlike other frameworks that actually preload your runtime classes — which can be a substantial performance hit — Yii performs autoloading only when the classes are needed.
You define the locations to autoload from in your configuration file in the import
section:
// protected/config/main.php
return array(
...
'import' => array(
'application.models.*',
'application.components.*'
),
...
Yii notes all the files found in these directories and associates them with classes of the same name. If one of the classes is later needed, the file is include
d directly, which provides the class to the application.
Some notes about autoloading:
application.
is an alias for yourprotected/
directory- None of these files is actually loaded by PHP unless the contained classes are actually requested by the application; there is very low overhead in setting up autoloading
- If you wish to use the same autoload paths in console applications, set the same imports in
protected/config/console.php
- Autoloading doesn't search subdirectories: if you want to autoload the
protected/components/mystuff/
folder, use'application.components.mystuff.*'
in addition to'application.components.*'
Multiple classes in one file ¶
It's possible to include more than one class inside a file, though this is only useful in some narrow circumstances.
Autoloading is only done when the desired class name matches the filename, but if a file contains a "main" class used by an application, but it in turn defines minor helper classes that the application won't call directly, this is perfectly legitimate.
Since the application only requests the primary class, that file is autoloaded upon use, but everything in a file is loaded into PHP during include
time. This brings the support functions along with it even though the application may be unaware of these goings-on.
Manual autoloads ¶
The usual autoload path does not pull from the zii
framework hierarchy, which is why full application paths must be used when requesting widgets:
$this->widget('zii.widgets.grid.CGridView', array(
...
This tells Yii to find the file via a specific application path, which is typically from within the framework source code directory itself.
But if one wishes to extend the CGridView class, we have to take the step of importing that specific name before we can use it:
<?php
// protected/components/MyGridView.php
Yii::import('zii.widgets.grid.CGridView');
class MyGridView extends CGridView {
...
Curiously, the import()
statement does not actually load the file: instead, it sets up an autoload so that the provided filename will be loaded as soon as CGridView
is referenced, which it is just two lines later.
This means that any application can now use MyGridView the same as any other class, without an application path:
$this->widget('MyGridView', array(
...
Some observations
is inaccurate or at least can lead to ambiguities. Should disambiguate by adding import
.../components.
CI helpers
it is the same with CI helpers.
components is already imported
@abajja - the
applications.components.*
directory is already imported by the default config file, so you can indeed just create a class file there and Yii will use it.Caution in using directory includes
It is better to include the specific path the the class instead of the directory.
application.path.directory.* is much slower than including each specific path to the class in the import. I made a post about it here: http://zurmo.org/features/major-performance-improvement
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.