Consider the situation where there are multiple classes that all need to have access to the configuration storage mechanism, but cannot be extended from a base class because of the architectuur of the framework.
In addition to that I wanted to keep the storage mechanism flexible (be able to switch storage backend later).
I felt it would make sense to create a trait which does the actual saving and use those functions inside all classes (for the example I use $_SESSION as storage system):
trait MyTrait {
function setting_enabled() {
return !empty($_SESSION['setting']) ? TRUE : FALSE;
}
function enable_setting() {
$_SESSION['setting'] = TRUE;
}
function disable_setting() {
$_SESSION['setting'] = FALSE;
}
}
This works great from classes. There is however also one file that is not a class, but is just plain PHP, for which I also need to know if the setting is enabled.
I have tried declaring the function as static:
trait MyTrait {
static function setting_enabled() { // Declared as static function
return !empty($_SESSION['setting']) ? TRUE : FALSE;
}
...
}
And then call the static function from the trait, which worked fine.
if (MyTrait::setting_enabled()) {
...
}
It however feels not entirely right. On the other hand, creating a new empty class that uses the trait and instantiating that to obtain the value seems like a lot of overhead.
Am I allowed to do this (as of PHP 5.6, but also considering the future with PHP 7.x)?
PHP does not allow calling trait's methods without some class (no matter if static or not).
A simple workaround is to use an anonymous class mediately:
...
(new class { use MyTrait; })::myMethod();
...
I like this way a little bit more because we don't create an unnecessary class name.
If you have a trait then you decided to make a multiple inheritance once, maybe for multiple classes. Otherwise, it's redundant declaration and you have to use a class. In fact, and existing of trait means its using.
If you have a static function inside trait, then why you can't using its from the class you'd implemented trait in?
trait MyTrait {
static myFunc() {}
}
class ThatUsingMyTrait {
use MyTrait;
}
// pretend below a code where you want to use the trait.
if(ThatUsingMyTrait::myFunc()) {
// do something
}
The code also is may be a class you want to implement without trait directly.
Hope I describe the idea understandingly.
unsure to import your trait be truing to resolve it:
In case of non-static method
(new class { use MyTrait; })->myMethod();
but it seem it deprecated on php 8
Is there any chance there is an equivalent of Objective C Categories in PHP?
If all you want to do is break a huge class definition up over multiple files, and it's your class, then you can do that with traits. Just define some of the methods in a trait in a different file and use it in your class:
trait FooBar_ExtraMethods {
function foo () { return 'qux'; }
}
class FooBar {
use FooBar__ExtraMethods;
function bar () { return 'baz'; }
}
But if you want to add methods to somebody else's class, then there's simply no way to do that with vanilla PHP. Your choices are:
Live with the fact that this isn't possible and just write a function that takes instances of the class instead of extending it.
Use an extension to add the functionality into the language. Right now, the only contender is Dmitry Zenovich and Sara Golemon's Runkit. Zenovich's fork currently seems to be better-maintained and generally superior to Golemon's (although Golemon's is the one hosted on PECL), and the instructions below use Zenovich's fork.
Suppose I have an existing user-defined class Foo...
class Foo {
function methodA($arg) { return 2*$arg; }
}
I can add a method to it like this:
runkit_method_add('Foo', 'methodC', function ($arg) {
return 5 * $this->methodA($arg);
});
and call it like an ordinary method:
$f = new Foo;
echo $f->methodC(2); // 20
A couple of caveats:
You can't add methods to built-in classes. So if you want to use this to extend library-defined classes, you're good, but if you want to extend built-in classes like DateTime, you're out of luck.
This isn't remotely idiomatic - indeed, Runkit's tagline is "For all those things you.... probably shouldn't have been doing anyway.....". I leave it to your judgement whether to let that deter you from doing it.
It looks like a trait.
trait CarMaintenance{
public function needsOilChange(){}
public function changeOil(){}
public function rotateTires(){}
public function jumpBatteryUsingCar(){}
}
class Car {
use CarMaintenance;
public function startEngine() {}
public function drive() {}
public function turnLeft() {}
public function turnRight() {}
}
But traits could be reused in other class and could have their own hierarchy tree.
I have a class called adminItems within adminitems.class.php. I am trying to include one of the function of this class in xmlParser::someName() within xmlParser.class.php.
Like this:
require_once("adminitems.class.php");
$obj = new adminitems();
class xmlParser
{
function someName()
{
$obj->addAds(); // addAds is within adminItems object
}
}
`
Is this a correct way of doing it?
Don't use extends simply to gain extra functionality. This is a code smell and implies that xmlParser is-a adminItems which it is obviously not. Also, you can't then extend again in the future because PHP doesn't have multiple inheritance. Choose composition over inheritance like this example shows.
Use Dependency Injection. Invert the control of your objects so that they don't depend on each other: see Inversion on Control.
class xmlParser
{
/**
* #var adminItems
*/
protected $adminItems;
/**
* #constructor
*
* #param adminItems $adminItems
*/
public function __construct(adminItems $adminItems)
{
$this->adminItems = $adminItems;
}
/**
* Whatever this does...
*/
function someName()
{
$this->adminItems->addAds();
}
}
`
You need to, external to the classes you create, wire them together like so. You pass adminItems into the xmlParser, then use it how you need to. This is called Dependency Injection and is something you can do in all object oriented languages, not just php.
You would use the above object API like this:
$adminItems = new adminItems;
$xmlParser = new xmlParser($adminItems);
$xmlParser->somName();
Really simple. Your objects (think of them as re-usable libraries) should not depend on other objects except by constructor or method injection - so you can substitute them out leading to testable and inherently clean code.
Also, I urge you to take a look at the following useful links:
PSR-2 for naming conventions:
Use XmlParser instead of xmlParser for your class names
PSR-4 for autoloading:
Learn how to use composer to generate your autoload files for you
Learn how your files have a 1:1 mapping with directory structure
Learn how you only ever need to use an include once in your project
If a class B need a function of the class A, you have many solutions in PHP:
1. Inheritance
Extend the class A with the class B. The class B will be able to access the public and protected method of the class A.
class B extends A {
}
I wouldn't recommend this. It is a really bad practice in OOP to use inheritance just to use one function of a class that has not the same responsability.
2. Traits
Use traits (since PHP5.4.0):
trait factoredMethods {
function getX() { /*...*/ }
function setY() { /*...*/ }
}
class A {
use factoredMethods;
}
class B {
use factoredMethods;
}
This could be an interesting solution in certain cases but it is often a patch on a bad conception.
3. Composition
The best option is to use composition. B uses A:
class A {
}
class B {
private $a;
public function __construct(A $a) {
$this->a = $a;
}
}
$a = new A();
$b = new B($a);
Of course, the method you want to use in A must be public. I would highly suggest to use an interface between A and B in order to have a low coupling.
Almost the correct method - but $obj is not in scope. An ugly solution would be to delcare it in the global scope...
require_once("adminitems.class.php");
global $obj;
$obj = new adminitems();
class xmlParser
{
function someName()
{
global $obj;
$obj->addAds();
}
You can refine this approach using namespaces but the right answer is probably to pass a reference into scope, e.g.
function someName($obj)
{
$obj->addAds();
}
You can use other class function by extending the parent class
class xmlParser extends adminitems{
function someName(){
$obj->addAds();
}
}
I'm comming from C++ and from all I've read in the manual and code examples, none seem to separate a class method declaration from its definition. Is this not possible in PHP? Dosn't this lead to very hard-to-read and cluttery interfaces?
Thanks
EDIT:
I want something like this:
class MyClass
{
public function Foo();
};
MyClass::Foo()
{
echo "O-hoy!";
}
When not using interfaces, you are right. Like in Java, the class definition is the declaration. However, (also like Java), you have the interface available that you can use:
From the documentation:
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// Implement the interface
// This will work
class Template implements iTemplate
{
private $vars = array();
...
}
it is perfectly legal to put them in different files. The class definition though, will always be in one file. You cannot use the partial keyword as you can in C#.
This concept is not necessary in PHP. If you want to get a clean interface, you might define one. http://php.net/manual/en/language.oop5.interfaces.php
i just got some more questions while learning PHP, does php implement any built in plugin system?
so the plugin would be able to change the behavior of the core component.
for example something like this works:
include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
new plugin2;
where
core.class.php contains
class core {
public function coremethod1(){
echo 'coremethod1';
}
public function coremethod2(){
echo 'coremethod2';
}
}
plugin1.class.php contains
class plugin1 extends core {
public function coremethod1(){
echo 'plugin1method1';
}
}
plugin2.class.php contains
class plugin2 extends plugin1 {
public function coremethod2(){
echo 'plugin2method2';
}
}
This would be ideal, if not for the problem that now the plugins are dependable on each other, and removing one of the plugins:
include 'core.class.php';
//include 'plugin1.class.php';
include 'plugin2.class.php';
new plugin2;
breaks the whole thing...
are there any proper methods to doing this?
if there are not, them i might consider moving to a different langauge that supports this...
thanks for any help.
edit:
obviously it is my understanding that is lacking, so here is a
attempt at a clarification.
core.class.php contains anything...
plugin1.class.php contains anything...
plugin2.class.php contains anything...
include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin2method1
whereas:
include 'core.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin1method1
I'm interested in any implementation, even one not involving classes
for example
include 'core.php';
//does core stuff
include 'core.php';
include 'plugin1';
//does extended core stuff
include 'core.php';
include 'plugin2';
//does extended core stuff
include 'core.php';
include 'plugin2';
include 'plugin1';
//does very extended core stuff
including a file needs to change the application behavior. for it to have any meaning.
I do not know what this is called either, so point me at the proper naming if there is any.
You are misusing the term "plugin". A plugin is generally a package of code that extends or alters the base functionality of a system - to make actual PHP plugins (which in the PHP world are called extensions) you'd be writing C or C++.
What you're describing here is merely including classes or class trees into the current execution for usage. And there is a way to bring them into the current execution context 'automatically', and that's via the autoload system.
If, after you've read the documentation on autoloading, you are still unsure of how to move forward, comment here and I will help you along.
EDIT
Ok, I see what you're after. You can't do exactly what you're after. When you execute new core; an instance of the class core will be returned - you can't modify that at all.
However, if you are willing to modify how you create instances of core, then I think I have something that could work for you, and it might look something like this.
class core {
public function coremethod1(){
echo 'coremethod1';
}
public function coremethod2(){
echo 'coremethod2';
}
/**
* #return core
*/
final public static function create()
{
// listed in order of preference
$plugins = array( 'plugin2', 'plugin1' );
foreach ( $plugins as $plugin )
{
if ( class_exists( $plugin ) )
{
return new $plugin();
}
}
return new self;
}
}
class plugin1 extends core {
public function coremethod1(){
echo 'plugin1method1';
}
}
class plugin2 extends plugin1 {
public function coremethod2(){
echo 'plugin2method2';
}
}
$core = core::create();
// test what we have
echo get_class( $core ), '<br>'
, $core->coremethod1(), '<br>'
, $core->coremethod2()
;
If your only concern is that not including plugin1 will create an error, then you can resort to autoloading to have plugin2 load plugin1 automatically:
From the comments in the PHP Manual on spl_autoload
// Your custom class dir
define('CLASS_DIR', 'class/')
// Add your class dir to include path
set_include_path(get_include_path().PATH_SEPARATOR.CLASS_DIR);
// You can use this trick to make autoloader look
// for commonly used "My.class.php" type filenames
spl_autoload_extensions('.class.php');
// Use default autoload implementation
spl_autoload_register();
If, however, you are looking for a traits/mixin-like feature, then the answer is no. PHP does not support this as of now. At least not without patching the core or resorting to these two APIs you do not want to use in production code.
The proper way to change how an object behaves at runtime would be to use Decorators:
$class = new BasicCache( new BasicValidators ( new Basic ) );
or Strategy patterns:
$class = new Basic;
$class->setStrategy(function() { return 'foo'} );
echo $class->callStrategy(); // foo
$class->setStrategy(function() { return 'bar'} );
echo $class->callStrategy(); // bar
See http://sourcemaking.com/design_patterns for the most common patterns.
EDIT Here is an example of how to create plugins with decorators. Assume, we have a game of some sort where some non-player characters walk around in a virtual space and greet the main character from time to time. That's all they do right now. We want some variation on how they greet though, which is why we need our plugins/decorators in this scenario.
First we create an interface that defines some methods any object able to greet should have. We don't care about what it does when these methods are invoked on a specific object. We just want to make sure that the methods are available and that they are called with a clearly defined input:
interface GreetInterface
{
public function greet($name);
public function setGreeting($greeting);
}
An interface is basically a contract any implementing object must fulfill. In our case, the contract says, if you are an object that can greet, you have to have two methods. Implement them any way you like, but have these methods.
Let's build our non-player character classes now, implementing this interface
class Dude implements GreetInterface
{
protected $greeting = 'hello';
public function greet($name)
{
return sprintf('%s %s', $this->greeting, $name);
}
public function setGreeting($greeting)
{
$this->greeting = $greeting;
return $this;
}
}
That's pretty straigtforward I guess. The Dude class just defines the two methods from the interface. When greet() is called, it will fetch the string stored in greeting and prepend to the param passed to the greet method. The setGreeting method allows us to change the greeting at runtime. Note: you could add a getter as well (I was just lazy)
Now on to the plugins. We will create an abstract GreetPlugin class to contain some shared boilerplate code, simply because we don't want to duplicate code in our actual plugins. The abstract plugin class will implement the GreetInterface, so we can make sure all subclasses implement the interface too.
Since Dude already implements the interface as well, we could have the plugins extend Dude, but that would be conceptually wrong, because extending creates an is-a relationship, but a plugin is not a Dude.
abstract class GreetPluginAbstract implements GreetInterface
{
protected $inner;
public function __construct(GreetInterface $inner)
{
$this->inner = $inner;
}
public function setGreeting($greeting)
{
$this->inner->setGreeting($greeting);
return $this;
}
public function greet($name)
{
return $this->inner->greet($name);
}
}
The plugin class accepts one argument when initialized: any class implementing the GreetInterface. The TypeHint makes sure, the class fulfills the contract. That's required, because, as you can see in the code, our plugins will need to call the methods in the interface on the class passed through the constructor. If we had extended from Dude, we would now be able to wrap dudes into dudes, which is a bit odd. Another reason for not doing it.
Now on to the first plugin. We want some of our dudes to speak with a fancy french accent, which means they use âccénts all over the place, but cannot pronounce a proper h. Disclaimer: yes, I know that's a cliche. Please bear with my examples
class FrenchPlugin extends GreetPluginAbstract
{
public function greet($name) {
return str_replace(array('h', 'e'), array('', 'é'),
$this->inner->greet($name));
}
}
Since the Plugin extends the abstract plugin, we can now focus on the actual code that modifies how a regular dude would do his greeting. When greet() is called, we call greet() on the wrapped element and then remove all h characters and turn all es into és. Everything else is unmodified abstract behavior.
In another plugin, we want to change the wording of the greeting, so we have some dudes say Heya, instead of just Hello. Just to add some variation.
class EasyGoingPlugin extends GreetPluginAbstract
{
protected $inner;
public function __construct(GreetInterface $inner) {
$this->inner = $inner->setGreeting('heya');
parent::__construct($inner);
}
}
This way we only override the constructor, because the greet method should just return whatever it will be. So we call the setGreeting method on the object passed to this plugin. Because the object has to implement the GreetInterface, we can be sure this works.
Note that I am assigning the return value of setGreeting as the inner object. This is possible because I return $this, whenever setMethod is called. This cannot be enforced through the interface, so you cannot rely on this form the interface. I just added it to show another technique: method chaining.
With two plugins done, we feel we have enough variation. Now we only need a convenient way to create Dudes. For that we create a small class like this:
class DudeBuilder
{
public static function build()
{
$dude = new Dude();
$decorators = func_get_args();
foreach($decorators as $decorator) {
$decorator .= "Plugin";
// require_once $decorator;
$dude = new $decorator($dude);
}
return $dude;
}
}
Note: I always mix up Builder and AbstractFactory, so if the above is a Factory, well, then it's a factory. Check out the design patterns links I gave earlier on ;)
All this Builder does, is create a regular dude and then wrap/decorate it into/with whatever plugins we tell it to use and than return it. Because the builder encapsulates no own state, we make the build method static.
For this example I assume you used the autoloading code I gave right on top. If not, you can include the plugin files in the foreach loop. Lazy loading them only when they are needed will give you a few microseconds faster load times over including them all on top. Hopefully, this also explains what I meant in the various comments when I argued the behavior should not be controlled by a file inclusion. The file inclusion is just a necessity. You cannot use a class that is not know to PHP. But that the class is actually used, is controlled by our code alone, by passing in the plugin names to the build method.
Let's do this now
$regularDude = DudeBuilder::build();
$frenchDude = DudeBuilder::build('French');
$easygoingDude = DudeBuilder::build('EasyGoing');
$frenchEasyGoingDude = DudeBuilder::build('French', 'EasyGoing');
This is effectively the same as doing:
$regularDude = new Dude;
$frenchDude = new FrenchPlugin(new Dude);
$easygoingDude = new EasyGoingPlugin(new Dude);
$frenchEasyGoingDude = new FrenchPlugin(new EasyGoingPlugin(new Dude));
With just two plugins, we can now create three types of Dudes. Let's have them greet you:
echo $regularDude->greet('Yuri'), PHP_EOL,
$frenchDude->greet('Yuri'), PHP_EOL,
$easygoingDude->greet('Yuri'), PHP_EOL,
$frenchEasyGoingDude->greet('Yuri'), PHP_EOL;
// gives
hello Yuri
éllo Yuri
heya Yuri
éya Yuri
We can now create additional plugins to decorate our basic classes with. If for some reason, you decide your game should have talking horses or cars as well, you could also create a class Car or Horse and have it implement the greet interface too and add a Builder for them. You can then reuse the plugins to create French EasyGoing Cars or Horses.
PHP core can be extended with PECL extensions (which are C++, I believe).
Core functions can be overridden (if you have the APD PECL extension installed) with override_function
User functions can be executed with call_user_func.
Maybe if you could explain what you are planning, we'd be able to offer a better answer?
Your code is breaking because plugin2 extends plugin1, and you're not including the plugin1 class. Why not make class plugin2 extend core? That seems to be what you're going for.