PHP How to disable trait in subclass? - php

If I have class:
class_A{
use SomeTrait;
}
And
class_B extends class_A{
//
}
How to disable trait "SomeTrait" in class_B class ?

You can't disable inheriting trait in a subclass.
However you can change trait's method visibility.

Why extending class in first place when using traits - if - *(let's say it's true) there are A LOTS of traits in Your code/project .. ?
class A {
use private_trait_holding_this,
private_trait_holding_just_that;
// .. properties, public methods...
}
class B {
use private_trait_holding_just_that;
// ... properties, public methods ....
}
Traits are very powerful things, and I often like to refer to them as bags. Just because of this below. Note that everything inside traits is private.
trait private_properties {
private $path;
private $file_;
private $pack_;
}
trait private_methods_uno
{
private function getFilePrivate()
{
if(is_file($this->path))
$this->file_ = file_get_contents($this->path);
}
}
trait private_methods_due
{
private function putFilePrivate()
{
if(!is_string($this->file_))
die('File probably doesn\'t exist ... ');
else
{
$this->pack_ = base64_encode($this->file_);
file_put_contents(("{$this->path}.bak"), $this->pack_, LOCK_EX);
$this->pack_ = null; $this->file_ = $this->pack_;
}
}
}
final class opcodeToString
{
use
private_properties,
private_methods_uno,
private_methods_due;
public function __construct($path)
{
$this->path = $path;
$this->getFilePrivate();
}
public function putFile()
{
$this->putFilePrivate();
}
}
$filepath = '/my/path/to/opcode.php';
$ots = new opcodeToString($filepath);
$ots->putFile();

Related

Extends a PHP class and it's children

In one of my projects, I use an external library providing two classes : DrawingImage and DrawingCharset, both of them extending BaseDrawing.
I want to extends BaseDrawing to add some properties and alter an existsing method. But I also want theses modifications in "copy" of existing children (DrawingImage and DrawingCharset).
There is a simple way to do it ? Extending don't seems to be a solution : I must duplicate code between each subclass. And I'm not sure i can call a parent method through Trait.
Traits can access properties and methods of superclasses just like the subclasses that import them, so you can definitely add new functionality across children of BaseDrawing with traits.
<?php
class BaseDrawing
{
public $baseProp;
public function __construct($baseProp)
{
$this->baseProp = $baseProp;
}
public function doSomething()
{
echo 'BaseDrawing: '.$this->baseProp.PHP_EOL;
}
}
class DrawingImage extends BaseDrawing
{
public $drawingProp;
public function __construct($baseProp, $drawingProp)
{
parent::__construct($baseProp);
$this->drawingProp = $drawingProp;
}
public function doSomething()
{
echo 'DrawingImage: '.$this->baseProp.' - '.$this->drawingProp.PHP_EOL;
}
}
class DrawingCharset extends BaseDrawing
{
public $charsetProp;
public function __construct($baseProp, $charsetProp)
{
parent::__construct($baseProp);
$this->charsetProp = $charsetProp;
}
public function doSomething()
{
echo 'DrawingCharset: '.$this->baseProp.' - '.$this->charsetProp.PHP_EOL;
}
}
/**
* Trait BaseDrawingEnhancements
* Adds new functionality to BaseDrawing classes
*/
trait BaseDrawingEnhancements
{
public $traitProp;
public function setTraitProp($traitProp)
{
$this->traitProp = $traitProp;
}
public function doNewThing()
{
echo 'BaseDrawingEnhancements: '.$this->baseProp.' - '.$this->traitProp.PHP_EOL;
}
}
class MyDrawingImageImpl extends DrawingImage
{
// Add the trait to our subclass
use BaseDrawingEnhancements;
}
class MyDrawingCharsetImpl extends DrawingCharset
{
// Add the trait to our subclass
use BaseDrawingEnhancements;
}
$myDrawingImageImpl = new MyDrawingImageImpl('Foo', 'Bar');
$myDrawingImageImpl->setTraitProp('Wombats');
$myDrawingCharsetImpl = new MyDrawingCharsetImpl('Bob', 'Alice');
$myDrawingCharsetImpl->setTraitProp('Koalas');
$myDrawingImageImpl->doSomething();
$myDrawingCharsetImpl->doSomething();
$myDrawingImageImpl->doNewThing();
$myDrawingCharsetImpl->doNewThing();

PHP traits - change value of static property in inherited class

