I know it is basic php question but I had something that I didn't understand, it is about the return; when I call a function, the bellow code is just an exemple.
Case : In TEST2 when I do my check then I return, that return; do the job and stop the execution of the next code TEST3 Good.
Now in TEST1 I Call a function _checkThat(), and this function do a check then redirect. the problem is it returns shure but the next code will also be executed TEST2 and TEST3 Why ? why when I put the content of that function directly in TEST1 it returns and stop the execution of next code ?
<?php class Some_Class_IndexController extends Some_Other_Controller_Front_Action
{
$name = $this->getRequest()->getParam('name'); //Output: "john"
$email = $this->getRequest()->getParam('email'); //Output: "john#gmail.com"
$phone = $this->getRequest()->getParam('phone'); //Output: 09000000
//TEST1
if(isset($name)) {
$this->_checkThat($name);
}
//TEST2
if(isset($email)) {
if($email === "john#gmail.com") {
//some code to redirect to another page
return;
} else {
//some code to redirect to another page
return;
}
}
//TEST3
if(isset($name)) {
$this->_checkthat();
}
private function _checkThat($name) {
if ($name !== "john") {
//some code to redirect to another page
return;
}
}
}
Other question, Can I use continue; in this case :
if(isset($name)) {
Mage::log('check passed'); //This just write in logs
continue; // or something else
} else if (!isset($name)) {
// some code
}
Although as already mentioned in comments your example code is not correct, your problem here:
if(isset($name)) {
$this->_checkThat($name);
}
is that you do nothing with result returned by _checkThat(). And obviously you should return it:
if(isset($name)) {
return $this->_checkThat($name);
}
As a sidenote, I should mention that naming methods with _ to mark them protected/private is out-of-date practice since php5.
Here is a simple guide.
Inheritance – reusing code the OOP way
Inheritance is a fundamental capability/construct in Object oriented programming where you can use one class, as the base/basis for another class or many other classes.
Why do it?
Doing this allows you to efficiently reuse the code found in your base class.
Say, you wanted to create a new employee class since we can say that employee is a type/kind of `person’, they will share common properties and methods.
Making some sense?
In this type of situation, inheritance can make your code lighter because you are reusing the same code in two different classes. But unlike old-school PHP:
You only have to type the code out once.
The actual code being reused, can be reused in many (unlimited) classes
but it is only typed out in one place conceptually, this is sort-of
like PHP includes().
Take a look at the sample PHP code:
// 'extends' is the keyword that enables inheritance
class employee extends person
{
function __construct($employee_name) {
$this->set_name($employee_name);
}
}
Reusing code with inheritance:
Because the class employee is based on the class person, employee automatically has all the public and protected properties and methods of ‘person’.
Nerd note: Nerds would say that employee is a type of person.
The code:
class employee extends person
{
function __construct($employee_name){
$this->set_name($employee_name);
}
}
Notice how we are able to use set_name() in employee, even though we did not declare that method in the employee class. That is because we already created set_name() in the class person.
Nerd Note: the person class is called (by nerds,) the base class or the parent class because it is the class that the employee is based on. This class hierarchy can become important down the road when your projects become more complex.
Reusing code with inheritance:
As you can see in the code snippet below, we can call get_name on our employee object, courtesy of person.
The code:
<?phpinclude("class_lib.php"); ?>
<?php
// Using our PHP objects in our PHP pages.
$stefan = new person("Stefan Mischook");
echo "Stefan's full name: " . $stefan->get_name();
$james = new employee("Johnny Fingers");
echo "---> " . $james->get_name();
?>
This is a classic example of how OOP can reduce the number of lines of code (don’t have to write the same methods twice) while still keeping your code modular and much easier to maintain.
Overriding methods 1
Sometimes (when using inheritance,) you may need to change how a method works from the base class.
For example, let us say set_name() method in the 'employee' class, had to do something different than what it does in the person class.
You override the person classes version of set_name(), by declaring the same method in employee.
The code snippet:
<?php
class person
{
protected function set_name($new_name) {
if ($new_name != "Jimmy Two Guns") {
$this->name = strtoupper($new_name);
}
}
}
class employee extends person
{
protected function set_name($new_name) {
if ($new_name == "Stefan Sucks") {
$this->name = $new_name;
}
}
}
?>
Notice how set_name() is different in the employee class from the version found in the parent class: person.
<Overriding methods: 2
Sometimes you may need to access your base class’s version of a method you overrode in the derived (sometimes called ‘child’) class.
In our example, we overrode the set_name() method in the employee class. Now I have
used this code:
hperson::set_name($new_name);
to access the parent class’ (person) version of the set_name() method.
The code:
<?php
class person
{
// explicitly adding class properties are optional - but
// is good practice
var $name;
function __construct($persons_name) {
$this->name = $persons_name;
}
public function get_name() {
return $this->name;
}
// protected methods and properties restrict access to
// those elements.
protected function set_name($new_name) {
if ($this->name != "Jimmy Two Guns") {
$this->name = strtoupper($new_name);
}
}
}
// 'extends' is the keyword that enables inheritance
class employee extends person
{
protected function set_name($new_name) {
if ($new_name == "Stefan Sucks") {
$this->name = $new_name;
}
else if ($new_name == "Johnny Fingers") {
person::set_name($new_name);
}
}
function __construct($employee_name)
{
$this->set_name($employee_name);
}
}
?>
Notes: Using the symbol:
::
… allows you to specifically name the class where you want PHP to search for a method:
person::set_name()
… tells PHP to search for set_name() in the person class.
There is also a shortcut if you just want refer to current class’s parent – by using the parent keyword.
The code:
protected function set_name($new_name)
{
if ($new_name == "Stefan Sucks") {
$this->name = $new_name;
}
else if ($new_name == "Johnny Fingers") {
parent::set_name($new_name);
}
}
Related
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.
I am testing a class that has a dependency injected. In my infinite cleverness, I scattered references to the dependency's class constant throughout my code.
(Sorry for the stupid example, wanted to deviate from foobar.)
<?php
class Book_PhoneBook extends Book {
private $author;
public function __construct(Author $author) {
$this->author = $author;
}
public function getCover() {
return $this->author->getTitle(Author::NAME_UNKNOWN) . ' - YELLOW PAGES';
}
}
class Author {
const NAME_UNKNOWN = 'anonymous';
public function getTitle($nameStyle) {
//do complicated calculation of author name
if ($nameStyle == $this::NAME_UNKNOWN) {
$name = "Anonymous";
}
//do further complicated calculations, modifying $name
return $name;
}
}
My problem is with unit tests! I'm getting "Fatal error: Undefined class constant 'NAME_UNKNOWN'" when I mock Author. The whole purpose of mocking is to avoid including the Author class file, so what is the correct way to handle that constant?
I could split Author into several objects or split the method that relies on the constant, but that would incur much repetition.
The fact that you are using the class constant from Author means that you are dependent on having that class available in your code and thus also in your test. So in order to test Book_PhoneBook you need to have an Author class with the constant. If the class constant is going to be a series of flags that you will need to pass to your class, you will need to have the class available and in your test make sure that the original class is loaded. You are dependent on that class for Book_PhoneBook::getCover().
You can also just use the string value of the class constant in your Book_PhoneBook though that sort of defeats the purpose of making it a constant so that you are able to change the value in one place.
With your example, it is a little tricky to get an idea of what you are trying to achieve but since you want to remove the dependency on Author in Book_PhoneBook, I would change it to something like this:
<?php
class Book_PhoneBook extends Book {
private $author;
public function __construct(Author $author) {
$this->author = $author;
}
public function getCover() {
return $this->author->getTitle() . ' - YELLOW PAGES';
}
}
class Author {
const NAME_UNKNOWN = 'anonymous';
public function __construct($nameStyle) {
$this->nameStyle = $nameStyle;
}
public function getTitle() {
//do complicated calculation of author name
if ($this->nameStyle == $this::NAME_UNKNOWN) {
$name = "Anonymous";
}
//do further complicated calculations, modifying $name
return $name;
}
}
This solution does have the problem that adding other options is difficult for getTitle. And without having a better idea of what you are trying to achieve with getTitle, I am not able to offer a better solution.
For anybody having a problem like this in the future, I ended up with this based on #Schleis' answer:
class Author {
const NAME_UNKNOWN = 'anonymous';
private function getTitle($nameStyle) {
//do stuff, taking $nameStyle into account
return $name;
}
public function getAnonymousTitle() {
return $this->getTitle($this::NAME_UNKNOWN);
}
}
I've been trying for a long time now to find a correct design using PHP to achieve what I want, but everything I've tried failed and I'm guessing it's probably because I'm not looking from the right angle, so I wish some of you can enlighten me and give me some good advice!
The design might seem a little weird at first, but I assure you it's not because I like to make things complicated. For the sake of simplicity I'm only giving the minimal structure of my problem and not the actual code. It starts with these:
<?php
// ------------------------------------------------------------------------
class Mother_A
{
const _override_1 = 'default';
protected static $_override_2 = array();
public static function method_a()
{
$c = get_called_class();
// Uses $c::_override_1 and $c::$_override_2
}
}
// ------------------------------------------------------------------------
class Mother_B extends Mother_A
{
public function method_b()
{
// Uses self::method_a()
}
}
Class Mother_A defines a static method that uses constants and statics to be overridden by children. This allows to define a generic method (equivalent of a "template" method) in the derived class Mother_B. Neither Mother_A or Mother_B are intended to be instanciated, but Mother_B should not be abstract. This exploits Late Static Binding, which I find very useful btw.
Now comes my problem. I want to define two classes, in n distinct 'situations' (situation 1, situation 2, etc):
<?php
// ------------------------------------------------------------------------
class Child_A_Situation_k extends Mother_A
{
// Uses method_a
}
// ------------------------------------------------------------------------
class Child_B_Situation_k extends Mother_B
{
// Uses method_a and method_b
}
Of course I'm not actually giving these stupid names; both classes have different names in each situation, but both follow the same derivation pattern from Mother_A and Mother_B. However, in each individual case ('situation'), both classes need the exact same constants/static override, and I don't know how to do that without duplicating the override manually in both classes.
I tried many things, but the closest I got was to implement an interface Interface_Situation_k that defined constants and statics for the situation k, and make both children implement this interface. Of course, you can't define statics in an interface, so it failed, but you get the idea. I would have traded the interface for a class, but then there's no multiple inheritance in PHP, so it's not valid either. :/ I'm really stuck, and I can't wait to read a possible solution! Thanks in advance!
this is the best i can do, i don't think there is a way to do it with less code.
Look at the comments inside the code for more info.
Fully working code:
<?php
class Mother_A
{
// you're using '_override_1' as a variable, so its obviously not a constant
// also i made it public for the setSituation function,
// you could keep it protected and use reflections to set it
// but i dont really see a reason for that.
// if you want that, look up how to set private/protected variables
public static $_override_1 = 'default';
public static $_override_2 = array();
public static function method_a()
{
$c = get_called_class();
var_dump($c::$_override_1);
var_dump($c::$_override_2);
// Uses $c::_override_1 and $c::$_override_2
}
public static function setSituation($className)
{
$c = get_called_class();
// iterate through the static properties of $className and $c
// and when the you find properties with the same name, set them
$rBase = new ReflectionClass($c);
$rSituation = new ReflectionClass($className);
$staBase = $rBase->getStaticProperties();
$staSituation = $rSituation->getStaticProperties();
foreach($staSituation as $name => $value)
{
if(isset($staBase[$name])) $c::$$name = $value;
}
}
}
// ------------------------------------------------------------------------
class Mother_B extends Mother_A
{
public function method_b()
{
self::method_a();
}
}
class Situation_k
{
public static $_override_1 = 'k';
public static $_override_2 = array('k','k');
}
class Child_A_Situation_k extends Mother_A { }
Child_A_Situation_k::setSituation('Situation_k');
// This is not as short as writing 'extends Mother_A, Situation_k'
// but i think you wont get it shorter
class Child_B_Situation_k extends Mother_B { }
Child_B_Situation_k::setSituation('Situation_k');
echo '<pre>';
Child_A_Situation_k::method_a();
echo "\n";
Child_B_Situation_k::method_a();
echo "\n";
Child_B_Situation_k::method_b();
echo "\n";
echo '</pre>';
?>
I am trying to inherit a set of different parent class and even not inherit any class but as per some condition.
For example, Here is what I would like to do
$choice = 2;
switch($choice) {
case 1:
class child extends parent1
break;
case 2:
class child extends parent2
break;
default:
class child
//extend nothing
break;
}
I think you can figure out what I am trying achieve here.
parent classes
class car { }
Child classes
class ferari extends car { }
class ford extends car { }
grandchild classes
class automaticcar { }
class manualcar { }
Now this grandclasses need to interit a parent as per the value sent from the form using post. Something like this
$brand = $_POST['brand'];
if(isset($brand) && !empty($brand)) {
class automaticcar extends $brand
}
else {
class automaticcar extends car //or even nothing
}
//And then I wish to write the remaining portion of the class
The kind of inheritance you are trying to obtain is not attainable using a language which inheritance is based on classes.
The closer solution you can obtain is using a sort of decorator pattern with a bit of magic methods. something like this:
$choice = 2;
switch($choice) {
case 1:
$obj = new child(new parent1());
break;
case 2:
$obj = new child(new parent2());
break;
default:
//extend nothing
$obj = new child();
break;
}
with child being similar to this:
class child {
function __construct($composeObj) {
$this->core = $composeObj;
// wathever you need to iniyialize
}
function __call($name, $params) {
return call_user_func(array($sthis->core, $name), $parameters);
}
// other functions
} // eo child
This solution have some caveats but if you can cope with them (the object does not belongs to the family of the composited object, call_user_func does not pass the parameters by reference) this is a suitable solution.
A better solution is the factory approach suggested by sandeepan but you already refused it.
A Ferrari is not different to a Ford in the properties or methods it supplies. They are both still cars. They just have different values for their attributes. Creating a spezialized subclass shouldn't be necessary for that. Instead try this route:
class Car
{
protected $_manufacturer;
protected $_engine;
protected $_gear;
protected $_price;
protected $_color;
public function __construct($manufacturer, $engine, $gear, $price, $color)
{
// setting properties
}
}
class CarFactory
{
public static function createFerrari()
{
$engine = new Engine(500); // PS
$gear = new Gear(6, 'manual');
return new Car('Ferrari', $engine, $gear, '250000', 'red');
}
public static function createFord()
{
$engine = new Engine(90); // PS
$gear = new Gear(5, 'automatic');
return new Car('Ford', $engine, $gear, '50000', 'black');
}
// other car creation methods ...
}
If you extend a class, you are creating an is-a relationship. The subclass is a specialized parent class. Gear and Engine is nothing a Car is, but something a car has. Whenever you can describe a class to have something, it's a candidate for it's own class or for just being an attribute. Whether it should be it's own class depends on whether the thing encapsulated own unique state and responsibiliy.
First off, I really don't think you understand object oriented principles well enough to ask for this functionality. It's not really needed with the style of OOP that PHP implements.
You are requesting something like conditional mix-ins. It's possible to implement it, but it is a huge kludge and should be avoided. Here's something I put together a while ago when I was just testing some concepts:
<?php
class Mixin
{
private $objects = array();
private $funcs = array();
public function addMixin(Mixable $object)
{
$exported_vars = $object->exportVars();
foreach ($exported_vars as $key => &$ref)
$this->$key = &$ref;
$vars = array();
foreach (array_keys(get_object_vars($this)) as $key)
$vars[$key] = &$this->$key;
$object->importVars($vars);
$this->objects[] = $object;
}
public function __call($method, $args)
{
if (!isset($this->funcs[$method]))
{
$found = false;
foreach ($this->objects as $obj)
{
if (method_exists($obj, $method))
{
$found = true;
$this->funcs[$method] = array($obj, $method);
break;
}
}
if (!$found)
throw new Exception("method doesn't exist");
}
return call_user_func_array($this->funcs[$method], $args);
}
}
class Mixable
{
public function exportVars()
{
$vars = array();
foreach (array_keys(get_object_vars($this)) as $key)
{
$vars[$key] = &$this->$key;
}
return $vars;
}
public function importVars($vars)
{
foreach ($vars as $key => &$ref)
{
$this->$key = &$ref;
}
}
}
?>
You would use it like:
<?php
class Parent1 extends Mixable
{
protected $name = 'Parent 1';
public function p1()
{
print "P1\n";
}
}
class Parent2 extends Mixable
{
protected $name = 'Parent 2';
public function p2()
{
print "P2\n";
}
}
class Child1 extends Mixin
{
public function whoAmI()
{
print $this->name."\n";
}
}
$foo = new Child1();
if (mt_rand(1, 2) == 1)
{
$foo->addMixin(new Parent1());
$foo->p1();
}
else
{
$foo->addMixin(new Parent2());
$foo->p2();
}
$foo->whoAmI();
?>
Please do not try to use the code! Even if it were production ready, it's a terrible concept. I put it here to show you how it would work.
I think what you really should be doing is something more like a Factory pattern: build a CarFactory class that returns a properly subclassed Car. (Or you could create a factory method within a Car class.)
It could be something like Car::get($_POST['brand']).
Is your question "Condition based inheritance good?" Then yes it looks necessary in many cases. But I think it would be better to initiate objects conditionally instead of defining extended classes inside condition.
Updates
As far as I understand you want to have different attributes/functions of the child class depending on condition. I faced a similar need/problem in my project. There it was relating to view logic. You may check How is my approach to reuse view logic in my project?
If I understand your problem correctly, then you should have the child classes ready beforehand like this in separate php files:-
child1 class
class1 child extends parent1
child2 class
class2 child extends parent2
And in the condition part do something like:-
$choice = 2;
switch($choice) {
case 1:
include /path/to/child1;
$obj = new child1();
break;
case 2:
include /path/to/child2;
$obj = new child2();
break;
default:
include /path/to/child;
$obj = new child();
//extend nothing
break;
}
I know I'm almost SIX years late. But just in case someone lands here again, I decided to put it here.
Please note that I do not assume the implicit understanding that the class names Car, Ferrari, Ford etc are vehicles. So as to be able to apply this pattern in a generic fashion.
I'll use either of the following approaches in the decreasing order of preference:
Class alias PHP Manual (PHP 5 >= 5.3.0, PHP 7)
// Assuming $my_brand is the required brand
if (!class_exists($my_brand))
{
// Raise suitable warning here and exit
exit('Brand ' . $my_brand . 'not found.');
}
class_alias($my_brand, 'MyBrand');
class AutomaticCar extends MyBrand
{
}
Conditional stacking of inheritance (Too much work, but useful in a larger size project)
// File: lib/MyBrand/Ferrari.php
class MyBrand extends Ferrari
{
}
// File: lib/MyBrand/Ford.php
class MyBrand extends Ford
{
}
// Then in your main code, assuming $my_brand is the required brand
if (!file_exists('lib/MyBrand/' . $my_brand . '.php'))
{
// Raise suitable warning here and exit
exit('Brand ' . $my_brand . 'not found.');
}
class AutomaticCar extends MyBrand
{
}
Other patterns that I can right now (such as Factory Design and Decorator Pattern) think of would take different routes which doesn't comply with the exact topic. So thats all for now.
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.