Property VS reference: share a variable between class methods - php

Let's say that I'm building a class (for a generic purpose) and I have two methods that work on common variables.
class renderElement
{
public function process()
{
$output = array();
$data = $this->supportMethod($output);
// do stuff with $output
}
public function supportMethod(&$processed_output)
{
// do stuff with $processed_output
}
}
I want to use the same variable into both methods; let's say $output.
I'm curious to know the theory behind the choice of eventually rely on a class property (like following) or when instead is ok (or better) to pass the variable as reference.
class renderElement
{
private $output = array();
public function process()
{
$data = $this->supportMethod();
// do stuff with $this->output
}
public function supportMethod()
{
// do stuff with $this->output
}
}
Advantages? Disadvantages? Design suggestions?
Suggested lectures about this kind of design choices?
[ EDIT ]
I would add that the variable/property should obviously have sense as an object property. I'm not talking about variables for just supporting data processing.

An object fundamentally consists of two things, behaviour and state.
Methods of your class define the behaviour of your object.
Attributes of your class define the state of your object.
In your first example, $output isn't a part of the object's state, so it will not persist throughout the life of the object.
In your second example, $output will persist throughout the life of the object since it is a part of the object's state.
Take this example...
class Shape
{
protected $sides;
public function getNumberOfSides()
{
return $this->sides;
}
}
class Triangle extends Shape
{
public function __construct()
{
$this->sides = 3;
}
}
class Square extends Shape
{
public function __construct()
{
$this->sides = 4;
}
}
$shape = new Square;
echo $shape->getNumberOfSides(); // Returns 4
$shape = new Triangle;
echo $shape->getNumberOfSides(); // Returns 3
$sides (number of sides) is an intrinsic part of a shapes nature, therefore it is appropriate for it to be a part of the object's state throughout the life of the object. This doesn't really have anything to do with the convenience of passing parameters between methods in the same class.

Related

PHP: Shorthand Switch

I'm looking for more comfortable/more short version of Switch() statement in case of using multiple functions.
I'll give you one example: imagine 100-200 functions in one class, and you want to call only one of them by setting value to id in that class.
In my particular case, I have the following structure of PHP file:
<?php
class _main
{
function request($id)
{
switch($id)
{
case 0:
$this->writeA();
break;
case 1:
$this->writeB();
break;
///...
// then we have 100-200 functions like this in switch.
}
}
function writeA()
{
echo('a');
}
function writeB()
{
echo('b');
}
}
$id = 1;
$x = new _main();
$x->request($id);
?>
For some of you it may seem weird, but I don't want to have that much lines of code with case and break. For me, they are just making code more difficult to read.
(by the way, writing it 100 times will not making it fun for me too).
CONCLUSION
What could be the best,fast and comfortable method?
Can I store functions to array and then call them?
And will it affect performance? Will be Swicth() even faster?
Thank you :)
EDIT
Perhaps there is a different way of thinking/coding and not only array/switch thing.
I can't say I would ever recommend this but if you really want that many methods within a single class and a singular function to route the calls through...
<?php
class MyClass
{
public $id;
public function callFunction()
{
$funcName = 'execute' . $this->id;
return $this->$funcName();
}
private function execute1()
{
echo 'execute1() Called.';
}
private function execute2()
{
echo 'execute2() Called.';
}
}
$c = new MyClass();
$c->id = 1;
$c->callFunction();
Output:
execute1() Called.
I feel like there is most likely another way to approach this with more information utilising Interfaces and Abstract classes, but with the information to go off the above might suffice your requirement.
Edit: Sadly I don't have the time right now to come up with a detailed solution, and I don't really have enough information to go off but perhaps utilising interfaces is your best solution for your requirement. Below is a very quick example.
<?php
interface WritableInterface
{
public function write($data);
}
class VersionOneWriter implements WritableInterface
{
public function write($data)
{
return $data . '<br/>';
}
}
class VersionTwoWriter implements WritableInterface
{
public function write($data)
{
return $data . $data . '<br/>';
}
}
class MyMainClass
{
public function request(WritableInterface $writer, $data)
{
return $writer->write($data);
}
}
$c = new MyMainClass();
$w1 = new VersionOneWriter();
$w2 = new VersionTwoWriter();
echo $c->request($w1, 'DataString');
echo $c->request($w2, 'DataString');
Essentially when you call your request function you pass along a Writer class which implements the WritableInterface. Anything that implements that interface has to have a write() method.
Now when you pass your data across with your method, since you are also passing a writer along that can handle the data you can safely call ->write($data) within your request() method and the result will be dependent on the class you passed through.
If you ever need another method of writing you can just add create another class that implements your interface
Hopefully that made some sense, it was a bit of a ramble as I have to disappear for a bit. If you have any questions I'll try to check back when I have time.
--
Edit2:
The define() in this instance requires PHP7+ since I'm defining an array, but you could prior to PHP7 you could just use a standard array. $classMap = ['FirstClass', 'SecondClass'];
interface MyInterface {}
class FirstClass implements MyInterface {}
class SecondClass implements MyInterface {}
$requestParam = 1;
define('CLASS_MAP', array(
'FirstClass',
'SecondClass',
));
$classMap = CLASS_MAP[$requestParam]; // SecondClass
$class = new $classMap;
var_dump($class); // Dumps out: object(SecondClass)#1 (0) {}

