PHP: classes using each other - php

I have parent class Color and children, ColorRGBA and ColorHSLA. In class Color I want to use a static functions from these children, but I got error "Class 'Color' not found." Here is the same problem http://forums.codeguru.com/showthread.php?t=469995 but class Color; doesn't seem to work in PHP.
Color.php:
include_once 'ColorRGBA.php';
include_once 'ColorHSLA.php';
class Color{
public static function isValid(&$tokens, $i) {
return ColorRGBA::isValid($tokens, $i) || ColorHSLA::isValid($tokens, $i);
}
}
ColorHLSA.php and similarly ColorRGBA.php
include_once 'Color.php';
class ColorRGBA extends Color {
public static function isValid(&$t, &$i) {
...
}
}
How should I rebuild my class hierarchy or include directives? Or is there any other option how to make my code work?

Yes in PHP there are no "forward declarations" like in C++. That's why class Color; is invalid in PHP.
Now why do you get "Class 'Color' not found."? The problem is that, this line
class ColorRGBA extends Color
gets executed before that line:
class Color {
So Color is indeed not defined. To solve this you could do the following:
class Color{
public static function isValid(&$tokens, $i) {
include_once 'ColorRGBA.php';
include_once 'ColorHSLA.php';
return ColorRGBA::isValid($tokens, $i) || ColorHSLA::isValid($tokens, $i);
}
}
This works because the Color class is now fully defined and the ColorRGBA/ColorHSLA classes are defined only when isValid gets called.
You could also put include_once after the definition of the Color class.

To get around this type of problem, perhaps you should think about implementing a factory class. If that isn't your style, another elegant way around this issue is it use __autoload().
As for the maintenance of the code. It is going to be difficult depending on how many colors you introduce. Why not trying something like:
class Color{
public static function isValid($type, &$tokens, $i){
$class_name = 'Color'.$type;
if (!class_exists($class_name)) {
throw new Exception('Missing '.$class_name.' class.');
}
$class_name::isValid(&$tokens, $i);
}
}
PHP 3.5+

You cannot include ColorRGBA.php in Color.php and Color.php in ColorRGBA.php. You will get circular dependency. This is why you get class not found error.

Related

add more methods to class using include_once [duplicate]

I want to make a PHP class, lets say Myclass.php. Now inside that class I want to define just the class itself and some instance variables. But all the methods must come from a Myclass_methods.php file. Can I just include that file into the class body?
I have good reasons why I want to seperate this. In short, I'll have a backend in which I can change the business logic of a class, while all other things must remain untouched. The system maintains all the ORM and other stuff for me.
But if this is a bad idea, it might be better to re-generate the whole class file after editing the business logic (so, the user-defined methods in this case).
Performance question: If during one request Myclass.php is included just once, actually that Myclass_methods.php should also be included just once. Might be wrong. Experts?
No. You cannot include files in the class body.
In a file defining a class, you may only include files in a method body or outside the class body.
From your description I take you want this:
<?php // MyClass.php
class MyClass
{
protected $_prop;
include 'myclass-methods.php';
}
<?php // myclass-methods.php
public function myMethod()
{
$this->$_prop = 1;
}
Running this code will result in
Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION
What is possible though is this
<?php // MyClass.php
class MyClass
{
protected $_prop;
public function __construct() // or any other method
{
include 'some-functions.php';
foo($b); // echoes 'a';
}
}
<?php // some-functions.php
$b = 'a';
function foo($str)
{
echo $str;
}
Doing it this way, will import the contents of the include file into the method scope, not the class scope. You may include functions and variables in the include file, but not methods. You could but should not put entire scripts into it as well and change what the method does, e.g.
<?php // MyClass.php
// ...
public function __construct($someCondition)
{
// No No Code here
include ($someCondition === 'whatever') ? 'whatever.php' : 'default.php';
}
// ...
<?php // whatever.php
echo 'whatever';
<?php // default.php
echo 'foo';
However, patching the class this way to exhibit different behavior is not how you should do it in OOP. It's just plain wrong and should make your eyes bleed.
Since you want to dynamically change behavior, extending the class is also not a good option (see below why). What you really will want to do is write an interface and make your class use objects implementing this interface, thus making sure the appropriate methods are available. This is called a Strategy Pattern and works like this:
<?php // Meowing.php
interface Meowing
{
public function meow();
}
Now you got the contract that all Meowing Behaviors must obey, namely having a meow method. Next define a Meowing Behavior:
<?php // RegularMeow.php
class RegularMeow implements Meowing
{
public function meow()
{
return 'meow';
}
}
Now to use it, use:
<?php // Cat.php
class Cat
{
protected $_meowing;
public function setMeowing(Meowing $meowing)
{
$this->_meowing = $meowing;
}
public function meow()
{
$this->_meowing->meow()
}
}
By adding the Meowing TypeHint to setMeowing, you make sure that the passed param implements the Meowing interface. Let's define another Meowing Behavior:
<?php // LolkatMeow.php
class LolkatMeow implements Meowing
{
public function meow()
{
return 'lolz xD';
}
}
Now, you can easily interchange behaviors like this:
<?php
require_once 'Meowing.php';
require_once 'RegularMeow.php';
require_once 'LolkatMeow.php';
require_once 'Cat.php';
$cat = new Cat;
$cat->setMeowing(new RegularMeow);
echo $cat->meow; // outputs 'meow';
// now to change the behavior
$cat->setMeowing(new LolkatMeow);
echo $cat->meow; // outputs 'lolz xD';
While you also could have solved the above with inheritance by defining an abstract BaseCat and meow method and then deriving concrete RegularCat and Lolkat classes from that, you have to consider what you want to achieve. If your cats will never change the way they meow, go ahead and use inheritance, but if your RegularCat and Lolkat is supposed to be able to do arbitrary meows, then use the Strategy pattern.
For more design patterns in PHP, check these resources:
http://www.php.net/manual/en/language.oop5.patterns.php
http://www.ibm.com/developerworks/library/os-php-designptrns/
http://www.fluffycat.com/PHP-Design-Patterns/
http://sourcemaking.com/design_patterns
Might it not be an idea to create the core class with the relevant base functionality and then extend this with the required methods - it seems like a more logical approach.
I'll start by saying I'm not too clear why this problem is not best solved using a base class containing the methods, subclasses containing the data, and dynamic class loading. I'll assume you have a good reason.
Once your provider supports PHP 5.4 you can do what you want using traits.
Code File:
if ($pet === 'dog') include 'dog.php';
elseif ($pet === 'cat') include 'cat.php';
else die('Unknown pet');
class Pet {
use PetSounds;
}
$myPet = new Pet();
$myPet->speak();
File cat.php
trait PetSounds {
function speak() { echo 'meow'; }
}
File dog.php
trait PetSounds {
function speak() { echo 'woof'; }
}
You could make this even cleaner by naming both include files the same, putting them in different subdirectories, and using set_include_path() or defining an __autoload() function to select between them. Like I said though, this same problem could be solved better using inheritance. If you have a multiple-inheritance type problem though, if for instance you have four kinds of pets with five kinds of colors with three hair types and you need a different combination of methods for each of the 60 different classes, this is the right solution.
5.4 is currently just a Release Candidate (as of 2/24/2012) and even once released most hosts will not support it for many months - mine took 18 months after 5.3 was released before they would support it. Until then you must write entirely separate and complete class files. You can however format your classes with an eventual change to traits in mind.
Right now you can partially get what you want using magic methods and have an easy upgrade to traits when they are available.
Code File:
if ($pet === 'dog') include 'dog.php';
elseif ($pet === 'cat') include 'cat.php';
else die('Unknown pet');
class Pet {
public function __call($name, array $arguments)
{
array_unshift($arguments, $this);
return call_user_func_array("TraitFunc_$name", $arguments);
}
}
$myPet = new Pet();
$myPet->speak();
File cat.php
function TraitFunc_speak(Pet $that) { echo 'meow'; }
File dog.php
function TraitFunc_speak(Pet $that) { echo 'woof'; }
You are limited however in that your functions can not access private and protected class properties and methods and you can not use this method to provide magic methods such as __get(). Traits will solve both of those limitations.
What about using traits for this? Would that be an acceptable option? This is something I am currently experimenting with and it seems to work quite while.
A simplified version of what I am doing is basically like this. I have an application with shared core files and multiple projects. Within those projects i have modules. I want to have functions that are available for the entire project on a core level but only for that specific project.
My project controller
if(is_file(PROJECT_PATH.'/project_extensions.trait.php')){
// additional functions for this specific project
require_once(PROJECT_PATH.'/project_extensions.trait.php');
}else{
// no additional functions
trait Extensions{};
}
Class Project{
USE Extensions;
// default functions shared between all projects
function shared_stuff(){
}
}
Extensions file
trait Extensions{
// project-specific extensions
function this_project_only(){
echo 'Project Only';
}
}
Module file in the project
class MyModule extends Modules{ // modules extends projects in a different class not relevant here
function do_something(){
echo $this->project_only();
}
}
Since PHP5.4 release you can create dynamic objects like this: https://github.com/ptrofimov/jslikeobject
But this is scarcely the best practice.
Reviving an old question but this is a fairly simple solution. Do you need the common function calls to be exclusive to your class? If not, simply include your common function file(s) within the same scope as your class. You will need to create methods in your class but they will only need to call the common function. Here's a simple SOAP server example:
<?php
include 'post_function.php';
$server = new SoapServer( null, array('uri' => "http://localhost/") );
$server->setClass( 'postsoapclass' );
$server->handle();
class postsoapclass
{
public function animalNoise( $animal )
{
return get_animal_noise($animal);
}
}
?>
post_function.php
<?php
function get_animal_noise($animal)
{
if(strtolower(trim($animal)) == 'pig')
{
return 'Oink';
}
else
{
return 'This animal is mute';
}
}
?>
I have had to do what you are describing in cases where I maintain a free version and a premium version of the same software. Because, as #Gordon noted, you cannot do exactly this:
class SomeClass {
premium_file = "premium.php";
if (file_exists($premium_file)) {
require($premium_file);
}
Instead I do this:
premium_file = "premium.php";
if (file_exists($premium_file)) {
require($premium_file);
}
class SomeClass {
...
For functions you want to reference, create class methods in the main class, and call the included file's method, passing the $this pointer as a parameter. So that I can tell at a glance where functions are, I will prefix the name of the included functions as shown below:
class SomeClass {
...
// Premium functions
public function showlist() {
premium_showlist($this);
}
You can include or require before declaring your class like below:
require 'path-to-file';
class myClass{
function show($uid){
}
}
The answer is yes, for example:
Into class construct, pass to the function (that's into the included file) values as params:
$this->wpd = $this->wpdopt = 'something';
include_once('/common/functions_common.php');
$this->wpdb = wpquery($sql='', $mode='', $this->wpd);
Into the included functions_common.php file:
function wpquery($sql, $mode, $wdp)
{
if(!empty($wdp))
{ return true; } else { return false; }
}
Into class methods:
$sql = "UPDATE ..... SET ... WHERE LOWER(user_email) = . ...";
$this->wpdb = wpquery($sql,'update',$this->wpd);
OR
$retval_var = $this->wpdb = wpquery($sql,'update',$this->wpd);
OR even
$this->var = $this->wpdb = wpquery($sql,'update',$this->wpd);
Cheers to all the lovely and cool people
I came across this recently, and came up with a solution, that helped in my case. I wanted many functions in a class, but the class became bloated, so wanted to separate out the class functions into groups for readability. It took a little time to accomplish, but since the functions of the class didn't rely (much) on $this, I removed "$this" from the class functions and created several helper files to include those functions. When $this was necessary, I could nevertheless move the function into a helper file, by passing $this to the function, adding public set/get functions where necessary. It's a hack, but it's sure to help someone
class myClass
{
var x;
function myClass()
{
$this->x = 0;
}
function myFunc1Group1()
{
$x = $this->x;
$x++;
$this->x = $x;
}
function myFunc2Group1(){}
function myFunc1Group2(){}
function myFunc2Group2(){}
}
can be worked around to
class myClass
{
var x;
function myClass()
{
$this->x = 0;
}
function doSomething()
{
// not called on $this but takes $this as a parameter
myFunc1Group1($this);
}
}
and helper function set 1
function myFunc1Group1($THIS_OBJECT)
{
$x = $THIS_OBJECT->getX();
$x++;
$THIS_OBJECT->setX($x);
}
function myFunc2Group1($THIS_OBJECT){}
and helper function set 2, etc.
Probably not the best route in all cases, but helped me out a lot. Basically the class functions were only to construct and delegate, and the calculations were put into helpers.

Can I Conditionally add a function to my class?

In the framework question 2 answers, themes are an extension of a base theme qa_html_theme_base. In this example I extend the html-function that outputs html.
class qa_html_theme extends qa_html_theme_base
{
function html(){
//Theme goes here
}
}
I want to be able to quickly turn on and off my theme for testing purposes. Is it possible to conditionally extend a class, I tried
class qa_html_theme extends qa_html_theme_base
{
if($debug){
function html(){}
}
}
But it didn't work.
I'm not sure that is possible, this syntax inside a class declaration wouldn't be correct. And if it was, I'm not sure I would recommend it.
But if your function is overriding one of the extended class functions, you could do the following :
class qa_html_theme extends qa_html_theme_base
{
function html(){
global $debug; // added to maintain a correct syntax, but you could as well use $this->debug below, if the value comes from a class property.
if( $debug ){
// your debug code here
}
else {
parent::html();
}
}
}
The only way I can think of to do what you're suggesting (and it's clunky at best) is to conditionally include the class file. So create two class files. We'll call the first theme_html.php and it includes your html() function. The second would be theme_no_html.php and it does NOT have your html() function. This is clunky because you'll have two files to maintain.
Then we do
if($debug) {
include('theme_html.php');
} else {
include('theme_no_html.php');
}
$class = new qa_html_theme();
if my mind is right,
class qa_html_theme extends qa_html_theme_base
{
protected $debug = 1; // or const DEBUG = 1;
/**
* Constructor
*/
public function __construct()
{
if($this->debug){
$this->html();
}else{
// do anything you want
}
}
protected function html(){
//Theme goes here
}
}

Pondering implementation: Instantiate class based on constant without reflection

Second update
I think I've been approaching this problem from the wrong side of the coin. Would I be correct in assuming that I should be making 'First' an abstract class and just finding a way to reference 'Second' and 'Third' at a later time?
Update
Based on some of the feedback, I have added some content to try and clear up what I would like to do. Something similar to this effect.
I know from just looking at the code below that, it is a waste of performance "if" it did work and because it doesn't, know I am approaching the problem from the wrong angle.The end objective isn't all to uncommon at a guess from some of the frameworks I've used.
I'm more trying to base this particular bit of code on the CodeIgniter approach where you can define (what below) is STR_CLASS_NAME in a config file and then at any point through the operation of the program, use it as i have dictated.
STR_CLASS_NAME = 'Second';
class First {
protected $intTestOne = 100;
public function __construct() {
$strClassName = STR_CLASS_NAME;
return new $strClassName();
}
public function TestOne() {
echo $this->intTestOne;
}
protected function TestThreePart() {
return '*Drum ';
}
}
class Second extends First{
/* Override value to know it's working */
protected $intTestOne = 200;
/* Overriding construct to avoid infinite loop */
public function __construct() {}
public function TestTwo() {
echo 'Using method from extended class';
}
public function TestThree() {
echo $this->TestThreePart().'roll*';
}
}
$Test = new First();
$Test->TestOne(); <-- Should echo 200.
$Test->TestTwo(); <-- Should echo 'Using method from extended class'
$Test->TestThree(); <-- Should echo '*Drum roll*'
You may be asking, why do this and not just instantiate Second, well, there are cases when it is slightly different:
STR_CLASS_NAME = 'Third';
class Third extends First{
/* Override value to know it's working */
protected $intTestOne = 300;
/* Overriding construct to avoid infinite loop */
public function __construct() {}
public function TestTwo() {
echo 'Using method from extended class';
}
public function TestThree() {
echo $this->TestThreePart().'snare*';
}
}
$Test = new First();
$Test->TestOne(); <-- Should echo 300.
$Test->TestTwo(); <-- Should echo 'Using method from extended class'
$Test->TestThree(); <-- Should echo '*Drum snare*'
Situation
I have a an abstract class which extends a base class with the actually implementation; in this case a basic DB wrapper.
class DBConnector ()
class DBConnectorMySQLi extends DBConnector()
As you can see, MySQLi is the implementation. Now, dependant upon a value in the configuration process, a constant becomes the class name I wish to use which in this case (as shown below builds DBConnectorMySQLi.
define('STR_DB_INTERFACE', 'MySQLi');
define('DB_CLASS', 'DBConnector'.STR_DB_INTERFACE);
Objective
To have a base class that can be extended to include the implementation
For the code itself not to need know what the name of the implementation actually is
To (in this case) be able to type or use a project accepted common variable to create DBConnectorMySQLi. I.E. $db or something similar. W
Issue
When it comes to actually calling this class, I would like the code to be shown as below. I was wondering whether this is at all possible without the need to add any extra syntax. On a side note, this constant is 100% guaranteed to be defined.
$DBI = new DB_CLASS();
Solution 1
I know it is possible to use a reflection class ( as discussed in THIS QUESTION) and this works via:
$DBI = new ReflectionClass(DB_CLASS);
However, this creates code that is "dirtier" than intended
Solution 2
Start the specific implementation of DBConnectorMySQLi within the constructor function of DBConnector.
define('STR_DB_INTERFACE', 'MySQLi');
define('DB_CLASS', 'DBConnector'.STR_DB_INTERFACE);
class DBConnector() { public function __construct() { $this->objInterface = new DBConnectorMySQLi(); }
class DBConnectorMySQLi()
This however would result in the need to keep on "pushing" variables from one to the other
Any advice is much appreciate
You can use variables when you instantiate a class.
$classname = DB_CLASS;
$DBI = new $classname();
Source: instantiate a class from a variable in PHP?

How do I add a method to an object in PHP?

I've got an Object Oriented library I wanted to add a method to, and while I'm fairly certain I could just go into the source of that library and add it, I imagine this is what's generally known as A Bad Idea.
How would I go about adding my own method to a PHP object correctly?
UPDATE ** editing **
The library I'm trying to add a method to is simpleHTML, nothing fancy, just a method to improve readability. So I tried adding to my code:
class simpleHTMLDOM extends simple_html_dom {
public function remove_node() {
$this->outertext = "";
}
}
which got me: Fatal error: Call to undefined method simple_html_dom_node::remove_node(). So obviously, when you grab an element in simpleHTML it returns an object of type simple_html_dom_node.
If I add the method to simple_html_dom_node my subclass isn't what will be created by simplHTML ... so stuck as to where to go next.
A solution would be to create a new class, that extends the one from your library -- and, then, use your class, which have have all methods of the original one, plus yours.
Here's a (very quick and simple) example :
class YourClass extends TheLibraryClass {
public function yourNewMethod() {
// do what you want here
}
}
And, then, you use your class :
$obj = new YourClass();
$obj->yourNewMethod();
And you can call the methods of the TheLibraryClass class, as yours inherits the properties and methods of that one :
$obj->aMethodFromTheLibrary();
About that, you can take a look at the Object Inheritance section of the manual.
And, as you guessed, modifying a library is definitly a bad idea : you'll have to re-do that modification each time you update the library !
(One day or another, you'll forget -- or one of your colleagues will forget ^^ )
You could do it with inheritance, but you could also use a decorator pattern if you do not need access to any protected members from SimpleHtml. This is a somewhat more flexible approach. See the linked page for details.
class MySimpleHtmlExtension
{
protected $_dom;
public function __construct(simple_html_dom $simpleHtml)
{
$this->_dom = $simpleHtml;
}
public function removeNode(simple_html_dom_node $node)
{
$node->outertext = '';
return $this;
}
public function __call($method, $args)
{
if(method_exists($this->_dom, $method)) {
return call_user_func_array(array($this->_dom , $method), $args));
}
throw new BadMethodCallException("$method does not exist");
}
}
You'd use the above like this
$ext = new MySimpleHtmlExtension( new simple_html_dom );
$ext->load('<html><body>Hello <span>World</span>!</body></html>');
$ext->removeNode( $ext->find('span', 0) );
I don't why adding the method would be bad, however if you want to so without editing the library, your best bet would be to extend the class like so:
class NewClass extends OldClass {
function newMethod() {
//do stuff
}
}
class myExtenstionClass extends SomeClassInLibrary
{
public function myMethod()
{
// your function definition
}
}
As Pascal suggests... read the manual :-)

Can I include code into a PHP class?

I want to make a PHP class, lets say Myclass.php. Now inside that class I want to define just the class itself and some instance variables. But all the methods must come from a Myclass_methods.php file. Can I just include that file into the class body?
I have good reasons why I want to seperate this. In short, I'll have a backend in which I can change the business logic of a class, while all other things must remain untouched. The system maintains all the ORM and other stuff for me.
But if this is a bad idea, it might be better to re-generate the whole class file after editing the business logic (so, the user-defined methods in this case).
Performance question: If during one request Myclass.php is included just once, actually that Myclass_methods.php should also be included just once. Might be wrong. Experts?
No. You cannot include files in the class body.
In a file defining a class, you may only include files in a method body or outside the class body.
From your description I take you want this:
<?php // MyClass.php
class MyClass
{
protected $_prop;
include 'myclass-methods.php';
}
<?php // myclass-methods.php
public function myMethod()
{
$this->$_prop = 1;
}
Running this code will result in
Parse error: syntax error, unexpected T_INCLUDE, expecting T_FUNCTION
What is possible though is this
<?php // MyClass.php
class MyClass
{
protected $_prop;
public function __construct() // or any other method
{
include 'some-functions.php';
foo($b); // echoes 'a';
}
}
<?php // some-functions.php
$b = 'a';
function foo($str)
{
echo $str;
}
Doing it this way, will import the contents of the include file into the method scope, not the class scope. You may include functions and variables in the include file, but not methods. You could but should not put entire scripts into it as well and change what the method does, e.g.
<?php // MyClass.php
// ...
public function __construct($someCondition)
{
// No No Code here
include ($someCondition === 'whatever') ? 'whatever.php' : 'default.php';
}
// ...
<?php // whatever.php
echo 'whatever';
<?php // default.php
echo 'foo';
However, patching the class this way to exhibit different behavior is not how you should do it in OOP. It's just plain wrong and should make your eyes bleed.
Since you want to dynamically change behavior, extending the class is also not a good option (see below why). What you really will want to do is write an interface and make your class use objects implementing this interface, thus making sure the appropriate methods are available. This is called a Strategy Pattern and works like this:
<?php // Meowing.php
interface Meowing
{
public function meow();
}
Now you got the contract that all Meowing Behaviors must obey, namely having a meow method. Next define a Meowing Behavior:
<?php // RegularMeow.php
class RegularMeow implements Meowing
{
public function meow()
{
return 'meow';
}
}
Now to use it, use:
<?php // Cat.php
class Cat
{
protected $_meowing;
public function setMeowing(Meowing $meowing)
{
$this->_meowing = $meowing;
}
public function meow()
{
$this->_meowing->meow()
}
}
By adding the Meowing TypeHint to setMeowing, you make sure that the passed param implements the Meowing interface. Let's define another Meowing Behavior:
<?php // LolkatMeow.php
class LolkatMeow implements Meowing
{
public function meow()
{
return 'lolz xD';
}
}
Now, you can easily interchange behaviors like this:
<?php
require_once 'Meowing.php';
require_once 'RegularMeow.php';
require_once 'LolkatMeow.php';
require_once 'Cat.php';
$cat = new Cat;
$cat->setMeowing(new RegularMeow);
echo $cat->meow; // outputs 'meow';
// now to change the behavior
$cat->setMeowing(new LolkatMeow);
echo $cat->meow; // outputs 'lolz xD';
While you also could have solved the above with inheritance by defining an abstract BaseCat and meow method and then deriving concrete RegularCat and Lolkat classes from that, you have to consider what you want to achieve. If your cats will never change the way they meow, go ahead and use inheritance, but if your RegularCat and Lolkat is supposed to be able to do arbitrary meows, then use the Strategy pattern.
For more design patterns in PHP, check these resources:
http://www.php.net/manual/en/language.oop5.patterns.php
http://www.ibm.com/developerworks/library/os-php-designptrns/
http://www.fluffycat.com/PHP-Design-Patterns/
http://sourcemaking.com/design_patterns
Might it not be an idea to create the core class with the relevant base functionality and then extend this with the required methods - it seems like a more logical approach.
I'll start by saying I'm not too clear why this problem is not best solved using a base class containing the methods, subclasses containing the data, and dynamic class loading. I'll assume you have a good reason.
Once your provider supports PHP 5.4 you can do what you want using traits.
Code File:
if ($pet === 'dog') include 'dog.php';
elseif ($pet === 'cat') include 'cat.php';
else die('Unknown pet');
class Pet {
use PetSounds;
}
$myPet = new Pet();
$myPet->speak();
File cat.php
trait PetSounds {
function speak() { echo 'meow'; }
}
File dog.php
trait PetSounds {
function speak() { echo 'woof'; }
}
You could make this even cleaner by naming both include files the same, putting them in different subdirectories, and using set_include_path() or defining an __autoload() function to select between them. Like I said though, this same problem could be solved better using inheritance. If you have a multiple-inheritance type problem though, if for instance you have four kinds of pets with five kinds of colors with three hair types and you need a different combination of methods for each of the 60 different classes, this is the right solution.
5.4 is currently just a Release Candidate (as of 2/24/2012) and even once released most hosts will not support it for many months - mine took 18 months after 5.3 was released before they would support it. Until then you must write entirely separate and complete class files. You can however format your classes with an eventual change to traits in mind.
Right now you can partially get what you want using magic methods and have an easy upgrade to traits when they are available.
Code File:
if ($pet === 'dog') include 'dog.php';
elseif ($pet === 'cat') include 'cat.php';
else die('Unknown pet');
class Pet {
public function __call($name, array $arguments)
{
array_unshift($arguments, $this);
return call_user_func_array("TraitFunc_$name", $arguments);
}
}
$myPet = new Pet();
$myPet->speak();
File cat.php
function TraitFunc_speak(Pet $that) { echo 'meow'; }
File dog.php
function TraitFunc_speak(Pet $that) { echo 'woof'; }
You are limited however in that your functions can not access private and protected class properties and methods and you can not use this method to provide magic methods such as __get(). Traits will solve both of those limitations.
What about using traits for this? Would that be an acceptable option? This is something I am currently experimenting with and it seems to work quite while.
A simplified version of what I am doing is basically like this. I have an application with shared core files and multiple projects. Within those projects i have modules. I want to have functions that are available for the entire project on a core level but only for that specific project.
My project controller
if(is_file(PROJECT_PATH.'/project_extensions.trait.php')){
// additional functions for this specific project
require_once(PROJECT_PATH.'/project_extensions.trait.php');
}else{
// no additional functions
trait Extensions{};
}
Class Project{
USE Extensions;
// default functions shared between all projects
function shared_stuff(){
}
}
Extensions file
trait Extensions{
// project-specific extensions
function this_project_only(){
echo 'Project Only';
}
}
Module file in the project
class MyModule extends Modules{ // modules extends projects in a different class not relevant here
function do_something(){
echo $this->project_only();
}
}
Since PHP5.4 release you can create dynamic objects like this: https://github.com/ptrofimov/jslikeobject
But this is scarcely the best practice.
Reviving an old question but this is a fairly simple solution. Do you need the common function calls to be exclusive to your class? If not, simply include your common function file(s) within the same scope as your class. You will need to create methods in your class but they will only need to call the common function. Here's a simple SOAP server example:
<?php
include 'post_function.php';
$server = new SoapServer( null, array('uri' => "http://localhost/") );
$server->setClass( 'postsoapclass' );
$server->handle();
class postsoapclass
{
public function animalNoise( $animal )
{
return get_animal_noise($animal);
}
}
?>
post_function.php
<?php
function get_animal_noise($animal)
{
if(strtolower(trim($animal)) == 'pig')
{
return 'Oink';
}
else
{
return 'This animal is mute';
}
}
?>
I have had to do what you are describing in cases where I maintain a free version and a premium version of the same software. Because, as #Gordon noted, you cannot do exactly this:
class SomeClass {
premium_file = "premium.php";
if (file_exists($premium_file)) {
require($premium_file);
}
Instead I do this:
premium_file = "premium.php";
if (file_exists($premium_file)) {
require($premium_file);
}
class SomeClass {
...
For functions you want to reference, create class methods in the main class, and call the included file's method, passing the $this pointer as a parameter. So that I can tell at a glance where functions are, I will prefix the name of the included functions as shown below:
class SomeClass {
...
// Premium functions
public function showlist() {
premium_showlist($this);
}
You can include or require before declaring your class like below:
require 'path-to-file';
class myClass{
function show($uid){
}
}
The answer is yes, for example:
Into class construct, pass to the function (that's into the included file) values as params:
$this->wpd = $this->wpdopt = 'something';
include_once('/common/functions_common.php');
$this->wpdb = wpquery($sql='', $mode='', $this->wpd);
Into the included functions_common.php file:
function wpquery($sql, $mode, $wdp)
{
if(!empty($wdp))
{ return true; } else { return false; }
}
Into class methods:
$sql = "UPDATE ..... SET ... WHERE LOWER(user_email) = . ...";
$this->wpdb = wpquery($sql,'update',$this->wpd);
OR
$retval_var = $this->wpdb = wpquery($sql,'update',$this->wpd);
OR even
$this->var = $this->wpdb = wpquery($sql,'update',$this->wpd);
Cheers to all the lovely and cool people
I came across this recently, and came up with a solution, that helped in my case. I wanted many functions in a class, but the class became bloated, so wanted to separate out the class functions into groups for readability. It took a little time to accomplish, but since the functions of the class didn't rely (much) on $this, I removed "$this" from the class functions and created several helper files to include those functions. When $this was necessary, I could nevertheless move the function into a helper file, by passing $this to the function, adding public set/get functions where necessary. It's a hack, but it's sure to help someone
class myClass
{
var x;
function myClass()
{
$this->x = 0;
}
function myFunc1Group1()
{
$x = $this->x;
$x++;
$this->x = $x;
}
function myFunc2Group1(){}
function myFunc1Group2(){}
function myFunc2Group2(){}
}
can be worked around to
class myClass
{
var x;
function myClass()
{
$this->x = 0;
}
function doSomething()
{
// not called on $this but takes $this as a parameter
myFunc1Group1($this);
}
}
and helper function set 1
function myFunc1Group1($THIS_OBJECT)
{
$x = $THIS_OBJECT->getX();
$x++;
$THIS_OBJECT->setX($x);
}
function myFunc2Group1($THIS_OBJECT){}
and helper function set 2, etc.
Probably not the best route in all cases, but helped me out a lot. Basically the class functions were only to construct and delegate, and the calculations were put into helpers.

Categories