I am trying to implement the getCost() function using a forloop but i am new to php and having trouble with understanding how to implement. i just keep getting error saying undefined variable.
Here is my code
<?php
class Burger {
public $title = '';
private $ingredients = array();
public function __construct($n) {
$this->name = $n;
}
public function addIngredient($ing) {
array_push($this->ingredients, $ing);
}
public function getCost() {
foreach( $ingredients as $ingredient=> $costDollars){
$price += $costDollars;
return $price;
}
} }
class Ingredient {
public $name = 'Ingredient'; public $costDollars = 0.0;
public function __construct($n, $c) {
$this->name = $n;
$this->costDollars = $c;
} }
$myBurger = new Burger('Tasty Burger');
$myBurger->addIngredient(new Ingredient('Meat', 0.3));
$myBurger->addIngredient(new Ingredient('Cheese', 0.2));
$myBurger->addIngredient(new Ingredient('Beetroot', 0.2));
$myBurger->addIngredient(new Ingredient('Pineapple', 0.4));
echo $myBurger->getCost(); ?>
You're forgetting $this when you're trying to access the class property $ingredients:
public function getCost() {
$price = 0;
foreach( $this->ingredients as $ingredient){
$price += $ingredient->costDollars;
}
return $price;
}
As you can see in the above code, the return-statement is also moved after the loop. If you have the return in your loop, the variable will be returned after the first iteration.
<?php
class Burger {
public $title = '';
private $ingredients = array();
public function __construct($n) {
$this->name = $n;
}
public function addIngredient($ing, $cost) {
$this->ingredients += array($ing => $cost); // Wont overide! EXTRA CHEEZ PLZ
}
public function getCost() {
//forloop
$totalprice = 0; // Start Register Cha Ching!
foreach($this->ingredients as $ing => $price){ // Add Items (*scanner Beeps*
$totalprice += $price;
} // All Done with items, let return cost
return $totalprice; // Return Value to Function Call
}
}
$myBurger = new Burger('Tasty Burger');
$myBurger->addIngredient('Meat', 0.3);
$myBurger->addIngredient('Cheese', 0.2);
$myBurger->addIngredient('Beetroot', 0.2);
$myBurger->addIngredient('Pineapple', 0.4);
echo $myBurger->getCost(); ?> // ECHO Value to Function Call
Related
The problem am having is keeping my inventory variable keep up with the changes made by different objects. For example, the $me object buys 4 items, which deducts from the inventory and leaves 6 in the inventory that is good. Then I make a new object $l, but the inventory starts from 10 again, instead of the new current inventory of 6.
Below is my PHP code for my class
class cashRegister {
public $total = 0;
public $name;
public $discount;
public $lastamount;
public $inventory = 10;
public function __construct($name, $discount) {
$this->name = $name;
$this->discount = $discount;
}
public function add($itemCost) {
$this->total += $itemCost;
$this->lastamount = $itemCost;
}
public function scan($item, $quantity) {
switch ($item) {
case "eggs" :
$this->add ( 1 * $quantity);
$this->inventory($quantity);
break;
case "news" :
$this->add(2 * $quantity);
$this->inventory($quantity);
}
//$this->inventory -= $quantity;
}
public function inventory($quantity) {
$this->inventory -= $quantity;
}
public function staffDiscount() {
$this->total -= ($this->total * ($this->discount/100)) ;
}
public function voidL() {
$this->total -= $this->lastamount;
}
}
Below is my normal code
include 'cashRegister.php';
$me = new cashRegister("Mg", 20);
$l = new cashRegister("ll", 50);
echo $me->inventory;
$me->scan("eggs", 2);
$me->scan("eggs", 1);
$me->scan("news", 1);
//$me->staffDiscount();
echo $me->inventory;
//echo $l->inventory;
//echo $me->total;
When you create a new instance of a class (that happens whenever you use the keyword new) it will create a brand new kind of 'copy' or 'instance' of that class. So, when you subtract the inventory amount, you are only subtracting from that instance.
PHP has the keyword static that will change the public instance variable of $inventory into a kind of shared variable between all instances of that class.
Update it from public to static to look like this:
public static $inventory = 10;
But you also need several other changes because you cannot reference a static variable in the same way as an instance variable.
Basically you need to change $this-> to self:: in your inventory method:
public function inventory($quantity) {
self::$inventory -= $quantity;
}
Then when you reference the static variable from the instance variable you need to access it like this:
echo $me::$inventory;
Your final code would look like this:
<?
class cashRegister {
public $total = 0;
public $name;
public $discount;
public $lastamount;
public static $inventory = 10;
public function __construct($name, $discount) {
$this->name = $name;
$this->discount = $discount;
}
public function add($itemCost) {
$this->total += $itemCost;
$this->lastamount = $itemCost;
}
public function scan($item, $quantity) {
switch ($item) {
case "eggs" :
$this->add ( 1 * $quantity);
$this->inventory($quantity);
break;
case "news" :
$this->add(2 * $quantity);
$this->inventory($quantity);
}
//$this->inventory -= $quantity;
}
public function inventory($quantity) {
self::$inventory -= $quantity;
}
public function staffDiscount() {
$this->total -= ($this->total * ($this->discount/100)) ;
}
public function voidL() {
$this->total -= $this->lastamount;
}
}
And when you call it:
$me = new cashRegister("Mg", 20);
$l = new cashRegister("ll", 50);
echo $me::$inventory;
echo "<br>";
$me->scan("eggs", 2);
$me->scan("eggs", 1);
$me->scan("news", 1);
//$me->staffDiscount();
echo $me::$inventory;
//echo $l->inventory;
//echo $me->total;
Here is an updated class that gives you a more extended idea of how you can use objects.
Instead of just an inventory class, it breaks down an item into an individual class and object that you can use.
When an item is scanned it loops through the inventory items and if there is not enough of that item in stock it will return false - in a real world scenario, you would probably handle that error differently but for this case it is okay. You might add a method called 'isItemInStock()' to the Inventory class that will check if it is available first.
So now that the inventory is an object its instance is shared between the other objects as well as the items that are in stock. Instead of adding/subtracting the totals during the scan process there is a getTotal() method that will recalculate the total with the discount.
<?
class Item {
public $name;
public $cost;
public $quantity;
public function __construct($name, $cost, $quantity=null) {
$this->name = $name;
$this->cost = $cost;
$this->quantity = $quantity;
}
}
class Inventory
{
public $items = array();
public function __construct()
{
}
public function add($item) {
$this->items[] = $item;
}
}
class CashRegister {
public $name;
public $discount;
public $inventory;
public $items = array();
public function __construct($name, $discount, $inventory) {
$this->name = $name;
$this->discount = $discount;
$this->inventory = $inventory;
}
public function add($item) {
$this->items[] = $item;
}
public function scan( $name, $qty ) {
foreach ($this->inventory->items as $key => $item) {
if ($item->name==$name) {
if (($item->quantity-$qty)>=0) {
$this->inventory->items[$key]->quantity -= $qty;
$this->add( new Item($item->name, $item->cost, $qty) );
return true;
} else {
// Not added, not enough
return false;
}
}
}
// Invalid item
return false;
}
public function getTotal() {
$total = 0;
foreach ($this->items as $item) {
$total += $item->cost*$item->quantity;
}
$discount = ((100-$this->discount)/100);
echo "Discount total: $discount\n";
return $total - $discount;
}
}
$inventory = new Inventory();
$inventory->add( new Item('eggs', 1, 20) );
$inventory->add( new Item('news', 2, 50) );
$cb1 = new CashRegister(1, 20, $inventory );
echo "<pre>\n";
echo "Scanning 5 eggs\n";
$cb1->scan( 'eggs', 5);
foreach ($inventory->items as $item) {
echo $item->name . ': '. $item->quantity." in stock\n";
}
echo "Scanning 6 news\n";
$cb1->scan( 'news', 5);
foreach ($inventory->items as $item) {
echo $item->name . ': '. $item->quantity." in stock\n";
}
$cb2 = new CashRegister(2, 30, $inventory );
echo "Scanning 3 eggs\n";
$cb2->scan('eggs', 3);
foreach ($inventory->items as $item) {
echo $item->name . ': '. $item->quantity." in stock\n";
}
echo "Cash Register 1 Total: " . $cb1->getTotal() . "\n";
echo "Cash Register 2 Total: " . $cb2->getTotal() . "\n";
I would define your inventory separately and add it to your cash register invocation.
class Inventory
{
public $eggs;
public $news;
public function __construct($eggs = 10, $news = 10)
{
$this->eggs = $eggs;
$this->news = $news;
}
}
You would need to modify your CashRegister class to use the properties of the object rather than just modifying the inventory property, and accept the inventory as an argument.
class CashRegister
{
// ...
protected $inventory;
public function __construct($inventory, name, $discount)
{
$this->inventory = $inventory;
$this->name = $name;
$this->discount = $discount;
}
// ...
public function scan($item, $quantity)
{
switch ($item) {
case "eggs" :
$this->add ( 1 * $quantity);
$this->inventory($item, $quantity);
break;
case "news" :
$this->add(2 * $quantity);
$this->inventory($item, $quantity);
}
}
protected function inventory($item, $quantity)
{
$this->inventory->$item -= $quantity;
}
// ...
}
Then you can do something like this:
$inventory = new Inventory;
$me = new CashRegister($inventory, 'mg', 20);
$l = new CashRegister($inventory, 'l', 50);
// ...
Because objects are always passed by reference, your inventory object is now in sync between both registers, and the changes made in either will affect the available inventory.
I'm trying to implement a skip list in PHP using the pseudocode from http://www.mathcs.emory.edu/~cheung/Courses/323/Syllabus/Map/skip-list-impl.html. I managed to get it working fine in java, but not in PHP. My put method is always returning null, and therefore, my get method too returns null.
I don't quite understand where I'm going wrong, so I'd appreciate any assistance!
<?php
interface SkipListEntry {
public function getPrev();
public function getNext();
public function getAbove();
public function getBelow();
public function getKey();
public function getValue();
public function setValue($v);
public function setPrev($v);
public function setNext($v);
public function setAbove($v);
public function setBelow($v);
public function hasPrev();
public function hasNext();
public function hasAbove();
public function hasBelow();
}
class SkipListNode implements SkipListEntry {
private $prev;
private $next;
private $above;
private $below;
private $key;
private $value;
public static $posInf = "+oo";
public static $negInf = "-oo";
function __construct($a, $b) {
$this->key = $a;
$this->value = $b;
}
public function getPrev(){
return $this->prev;
}
public function getNext(){
return $this->next;
}
public function getAbove(){
return $this->above;
}
public function getBelow(){
return $this->below;
}
public function getKey(){
return $this->key;
}
public function getValue(){
return $this->value;
}
public function setValue($n){
$this->value = $n;
}
public function setPrev($n) {
$this->prev = $n;
}
public function setNext($n) {
$this->next = $n;
}
public function setAbove($n) {
$this->above = $n;
}
public function setBelow($n) {
$this->below = $n;
}
public function hasPrev(){
return !is_null($this->prev);
}
public function hasNext(){
return !is_null($this->next);
}
public function hasAbove(){
return !is_null($this->above);
}
public function hasBelow(){
return !is_null($this->below);
}
}
class SkipList{
private $topLeft;
private $topRight;
private $height = 0;
private $totalEntries = 0;
private $head;
function __construct(){
$this->topLeft = new SkipListNode(SkipListNode::$negInf, null);
$this->topRight = new SkipListNode(SkipListNode::$posInf, null);
$this->topLeft->setNext($this->topRight);
$this->topRight->setPrev($this->topLeft);
$this->head = $this->topLeft;
}
public function size() {
return $this->totalEntries;
}
public function isEmpty(){
return $this->totalEntries == 0;
}
public function search($key){
$p = $this->head;
while (true) {
while (!$p->getNext()->getKey() == SkipListNode::$posInf
&& strcmp($p->getNext()->getKey(), $key) <= 0) {
$p = $p->getNext();
}
if ($p->hasBelow()){
$p = $p->getBelow();
}
else {
break;
}
}
return $p;
}
public function put($key, $value){
$searchElement = $this->search($key);
if ($key == $searchElement->getKey()){
$oldValue = $searchElement->getValue();
$searchElement->setValue($value);
return $oldValue;
}
$newEntry = new SkipListNode($key, $value);
$newEntry->setPrev($searchElement);
$newEntry->setNext($searchElement->getNext());
$searchElement->getNext()->setPrev($newEntry);
$searchElement->setNext($newEntry);
$currentHeight = 0;
for ($j = 1; $j <= $this->coinFlip(); $j ++){
if ($currentHeight >= $this->height){
$this->createAdditionalLayer();
}
while (is_null($searchElement->getAbove())){
$searchElement = $searchElement->getprev();
}
$searchElement = $searchElement->getAbove();
$aboveElement = new SkipListNode($key, null);
$aboveElement->setPrev($searchElement);
$aboveElement->setNext($searchElement->getNext());
$aboveElement->setBelow($newEntry);
$searchElement->getNext()->setPrev($aboveElement);
$searchElement->setNext($aboveElement);
$newEntry->setAbove($aboveElement);
$newEntry = $aboveElement;
$currentHeight ++;
}
$this->totalEntries ++;
return null;
}
public function get($key){
$p = $this->search($key);
if ($p->getKey() == $key){
return $p->getValue();
}
return null;
}
private function createAdditionalLayer(){
$newtopLeft = new SkipListNode(SkipListNode::$negInf, null);
$newtopRight = new SkipListNode(SkipListNode::$posInf, null);
$newtopLeft->setNext($newtopRight);
$newtopLeft->setBelow($this->head);
$newtopRight->setPrev($newtopLeft);
$this->head->setAbove($newtopLeft);
$this->head = $newtopLeft;
$this->height ++;
}
private function coinFlip(){
$total = 0;
$current = -1;
while ($current != 1){
$current = rand(0,1);
$total ++;
}
return $total;
}
}
// test
$a = new SkipList();
var_dump($a->put("a", "b"));
var_dump($a->put("a", "c")); // should return c (returns null)
var_dump($a->size()); // should return 1 (returns 2)
var_dump($a->get("a")); // should return c, (returns null)
Thank you!
I found some problems in a search function:
please change your code with this and try:
public function search($key){
$p = $this->head;
while (true) {
while ($p->getNext()->getKey() != SkipListNode::$posInf
&& strcmp($p->getNext()->getKey(), $key) == 0) {
$p = $p->getNext();
}
if ($p->hasBelow()){
$p = $p->getBelow();
}
else {
break;
}
}
return $p;
}
The result is:
var_dump($a->put("a", "b"));
var_dump($a->put("a", "c")); string 'b',
var_dump($a->size()); int 1,
var_dump($a->get("a")); string 'c'
I'm trying to pass an instance of my Generator class to another class to use some of the variables. The Generator class instance works fine but when i passed it to another (SelectStrategy) class it seems it is not passing the variable at all. I'm not sure what I'm doing wrong - I used var_dump on the called function to check what it gives me but it's just blank.
Function
class Generator
{
//properties for self
private $s_charge;
public $connection;
public $task_priority;
public $fog_mode = true;
public $nodes = array();
public $type;
public function generateNodesSpecs() {
$node = array();
for ($i = 0; $i < 100; $i++) {
$charge1 = mt_rand(30,100);
$node['charge'] = $charge1;
//array_push($node, $charge1);
$hops = mt_rand(0,4);
$node['hops'] = $hops;
//array_push($node, $hops);
$resource1 = mt_rand(0,100);
if ($resource1 <= 50) {
if ($resource1 <=10){
$node['connection'] = '4G';
//array_push($node, '4G');
}
else {
$node['connection'] = '3G';
//array_push($node, '3G');
}
}
else if ($resource1 > 50 && $resource1 <= 60) {
$node['connection'] = 'WiFi';
//array_push($node, 'WiFi');
}
else {
}
$resource2 = mt_rand(0,100);
if ($resource2 <=60) {
$node['additional'] = 'CPU';
//array_push($node, 'CPU');
}
else {
$node['additional'] = 'none';
}
$this->nodes[] = $node;
//array_push($nodes, $node);
unset($node);
}
//compare which get the resources
//var_dump($this->nodes[0]);
}
class SelectStrategy {
//take in generator class instance
private $generator;
private $priority;
private $size;
private $slaves = array();
private $found_slave = null; //will hold item with max val;
public function __construct($generator) {
$this->generator = $generator;
}
private function selectSlaves() {
$max = -9999999; //will hold max val
foreach($this->generator->nodes as $k=>$v)
{
if($v['charge']>$max)
{
$max = $v['charge'];
$this->found_slave = $v;
}
}
var_dump($this->found_slave);
}
}
And classes/function calls
$generator = new Generator();
$generator->generateNodesSpecs();
$select_strategy = new SelectStrategy($generator);
$select_strategy->selectSlaves();
The $this->generator->nodes is a 2D array
global $generator;
in every function of SelectSlave should do it
Is there a way to iterate over an object's keys implementing ArrayAccess and Iterator interfaces? Array access works as a charm but I can't use foreach on those objects which would help me a lot. Is it possible? I have such code so far:
<?php
class IteratorTest implements ArrayAccess, Iterator {
private $pointer = 0;
public function offsetExists($index) {
return isset($this->objects[$index]);
}
public function offsetGet($index) {
return $this->objects[$index];
}
public function offsetSet($index, $newValue) {
$this->objects[$index] = $newValue;
}
public function offsetUnset($index) {
unset($this->objects[$index]);
}
public function key() {
return $this->pointer;
}
public function current() {
return $this->objects[$this -> pointer];
}
public function next() {
$this->pointer++;
}
public function rewind() {
$this->pointer = 0;
}
public function seek($position) {
$this->pointer = $position;
}
public function valid() {
return isset($this->objects[$this -> pointer]);
}
}
$it = new IteratorTest();
$it['one'] = 1;
$it['two'] = 2;
foreach ($it as $k => $v) {
echo "$k: $v\n";
}
// expected result:
// one: 1
// two: 2
Thanks for any help and hints.
I use this to implement iterator. Maybe you can adapt to your code ;)
class ModelList implements Iterator{
public $list;
private $index = 0;
public $nb;
public $nbTotal;
/**
* list navigation
*/
public function rewind(){$this->index = 0;}
public function current(){$k = array_keys($this->list);$var = $this->list[$k[$this->index]];return $var;}
public function key(){$k = array_keys($this->list);$var = $k[$this->index];return $var;}
public function next(){$k = array_keys($this->list);if (isset($k[++$this->index])) {$var = $this->list[$k[$this->index]];return $var;} else {return false;}}
public function valid(){$k = array_keys($this->list);$var = isset($k[$this->index]);return $var;}
/**
*
* Constructor
*/
public function __construct() {
$this->list = array();
$this->nb = 0;
$this->nbTotal = 0;
return $this;
}
}
while ($it->valid()) {
echo $it->key().' '.$it->current();
$it->next();
}
Would be my approach, however, this function looks iffy:
public function next() {
$this->pointer++;
}
Incrementing 'one' isn't likely to give you 'two'. Try the code in the answers to this question to get the next array key:
$keys = array_keys($this->objects);
$position = array_search($this->key(), $keys);
if (isset($keys[$position + 1])) {
$this->pointer = $keys[$position + 1];
} else {
$this->pointer = false;
}
I have managed to implement OOP of Cart Basket
An Item contain 1 or more options.
If I add same OptionID again then the number of quantity should increase rather than creating another Option Object. How can that be done?
If I add same ItemID again, it should refuse to create another Item object.
Also is my OOP is good?
class Cart {
public $item = array();
public function addItem($id) {
$item = new Item();
$item->setItem($id);
$this->item[] = $item;
return $item;
}
}
class Item {
private $id = array();
private $option = array();
public function setItem($id) {
$this->id = $id;
return $this;
}
public function addOption($id) {
$option = new Option();
$option->setOption($id);
$this->option[] = $option;
}
}
class Option {
private $quantity;
private $id;
public function setOption($id) {
$this->quantity = 1;
$this->id = $id;
return $this;
}
}
$cart = new Cart();
//ItemID 10
$item = $cart->addItem(10);
//OptionID
$item->addOption(11);
$item->addOption(22);
$item->addOption(22); //should increase quantity
//It should not create another object because we already have Item Object of ItemID10
$item = $cart->addItem(10);
$Shop = $cart;
echo "<pre>";
print_r($Shop);
echo "</pre>";
If you can have only one item with the unique id in the cart - then rewrite the addItem() method like this:
public function addItem($id) {
$result = false;
if (empty($this->item[$id])) {
$item = new Item();
$item->setItem($id);
$this->item[$id] = $item;
$result = $item;
}
return $result;
}
The same is with addOption() method:
public function addOption($id) {
if (empty($this->option[$id])) {
$option = new Option();
$option->setOption($id);
$this->option[$id] = $option;
}
else {
$this->option[$id]->setQuantity($this->option[$id]->getQuantity() + 1);
}
}
And of course you should implement setQuantity() and getQuantity() methods in Option class.
Hope this helps.
Partialy rewrote the code and tested:
<?php
class Cart {
public $items = array();
public function addItem($id) {
if(array_key_exists($id, $this->items)){
$item = $this->items[$id];
}else{
$item = new Item($id);
$this->items[$id] = &$item;
}
return $item;
}
}
class Item {
private $id;
private $options = array();
public function __construct($id) {
$this->id = $id;
return $this;
}
public function addOption($id) {
if(array_key_exists($id, $this->options)){
$this->options[$id]->addQuantity();
}else{
$option = new Option($id);
$this->options[$id] = $option;
}
}
}
class Option {
private $quantity;
private $id;
public function __construct($id) {
$this->quantity = 1;
$this->id = $id;
return $this;
}
public function addQuantity()
{
$this->quantity++;
}
}
$cart = new Cart();
//ItemID 10
$item = $cart->addItem(10);
//OptionID
$item->addOption(11);
$item->addOption(22);
$item->addOption(22); //should increase quantity
//It should not create another object because we already have Item Object of ItemID10
$item = $cart->addItem(10);
$Shop = $cart;
echo "<pre>";
print_r($Shop);
echo "</pre>";
?>