PHP OOP - Pass data between classes through the calling class?

I'm struggling to find a correct approach to pass data between classes, which do not directly call each other, and are only related through a parent class (which I now use, but I consider it a dirty workaround rather than anything near a solution).
I have 3 classes both able to read input and write output, and based on configuration I set one to read, another one to write. It may even be the same class, they all share a parent class, but they are always two separate instances called from a controller class.
Currently I use this sort of functionality:
class daddy {
public static $data;
}
class son extends daddy {
public function setData() {
parent::$data = "candy";
}
}
class daughter extends daddy {
public function getData() {
echo parent::$data;
}
}
while($processALineFromConfig)
$son = new son;
$son->setData();
$daughter = new daughter;
$daughter->getData();
daddy::$data = null; //reset the data, in the actual code $daughter does that in parent::
}
Instantination of these classes runs in a loop, therefore I always need to reset the data after $daughter receives them, 'cos otherwise it would stay there for another pass through the loop.
I'm absolutely sure it's not how class inheritance is supposed to be used, however I'm struggling to find a real solution. It only makes sense the data should be stored in the controller which calls these classes, not the parent, but I already use return values in the setter and getter functions, and I am not passing a variable by reference to store it there to these functions 'cos I have optional parameters there and I'm trying to keep the code clean.
What would be the correct approach to pass data through the controller then?
Thanks!
The best option would be for two object share some other, third object. This would be the class for "third object" which will ensure the exchage:
class Messenger
{
private $data;
public function store($value)
{
$this->data = $value;
}
public function fetch()
{
return $this->data;
}
}
Then a class for both instance, that will need to share some state:
class FooBar
{
private $messenger;
private $name = 'Nobody';
public function __construct($messenger, $name)
{
$this->messenger = messenger;
$this->name = $name;
}
public function setSharedParam($value)
{
$this->messenger->store($value);
}
public function getSharedParameter()
{
return $this->name . ': ' . $this->messenger->fetch();
}
}
You utilize the classes like this:
$conduit = new Messenger;
$john = new FooBar($conduit, 'Crichton');
$dominar = new FooBar($conduit, 'Rygel');
$dominar->setSharedParameter('crackers');
echo $john->getSharedParameter();
// Crichton: crackers
Basically, they both are accessing the same object. This also can be further expanded by making both instance to observe the instance of Messenger.

Design nightmare with PHP

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>';
?>

Modular design pattern