So, this is my trait:
trait Cacheable
{
protected static $isCacheEnabled = false;
protected static $cacheExpirationTime = null;
public static function isCacheEnabled()
{
return static::$isCacheEnabled && Cache::isEnabled();
}
public static function getCacheExpirationTime()
{
return static::$cacheExpirationTime;
}
}
This is the base class:
abstract class BaseClass extends SomeOtherBaseClass
{
use Cacheable;
...
}
These are my 2 final classes:
class Class1 extends BaseClass
{
...
}
class Class2 extends BaseClass
{
protected static $isCacheEnabled = true;
protected static $cacheExpirationTime = 3600;
...
}
Here is the part of the code which executes these classes:
function baseClassRunner($baseClassName)
{
...
$output = null;
if ($baseClassName::isCacheEnabled()) {
$output = Cache::getInstance()->get('the_key');
}
if ($output === null) {
$baseClass = new $baseClassName();
$output = $baseClass->getOutput();
if ($baseClassName::isCacheEnabled()) {
Cache::getInstance()->set('the_key', $output);
}
}
...
}
This code doesn't work because PHP complains about defining same properties in Class2 as in Cacheable. I can't set them in their constructors because I want to read them even before running the constructor. I'm open for ideas, any help would be appreciated. :)
EDIT:
Well, I use this Cacheable trait on several places so i kind of got mixed up. :) This works fine like this. But I have another class which directly uses the Cacheable trait and when I try to do this on that class, I get the metioned error. So... Just assume that the BaseClass isn't abstract and I'm trying to set these cache properties on it. The question remains the same.
You can not reassign trait properties.
From PHP manual http://php.net/traits
See Example #12 Conflict Resolution
If a trait defines a property then a class can not define a property
with the same name, otherwise an error is issued. It is an E_STRICT if
the class definition is compatible (same visibility and initial value)
or fatal error otherwise.
One solution would be to define override properties in the class
class Class2 extends BaseClass
{
protected static $_isCacheEnabled = true;
protected static $_cacheExpirationTime = 3600;
...
}
and then modify your trait as such...
trait Cacheable
{
protected static $isCacheEnabled = false;
protected static $cacheExpirationTime = null;
public static function isCacheEnabled()
{
if ( Cache::isEnabled() ) {
return isset( static::$_isCacheEnabled ) ? static::$_isCacheEnabled :
static::$isCacheEnabled;
} else {
return false;
}
}
public static function getCacheExpirationTime()
{
return isset ( static::$_cacheExpirationTime ) ? static::$_cacheExpirationTime :
static::$cacheExpirationTime;
}
}
You cannot override properties, but you can override functions. So one of the possible solutions, if you're going to use the properties as given, not changing them, could be:
trait Cacheable {
protected static function isCacheEnabledForClass() { return false; }
public static function isCacheEnabled()
{
return static::isCacheEnabledForClass() && Cache::isEnabled();
}
}
class Class2 extends BaseClass {
protected static function isCacheEnabledForClass() { return true; }
}
You could use defined():
// only defined in classes
// static $isCacheEnabled = false;
public static function isCacheEnabled()
{
return defined(static::$isCacheEnabled ) ? static::$isCacheEnabled : false;
}
Or maybe you could live with the variable being protected instead of static?

How to make the inherited class run a method from same class in PHP

Whats wrong with me OOP here.
I want to inherit from Class A
The return_output method will do something common so I don't want to write that in the inherited classes.
However when I do B->return_output() I want it to run the do_something method in Class B, but I see that it always runs the method from Class A.
Should I replace $this with something else?
class A {
private function do_something() {
// do something
}
public function return_output() {
$op = $this->do_something();
// add some wrappers to $op
return $op;
}
}
class B extends A {
private function do_something() {
// do something different
}
}
var newClass = new B;
echo B->return_output();
use protected and not private since you are running it inside of scope a and scope b can't access private scope a:
class A {
protected function do_something() {
echo('ado_something');
}
public function return_output() {
$op = $this->do_something();
// add some wrappers to $op
return $op;
}
}
class B extends A {
protected function do_something() {
echo('bdo_something');
}
}
$newClass = new B;
echo $newClass->return_output();

PHP get_class() functionality in child classes

I need to check if a property exists and this works:
class someClass {
protected $some_var
public static function checkProperty($property) {
if(!property_exists(get_class()) ) {
return true;
} else return false;
}
}
But now when I try to extend the class, it doesn't work anymore.
class someChild extends someClass {
protected $child_property;
}
someChild::checkProperty('child_property'); // false
How do I get the functionality I want? I tried replacing get_class() with $this, self, static, nothing works.
I believe I've found the correct answer. For static methods, use get_called_class().
Perhaps $this works for object methods.
How about checking property_exists against get_class() and get_parent_class()? However, for more nested classes you would have to check against the classes recursively.
public static function checkProperty($property)
{
if (property_exists(get_class(), $property)
or property_exists(get_parent_class(), $property))
{
return true;
}
else return false;
}
(sorry but I'm more into Allman-Style ;-))
The following works:
<?php
class Car
{
protected $_var;
public function checkProperty($propertyName)
{
if (!property_exists($this, $propertyName)) {
return false;
}
return true;
}
}
class BMW extends Car
{
protected $_prop;
}
$bmw = new BMW();
var_dump($bmw->checkProperty('_prop'));
#param $class The class name or an object of the class to test for

Can a class Extend or Override himself?

Suppose we have a class. We create an object from the class and when we do the class Extends himself base on the object initialization value..
For example:
$objectType1 = new Types(1);
$objectType1->Activate(); // It calls an activation function for type 1
$objectType2 = new Types(2);
$objectType2->Activate(); // It calls an activation function for type 2
I don't want to use the standard procedure of class extending:
class type1 extends types{}
You cannot extend a class at runtime. Use an instance variable to distinct the two type or use a factory.
Example for instance variable:
class Types() {
private $type;
public function __construct($type) {
$this->type = $type;
}
public function activate() {
if($this->$type == 1) {
// do this
}
else if($this->type == 2) {
// do that
}
}
}
Example for factory pattern:
abstract class BaseClass {
// Force Extending class to define this method
abstract public function activate();
// Common method
public function printOut() {
echo "Hello World";
}
}
class Type1 extends BaseClass {
public function activate() {
// do something
}
}
class Type2 extends BaseClass {
public function activate() {
// do something else
}
}
class TypeFactory {
public static function getType($tpye) {
if($type == 1) {
return new Type1();
}
else if($type == 2) {
return new Type2();
}
}
}
then you do:
$obj = TypeFactory::getType($1);
$obj->activate();
Update:
Since PHP 5.3 you can use anonymous functions. Maybe you can make use of this.

Categories