If I want to add methods to my file from other classes or a script not using OOP should I include() the file or extend it in my class?
Include and create a new instance of this class.
For OOP classes you would have to decide if the object needs to be an instance. If its just a utility of functions you could use static methods like below:
class EmailFilter
{
public function clean($email)
{
...
}
public static function filter($email) {
....
}
}
You would then require the code and use
Static
EmailFilter::filter($email);
Object
$filter = new EmailFilter();
foreach ($emails as $email) {
$filter->clean($email);
}
if its non-oop functions you can include/require the code and use the functions as needed within your code.
Related
I use this code to load classes
function __autoload($className)
{
$files = dirname(__FILE__).'/public/class/'.$className.'.php';
if(file_exists($files))
{
include_once($files);
}
}
does anyone know how to retrieve the function automatically, too? Thank you.
Autoloader function registered spl_autoload_register() can be used to load classes, but not functions. Wrap your functions in class or classes to utilize autoloading, i.e.
class Utils {
static function foo() {
..
}
}
then call it static way:
Utils::foo();
and you can have it autoloaded when needed. See more infromation on autoloading in PHP manual.
Yes, you can automatically load classes using the autoload feature, but no, you can't do the same for functions.
So I have a config.php file, wich is included on top of every page on the site before the tag. This file uses __autoload() to get all the php classes I use. Then, after autoloading them I assign the classes to variables like so...
$myclass = new Myclass();
$mysecondclass = new MySecondClass();
When I want to call $mysecondclass in $myclass, I get an undefined variable error. This is of course, because $mysecondclass was not defined before $myclass. How do I fix this where I can define all classes from any other class?
Thanks for any help:)
The best OOP approach would be to use a superObject with properties which are objects of other classes.
class Context{
var $myClass;
var $myOtherClass;
var $db;
//...
}
In your MyClass
class MyClass{
var $context;
public function __construct(&context){
$this->context = $context;
}
public function otherFunction(){
$this->context->myOtherClass->functionFromOtherClass();
}
}
You should be instantiating these classes using Factory method or any mechanism to manage objects.
To initialize MyClass you would implement something like this.
ObjectFactory::createObject('MyClass',$context);
$myclass is not Myclass it is an instance of Myclass (an object). Objects are not classes. If you want to use a new instance of MySecondClass inside of an instance of Myclass, just instantiate it in there.
Your question also deals with scope. You have created these two objects in the global scope. They are not automatically accessible within one another. If you have some object which you will have only one instance of and which you want to be global and accessible by others, you can import it into their scope with the global keyword. However, this is not usually the best way to go about it. Instead, you may want to look up the Singleton Pattern. It gives you a way to ensure that a particular class is only instantiated one time and gives you a way to access the object that has been created as a result of that instantiation.
The registry pattern is also an easy way to access "global" object anywhere in your code.
You can Take a look at Zend_Registry : http://framework.zend.com/manual/en/zend.registry.using.html
$myclass = new Myclass();
$mysecondclass = new MySecondClass();
Zend_Registry::set('mysecondclass', $mysecondclass);
$myclass->doSomething();
class Myclass
{
public function doSomething()
{
// use $mysecondclass via the registry
Zend_Registry::get('mysecondclass')->methodFromSecondClass();
}
}
class MySecondClass
{
public function methodFromSecondClass()
{
return true;
}
}
According to how your classes works, think about extending them... Extending MyClass to MySecondClass automatically gives access to parent properties / functions.
MyClass
class MyClass{
function myFunction(){
// code here
}
}
MySecondClass
class MySecondClass extends MyClass{
function __construct(){
$this->myFunction();
}
}
I am interested in learning autoloading, but new to PHP.
I am reading the book "PHP in Action" which writes the autoload method like
function __autoload($className) {
include_once __autoloadFilename($className);
}
function __autoloadFilename($className) {
return str_replace('_','/',$className).".php";
}
I want to pack these methods in a class. will it be better to pack them in an abstract class?
Or in normal class and including it in index.php?
How effeciently I can use the autoloading feature?
Thanks
Securing an autoloader, ensure:
That the file you try to load is actually a file. include is pretty much like eval. For example disallow url inclusion via the php configuration.
That the classname is actually a syntactically correct classname. Could be helpful to secure things ;)
You can also white-list namespaces and/or classnames that are appropriate for your concrete autoloader.
Create a class as an autoloader, you must not take the static way, you can just assign any callback with spl_autoload_register, so you can register multiple autoloaders.
Some quickly written autoloader class stub:
class MyAutoloader
{
public function __construct()
{
$this->register();
}
public function register()
{
spl_autoload_register(array($this,'autoload'));
}
public function autoload($classname)
{
if ($this->isInvalidClassName($classname)) return;
$file = $this->getFileForClassName($classname);
if ($this->isInalidFile($file)) return;
require $file; // bail out fatally.
}
...
}
$myAutoloader = new MyAutoloader();
It's up to you. I use a dedicated class called Loader with a method called load(), which I activate with:
spl_autoload_register( 'Utility_Loader::load' );
I want create a helper class that containing method like cleanArray, split_char, split_word, etc.
The helper class it self will be used with many class. example :
Class A will user Helper, Class B, Class C, D, E also user Helper Class
what the best way to write and use helper class in PHP ?
what i know is basic knowledge of OOP that in every Class that use Helper class must create a helper object.
$helper = new Helper();
It that right or may be some one can give me best way to do that.
I also will create XXX Class that may use Class A, B, C, etc.
UPDATE : ->FIXED my fault in split_word method :D
Based on Saul, Aram Kocharyan and alex answer, i modified my code, but its dont work, i dont know why.
<?php
class Helper {
static function split_word($text) {
$array = mb_split("\s", preg_replace( "/[^\p{L}|\p{Zs}]/u", " ", $text ));
return $this->clean_array($array);
}
static function split_char($text) {
return preg_split('/(?<!^)(?!$)/u', mb_strtolower(preg_replace( "/[^\p{L}]/u", "", $text )));
}
}
?>
and i use in other Class
<?php
include "Helper.php";
class LanguageDetection {
public function detectLanguage($text) {
$arrayOfChar = Helper::split_char($text);
$words = Helper::split_word($text);
return $arrayOfChar;
}
}
$i = new Detection();
print_r($i->detectLanguage("ab cd UEEef する ح خهعغ فق 12 34 ٢ ٣ .,}{ + _"));
?>
Helper classes are usually a sign of lack of knowledge about the Model's problem domain and considered an AntiPattern (or at least a Code Smell) by many. Move methods where they belong, e.g. on the objects on which properties they operate on, instead of collecting remotely related functions in static classes. Use Inheritance for classes that share the same behavior. Use Composition when objects are behaviorally different but need to share some functionality. Or use Traits.
The static Utils class you will often find in PHP is a code smell. People will throw more or less random functions into a class for organizing them. This is fine when you want to do procedural coding with PHP<5.2. As of 5.3 you would group those into a namespace instead. When you want to do OOP, you want to avoid static methods. You want your objects to have High Cohesion and Low Coupling. Static methods achieve the exact opposite. This will also make your code less testable.
Are Helper Classes Evil?
Killing the Helper class, part two
Functional Decomposition AntiPattern
Is the word "Helper" in a class name a code smell?
Moreover, every Class that use Helper class must create a helper object is a code smell. Your collaborators should not create other collaborators. Move creation of complex object graphs into Factories or Builders instead.
As a rule of thumb, helpers should contain functionality that is common but has no special designation under the overall architecture of the application.
Suffix the classname with Helper
Use static methods whenever possible
In short:
// Helper sample
//
class ConversionHelper {
static function helpThis() {
// code
}
static function helpThat() {
// code
}
}
// Usage sample
//
class User {
function createThings() {
$received = ConversionHelper::helpThis();
}
}
Instead of creating static class , you should just write simple functions , and include that file at the index/bootstrap file (you can even use namespaces with it).
Instead of:
class Helper {
static function split_word($text) { ...
static function split_char($text) { ...
}
It should be:
namespace Helper;
function split_word($text) { ...
function split_char($text) { ...
There is no point wrapping it all up in a class. Just because you put it in a class doesn't make it object oriented .. actually it does the exact oposite.
You could create a class with static methods...
class Str {
public static function split_char($str, $chr) {
...
}
}
You could also namespace a bunch of functions with a namespace, but I think the former is preferred.
Use public static methods in the class as such:
/* Common utility functions mainly for formatting, parsing etc. */
class CrayonUtil {
/* Creates an array of integers based on a given range string of format "int - int"
Eg. range_str('2 - 5'); */
public static function range_str($str) {
preg_match('#(\d+)\s*-\s*(\d+)#', $str, $matches);
if (count($matches) == 3) {
return range($matches[1], $matches[2]);
}
return FALSE;
}
// More here ...
}
Then invoke them like this:
CrayonUtil::range_str('5-6');
If in another file, use the following at the top:
require_once 'the_util_file.php';
I am fairly new to OO programming...
I am building what will eventually turn out to be a large library of classes to be used throughout my site. Clearly, loading the entire library on every page is a waste of time and energy...
So what I would like to do is require a single "config" php class file on each page, and be able to "call" or "load" other classes as needed - thus extending my class according to my needs.
From what I know, I can't use a function in the config class to simply include() other files, because of scope issues.
What are my options? How do developers usually handle this problem, and what is the most stable?
You can use __autoload() or create an Object Factory that will load the files required when you need them.
As an aside, if you're having scope issues with your library files, you should probably refactor your layout. Most libraries are sets of classes that can be instantiated in any scope.
The following is an example very basic object factory.
class ObjectFactory {
protected $LibraryPath;
function __construct($LibraryPath) {
$this->LibraryPath = $LibraryPath;
}
public function NewObject($Name, $Parameters = array()) {
if (!class_exists($Name) && !$this->LoadClass($Name))
die('Library File `'.$this->LibraryPath.'/'.$Name.'.Class.php` not found.');
return new $Name($this, $Parameters);
}
public function LoadClass($Name) {
$File = $this->LibraryPath.'/'.$Name.'.Class.php'; // Make your own structure.
if (file_exists($File))
return include($File);
else return false;
}
}
// All of your library files should have access to the factory
class LibraryFile {
protected $Factory;
function __construct(&$Factory, $Parameters) {
$this->Factory = $Factory;
}
}
Sound like you want autoload and spl_autoload_register if you are using classes from 3rd party libraries.