I'm trying to decide the design of a system which is meant to allow for a high amount of extensiblity. From what I can tell, a pattern such as the abstract factory would not allow for overriding of the base methods, apart from duplicating code (as demonstrated below).
I've done some preliminary research into aspect oriented programming and it seems to be along the lines of what I'm looking for but I'm having a difficult time wrapping my head around the specifics.
abstract class Object {
protected $object_id;
protected $name;
function LoadObjectData()
{
$file_contents = readfile('object'.$object_id.'.data');
$data = array();
// parse file contents into $data array...
return $data;
}
function Create()
{
$data = $this->LoadObjectData();
$name = $data['name'];
return $data;
}
}
class User extends Object {
protected $email_address;
function Create()
{
$data = parent::Create();
$this->email_address = $data['email_address'];
return $data;
}
}
//----------Module 1-MySQL Lookup-------------
/*
* Redefine Object::LoadObjectData() as follows:
*/
function LoadObjectData()
{
$data = array();
$result = mysql_query("SELECT...");
// construct array from result set
return $data;
}
//----------Module 2-Cache Machine-------------
/*
* Redefine Object::LoadObjectData() as follows:
*/
function LoadObjectData()
{
if (exists_in_cache($object_id)) {
return get_cached_object($object_id);
}
$data = parent::LoadObjectData();
cache_object($object_id, $data);
return $data;
}
(This is sort of a poor example, but hopefully it helps to get my point across)
The intended system would have a very large proportion of methods available to be extended and I would like to minimize the extra effort and learning necessary for developers.
Is AOP exactly what I'm looking for, or is there a better way to deal with this?
Thanks!
So, you want to use a decorator pattern without defining the decorator itself.
If yes, then it's a monkeypatching and can be done with aspect-oriented tools. This can be solved easily with following extensions and frameworks:
PHP Runkit Extension
Go! Aspect-Oriented framework for PHP
PHP-AOP Extension.
You don't have to declare the base class as an abstract class. You can make it a regular class and have it load and instantiate other classes based on passed construct parameters. The constructor can return an instance of a class, not just the class the constructor is in. To avoid duplicating code, you can mix static with instantiated functions and variables. Just remember that a static function or variable is the same for ALL instances. Change a static variable in one and it is changed for all instances. A rather basic example of a plugin architecture.
class BaseObject {
protected static $cache = array();
public function __construct($load_plugin) {
require_once($load_plugin.'.class.php');
$object = new $load_plugin();
return $object;
}
public static function cacheData($cache_key, $data) {
self::$cache[$cache_key] = $data;
}
}
class Plugin extends BaseObject {
public function __construct() {
}
public function loadData() {
// Check the cache first
if ( !isset(self::$cache[$cache_key]) ) {
// Load the data into cache
$data = 'data to cache';
self::cacheData($cache_key, $data);
}
return self::$cache[$cache_key];
}
}

strategies for managing long class files in php

