I'm trying to use an interface as a substitute for the lack of enums in PHP, but it does not seem to be working the way I want it to.
Here is the code:
interface Brands
{
const abrand = "A Brand";
const anotherbrand = "Another Brand";
}
class Product
{
private $brand;
function __construct() {
}
public function getBrand() {
return Brands::$this->brand;
}
public function setBrand($value) {
$this->brand = $value;
}
}
$product = new Product();
$product->setBrand("aproduct");
echo $product->getBrand();
Can someone explain Why is the output is abrand instead of A Brand?
Well, that was stupid.
I should have been doing $product->setBrand(Brands::abrand); instead of $product->setBrand("aproduct");
:/
Related
code samples: https://sourcemaking.com/design_patterns/composite/php I made something similar, except that "OnTheBookShelf" knows about $books (SeveralBooks). My "boss" say its bad that they know about each other. But why?
Allright, I edit it:
abstract class OnTheBookShelf {
public $shelf; /////////////////////////////////////////////////
abstract function getBookInfo($previousBook);
abstract function getBookCount();
abstract function setBookCount($new_count);
abstract function addBook($oneBook);
abstract function removeBook($oneBook);
}
class OneBook extends OnTheBookShelf {
private $title;
private $author;
function __construct($title, $author) {
$this->title = $title;
$this->author = $author;
}
function getBookInfo($bookToGet) {
if (1 == $bookToGet) {
return $this->title." by ".$this->author;
} else {
return FALSE;
}
}
function getBookCount() {
return 1;
}
function setBookCount($newCount) {
return FALSE;
}
function addBook($oneBook) {
return FALSE;
}
function removeBook($oneBook) {
return FALSE;
}
}
class SeveralBooks extends OnTheBookShelf {
private $oneBooks = array();
private $bookCount;
public function __construct() {
$this->setBookCount(0);
}
public function getBookCount() {
return $this->bookCount;
}
public function setBookCount($newCount) {
$this->bookCount = $newCount;
}
public function getBookInfo($bookToGet) {
if ($bookToGet <= $this->bookCount) {
return $this->oneBooks[$bookToGet]->getBookInfo(1);
} else {
return FALSE;
}
}
public function addBook($oneBook) {
$oneBook->shelf = $this; //////////////////////////////////////////////////
$this->setBookCount($this->getBookCount() + 1);
$this->oneBooks[$this->getBookCount()] = $oneBook;
return $this->getBookCount();
}
public function removeBook($oneBook) {
$counter = 0;
while (++$counter <= $this->getBookCount()) {
if ($oneBook->getBookInfo(1) ==
$this->oneBooks[$counter]->getBookInfo(1)) {
for ($x = $counter; $x < $this->getBookCount(); $x++) {
$this->oneBooks[$x] = $this->oneBooks[$x + 1];
}
$this->setBookCount($this->getBookCount() - 1);
}
}
return $this->getBookCount();
}
}
I added a bunch of //////////////// to the problematic lines. And here they say that book has reference to shelf.
They should know about their interfaces, so that they can be changed.
Let's say you have classes:
Bookshelf
private books: Book[]
Book
public title: String
You would then access books[i].title and display title of the a book.
Now imagine that the programmer in charge of Book decides that the title merrits its own class, so we have:
Book
public title: Title
Title
private t: String
public toString()
Now the programmer who was coding Bookshelf is required to change their code.
On the other hand if we would have:
Book
private title: String
public getTitleString()
Then we could change the implementation of the Book class, and all we would have to do is to write the getTitleString() function that would return a string representation of a title, and everything would continue to work without any additional changes to Bookshelf.
My "boss" say its bad that they know about each other. But why?
The problem is circular reference between Shelf and Book that is not so trivial and requires special care to work with.
For example, if you simply write $oneBook->shelf = $this; inside addBook method, then what happens if consumer calls this method for one book on two different shelves?
$book = new Book;
$shelf1 = new Shelf;
$shelf2 = new Shelf;
$shelf1->addBook($book);
$shelf2->addBook($book);
Book will be added to both shelves, but it will hold reference only to the last shelf, which leads to inconsistency and potential run-time bugs.
Of cause, circular reference can be done right, but it requires special attention and adds complexity to code.
What is the best way to call Method heDidIt() from child class Make?
I was thinking about events but couldnt find a good non global solution.
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make();
return $this->_make;
}
private function heDidIt()
{
//Call me if the Maker did something.
}
}
class Make
{
public function doIt()
{
//hey im doing something, better tell my Controller
}
}
Just tell Make who's its boss so it can inform him:
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make($this);
return $this->_make;
}
private function heDidIt()
{
//Call me if the Maker did something.
}
public function inform($sampleParam) {
var_dump($sampleParam);
$this->heDidIt();
}
}
class Make
{
protected $control;
public function __construct(Control $control) {
$this->control = $control;
}
public function doIt()
{
//hey im doing something, better tell my Controller
$control->inform('called in Make::doIt()');
}
}
$control = new Control();
$maker = $control->createMaker();
$maker->doIt();
class Control
{
private $_make;
public function createMaker()
{
$this->_make = new Make();
return $this->_make;
}
**protected** function heDidIt()
{
//Call me if the Maker did something.
}
}
class Make **extends Control**
{
public function doIt()
{
**$this -> heDidIt();**
//hey im doing something, better tell my Controller
}
}
Although this seems extremely pointless, so maybe providing your actual code and requirements would let us help you better.
I'm new to PHP OOP, but not so much to PHP, wanted to start learning.. and hit a few brick walls, but this one stumped me.. BUT since I can't find any questions anywhere on the web.. I can't find answers either..
So.. The Code.. I dumbed it down to its core problem, if I can understand that..
<?php
class wallet {
public $Money = 5;
public function Add($mMoney) {
$this->Money += $mMoney;
echo "added $mMoney to Wallet";
}
public function take($mMoney) {
$this->Money -= $nMoney;
}
public function check() {
echo $this->Money;
echo "Check?";
}
public function __get($var) {
echo "trying to get $var and Failing";
}
}
class person {
public $Name;
public $Wallet;
public $Purse;
public $Cash;
public function __construct($name, $cash) {
$this->Wallet = new wallet();
$this->Purse = new wallet();
$this->Name = $name;
$this->Cash = $cash;
}
public function status() {
echo "<br><table border = 1><tr><td>".$this->Name."</td><td> Wallet?</td><td> Purse </td></tr>
<tr><td> $ ".$this->Cash."</td><td>".$this->checkWallet()."<td>22</td></tr></table>";
}
public function toWallet($toAdd) {
$this->Wallet->add($toAdd);
}
public function checkWallet() {
echo $this->Wallet->check();
}
}
$bob = new person ("Bob", 10);
$sarah = new person ("Sarah", 20);
$bob->status();
$sarah->status();
$bob->toWallet(10);
$bob->status();
$sarah->status();
?>
Why won't toWallet Work? Why can't I access $this->checkWallet()..
The reason why ToWallet won't work is because the function thinks the echo from the Add is the return value. (Which is obviously a string and is useless in calculation). There needs to be a return command for the mMoney variable. Try typing something like this in the Add function
public function Add($mMoney) {
$this->Money += $mMoney;
echo "added $mMoney to Wallet";
return $mMoney;
}
I don't know how nobody else spotted that.
For Anyone who comes across this in the future.. Heres the Solution:
First: When you have an Object, don't echo or print the data to the screen, return it to the parent object to do that for you,
Second: Double check that all Variables are either function only i.e. $wallet, or are the objects variables $this->wallet because even though I was staring at the code for hours, I couldn't see that this was not the same variable..
new to OOP, what a mind-mess
I am using Reflections to adjust various values in objects, and I have an object who's parent I need to adjust.
For example:
class Ford extends Car
{
private $model;
}
class Car
{
private $color;
}
I can easily use Reflection to change the model, but how can I separate the parent from the child, so that I can use Reflection on the parent?
Some psuedo code for what I'm hoping is possible:
$ford = new Ford();
$manipulator = new Manipulator($ford);
$manipulator->set('model','F-150');
$manipulator->setParentValue('color','red');
class Manipulator
{
public function __construct($class) {
$this->class = $class;
$this->reflection = new \ReflectionClass($class);
}
public function set($property,$value) {
$property = $this->reflection->getProperty($property);
$property->setAccessible(true);
$property->setValue($this->class,$value);
}
public function setParentValue() {
$parent = $this->reflection->getParent();
$property = $this->reflection->getProperty($property);
$property->setAccessible(true);
// HOW DO I DO THIS?
$property->setValue($this->class::parent,$value);
}
}
Gist of the question:
In this case, how can I change the $color from outside the object altogether?
Is there something like Ford::parent() or get_parent_object($ford) available?
Note
The objects used above are not the exact scenario, but just used to illustrate the concept. In the real world case, I have a parent/child relationship, and I need to be able to access/change values in each from the outside.
ANSWER
Please check my answer below...I figured it out.
After extensive review, I have found that I can't access the parent of an object AS AN OBJECT outside of the object itself.
However, using Reflections, I was able to solve the example posted above:
<?php
class Car
{
private $color;
public function __construct()
{
$this->color = 'red';
}
public function color()
{
return $this->color;
}
}
class Ford extends Car
{
}
$ford = new Ford();
echo $ford->color(); // OUTPUTS 'red'
$reflection = new ReflectionClass($ford);
$properties = $reflection->getProperties();
foreach($properties as $property) {
echo $property->getName()."\n>";
}
$parent = $reflection->getParentClass();
$color = $parent->getProperty('color');
$color->setAccessible(true);
$color->setValue($ford,'blue');
echo $ford->color(); // OUTPUTS 'blue'
See it in action here: http://codepad.viper-7.com/R45LN0
See get_parent_class(): http://php.net/manual/en/function.get-parent-class.php
function getPrivateProperty(\ReflectionClass $class, $property)
{
if ($class->hasProperty($property)) {
return $class->getProperty($property);
}
if ($parent = $class->getParentClass()) {
return getPrivateProperty($parent, $property);
}
return null;
}
Here is the static version of the function I answered your other question with:
function getProperties($object) {
$properties = array();
try {
$rc = new \ReflectionClass($object);
do {
$rp = array();
/* #var $p \ReflectionProperty */
foreach ($rc->getProperties() as $p) {
$p->setAccessible(true);
$rp[$p->getName()] = $p->getValue($object);
}
$properties = array_merge($rp, $properties);
} while ($rc = $rc->getParentClass());
} catch (\ReflectionException $e) { }
return $properties;
}
I ask you for advice.
I struggle with session/object interactions....
<?php
class ShoppingCart
{
public $products
public function __construct($session) {
$this->products = $session['products'];
}
public addProduct($id) {
$this->products[] = new Product($id);
$_SESSION['products'] = $this->products;
}
}
session_start();
$shoppingCart = new ShoppingCart($_SESSION);
$shoppingCart->addProduct(1);
?>
How would you write similar code?
It's only the stub but I don't like my addProduct method and all this code in general.
Please don't be critical and help me improve it.
Maybe there are some design patterns or examples of such interaction?
class ShoppingCart {
private $products = array();
public function __construct() {
if (isset($_SESSION['products'])) {
$this->products = &$_SESSION['products'];
}
}
public addProduct($id) {
$this->products[] = new Product($id);
}
}