I've got a bunch of functions that I want to move into a class. They're currently split into a couple of fairly long files. I'd prefer not to have one 2500 line file, but as far as I can tell, you can't use include to split a class up into multiple files. In theory, I could group the functions in different classes, but they're closely related enough that I feel like they belong together, and splitting them will reduce some of the utility that I'm hoping to get from moving away from a procedural approach (with shared properties, rather than a bunch of parameters that are in nearly every function).
I know this is a bit vague, but any suggestions/pointers? If it matters, this is for a prototype, so ease of code management takes precedence over security and performance.
UPDATE: Let me see if I can remove some of the vagueness:
This class/set of functions outputs the html for a complex form. There are many different sections and variations within each section, depending on about 5 or 6 parameters, which are currently passed into the functions. I was hoping to define the parameters once as properties of the class and then have access to them from within all of the section-creation methods. If I use sub-classes, the values of those properties won't be initialized properly, hence the desire for one class. (Hmm... unless I define them as static. I may have just answered my own question. I'll have to look to see if there's any reason that wouldn't work.)
I've currently got a mess of functions like:
get_section_A ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
if ($this->type == 'foo') { }
else ($this->type == 'foo') { }
}
So I was initially imagining something like:
class MyForm {
public $type; // or maybe they'd be private or
public $mode; // I'd use getters and setters
public $read_only; // let's not get distracted by that :)
public $values_array;
// etc.
function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
$this->type = $type;
// etc.
}
function get_sections () {
$result = $this->get_section_A();
$result .= $this->get_section_B();
$result .= $this->get_section_C();
}
function get_section_A() {
if ($this->type == 'foo') { }
else { }
}
function get_section_B() {}
function get_section_C() {}
// etc. for 2500 lines
}
Now I'm thinking something like:
// container class file
class MyForm {
static $type
static $mode
static $read_only
static $values_array
// etc.
function __constructor ($type='foo', $mode='bar', $read_only=false, $values_array=array()) {
MyForm::$type = $type;
// etc.
}
function get_sections () {
$result = new SectionA();
$result .= new SectionB();
$result .= new SectionC();
}
}
// section A file
class SectionA extends MyForm {
function __constructor() {
if (MyForm::$type == 'foo') { }
else { }
}
function __toString() {
// return string representation of section
}
}
// etc.
Or probably I need an abstract class of FormSection where the properties live.
Any other ideas/approaches?
I'd split them up into as many classes as you want (or as many that make sense) and then define an autoloader to obviate inclusion headaches.
EDIT
Ok, after seeing more of your code - I think you're approaching subclasses wrong. You have lots of if statements against $type, which signals to me that that is what the polymorphism should be based on.
abstract class MyForm
{
protected
$mode
, $read_only
, $values
;
public function __construct( $mode, $read_only=false, array $values = array() )
{
$this->mode = $mode;
$this->read_only = (boolean)$read_only;
$this->values = $values;
}
abstract function get_section_A();
abstract function get_section_B();
abstract function get_section_C();
// final only if you don't want subclasses to override
final public function get_sections()
{
return $this->get_section_A()
. $this->get_section_B()
. $this->get_section_C()
;
}
}
class FooForm extends MyForm
{
public function get_section_A()
{
// whatever
}
public function get_section_B()
{
// whatever
}
public function get_section_C()
{
// whatever
}
}
Usually I do something like this:
class one
{
public function __get($key)
{
// require __DIR__ / $key . php
// instanciate the sub class
}
public function mainMethod()
{
}
}
class one_subOne extends one
{
public function otherMethod()
{
}
}
class one_subTwo extends one
{
public function anotherMethod()
{
}
}
$one->mainMethod();
$one->subOne->otherMethod();
$one->subTwo->anotherMethod();
As far as building the view is concerned, you might like to try the CompositeView pattern.
Here's a small example of how it could look in PHP. Pretend, for the sake of this example, that View::$html is encapsulated in a Template class that can load html from disk and allows you to inject variables, handles output escaping, etc.
interface IView {
public function display();
}
class View implements IView {
public $html = '';
public function display() {
echo $this->html;
}
}
class CompositeView implements IView {
private $views;
public function addPartial(IView $view) {
$this->views[] = $view;
}
public function display() {
foreach ($this->views as $view) {
$view->display();
}
}
}
The reason for the IView interface is to allow you to build composite views with other composite views.
So now consider a form with three parts: header, body and footer.
class HeaderView extends View {
public function __construct() {
$this->html .= "<h1>Hi</h1>\n";
}
}
class BodyView extends View {
public function __construct() {
$this->html .= "<p>Hi there.</p>\n";
}
}
class FooterView extends View {
public function __construct() {
$this->html .= "<h3>© 2012</h3>\n";
}
}
(Again, you wouldn't just write HTML into that public variable and handle output escaping yourself. You'd likely reference a template filename and register your data via the template's interface.)
Then, to put it all together you would go:
$view = new CompositeView();
// here you would make decisions about which pieces to include, based
// on your business logic. see note below.
$view->addPartial(new HeaderView());
$view->addPartial(new BodyView());
$view->addPartial(new FooterView());
$view->display();
So now your views can be composed and the fragments reused, but you can easily make a mess with the code that builds them, especially if you have a lot of conditions and many different possible outcomes (which it sounds like you do.) In that case, the Strategy pattern will probably be of some help.
If you haven't already read UncleBob's SOLID article, do it before anything else! At least the Single Responsibility Principle. I would also recommend reading Refactoring to Patterns by Joshua Kerievsky at some point.
If you want to do OOP, separate the concerns and encapsulate them into appropriate classes. Combine them either by extending them or by composition or better aggregation. Remove any duplicate code. Dont repeat yourself.
In your case, separate the stuff that is about any Form from the stuff that is about your specific form. The code that can be used for any Form is the code you want to place into a generic Form class. You can reuse this in later projects. For an example of a very complex Form class, check out Zend_Form.
Anything in your code related to the/a specific form gets into a class of it's own that extends the generic form. Assuming from the type property given in your code, you might end up with multiple special purpose form classes (instead of one-type-fits-all-form), which will likely eliminate the complexity from the getSection methods and make your code a lot easier to maintain because you can concentrate on what a specific type of form is supposed to look like and do.
Lastly, if you got code in there that fetches data for the form from within the form or is otherwise not directly related to form building, remove it and make it into a separate class. Remember, you want to separate concerns and your form classes' concern is to build a form, not get it's data or something. Data is something you will want to pass to the form through the constructor or a dedicated setter.
They are all in different files, which means that they were different enough to group by file. Just take the same logic when building them into classes. I have a Page object that deals with building the page. Technically the HTML for my page header is part of the page, but I separate it into a Page_HTML class for maintaining my sanity and not creating gigantic classes.
Also, I tend to make the sub_classes, like Page_HTML in this case, static, instead of instantiating it. That way I can access the $this variables in the Page class, but still group it into another class.
class Page
{
function buildPage($content)
{
$content = Page_HTML::getHeader() . $content;
}
}
class Page_HTML
{
function getHeader()
{
}
}
This class/set of functions outputs
the html for a complex form.
Why not remove PHP from the equation? It seems you're using PHP to organize views which can be done easily with the filesystem. Just write the views in HTML with as little PHP as possible. Then use PHP to map requests to views. I'm assuming you're processing forms with PHP, and you could continue to do so. However, your classes will become much smaller because they're only accepting, verifying and presumably saving input.

Categories