I'm trying to get a reference to a function of an object.
I tried what you can see on the way 2 with no success.
Any advice on this?
<?
function echoc($data) {
echo "\n<pre>\n";
print_r($data);
echo "</pre>\n";
}
class Person {
const STATUS_SLEEPING = 0;
const STATUS_EATING = 1;
const STATUS_SEEING = 2;
const STATUS_WALKING = 3;
function __construct() {
$this->status = self::STATUS_SLEEPING;
}
function see() {
$this->status = self::STATUS_SEEING;
echo 'I\'m seeing now!';
}
function eat($what) {
$this->status = self::STATUS_EATING;
echo 'I\'m eating '.$what.' now!';
}
function walk() {
$this->status = self::STATUS_WALKING;
echo 'I\'m walking now!';
}
function getStatus() {
return $this->status;
}
function getStatusStr() {
switch ($this->status) {
case self::STATUS_SLEEPING: return 'STATUS_SLEEPING';
case self::STATUS_EATING: return 'STATUS_EATING';
case self::STATUS_SEEING: return 'STATUS_SEEING';
case self::STATUS_WALKING: return 'STATUS_WALKING';
}
}
};
$p = new Person();
echoc('Status: '.$p->getStatusStr());
$p->see();
echoc('Status: '.$p->getStatusStr());
$p->walk();
echoc('Status: '.$p->getStatusStr());
$way = 2;
switch ($way) {
case 1:
$p->eat('piza');
break;
case 2:
$method = 'eat'; // the name of the function is stored on a variable
// begin of code I'm looking for
$callback = $p->$method; // I tried this with no success
// end of code I'm looking for
call_user_func($callback, 'pizza'); // this line cannot be changed. I'm not allowed to
break;
}
echoc('Status: '.$p->getStatusStr());
?>
What you are looking for is:
$callback = [$p, 'eat']; // Callback: $p->eat()
call_user_func($callback, 'pizza'); // Run $p->eat('pizza');
Related
I can't get value variable in a method, after use this value to another method in one class PHP Laravel.
public function paymentCourse(Request $request)
{
$idCourse = $request->input('idcourse');
$CoursePrice = Course::where('id', $idCourse)->first();
if(Auth::user()->palate) {
if(Auth::user()->palate->is_palate == 1) {
// this value I want to transfer method getTransactionAmount()
$currentPrice = $CoursePrice->price_palate;
}
} else {
// this value I want to transfer method getTransactionAmount()
$currentPrice = $CoursePrice->price;
}
return view('pages.payment-course', compact('currentPrice'));
}
public function getTransactionAmount($type) {
switch ($type) {
case 'palate':
return 11645;
break;
case 'course':
return 15000; // I get value method paymentCourse() $currentPrice.
break;
case 'course_sale':
return 12000; // I get value method paymentCourse() $currentPrice.
break;
default:
throw new \Exception('Wrong transaction type');
}
}
This is my solution, thank you for help.
public function paymentCourse(Request $request)
{
$idCourse = $request->input('idcourse');
$CoursePrice = Course::where('id', $idCourse)->first();
if(Auth::user()->palate) {
if(Auth::user()->palate->is_palate == 1) {
$currentPrice = $CoursePrice->price_palate;
\Session::put('currentPrice', $currentPrice);
}
} else {
$currentPrice = $CoursePrice->price;
\Session::put('currentPrice', $currentPrice);
}
return view('pages.payment-course', compact('currentPrice'));
}
private function getTransactionAmount($type) {
$currentPrice = \Session::get('currentPrice');
switch ($type) {
case 'palate':
return 11645;
break;
case 'course':
return $currentPrice;
break;
case 'course_sale':
return $currentPrice;
break;
default:
throw new \Exception('Wrong transaction type');
}
}
I have the following code:
<?php
class Node{
public $left,$right;
public $data;
function __construct($data)
{
$this->left=$this->right=null;
$this->data = $data;
}
}
class Solution{
public function insert($root,$data){
if($root==null){
return new Node($data);
}
else{
if($data<=$root->data){
$cur=$this->insert($root->left,$data);
$root->left=$cur;
}
else{
$cur=$this->insert($root->right,$data);
$root->right=$cur;
}
return $root;
}
}
public function getHeight($root) {
$heightLeft = 0;
$heightRight = 0;
if ($root->left != null) {
$heightLeft = getHeight($root->left) + 1;
}
if ($root->right != null) {
$heightRight = getHeight($root->right) + 1;
}
echo "heightRigh is $heightRight\n";
echo "heightLeft is $heightLeft\n";
$ans = ($heightLeft > $heightRight ? $heightLeft : $heightRight);
return $ans;
}
}//End of Solution
$myTree=new Solution();
$root=null;
$T=intval(fgets(STDIN));
while($T-->0){
$data=intval(fgets(STDIN));
$root=$myTree->insert($root,$data);
}
$height=$myTree->getHeight($root);
echo $height;
?>
When I run it with the inputs
1
1
it gives the correct results.
But when I run it with the inputs
2
1
2
I get the error:
PHP Fatal error: Call to undefined function getHeight() in C:\git\phpStudy\CallingAFunction.php on line 36
Fatal error: Call to undefined function getHeight() in C:\git\phpStudy\CallingAFunction.php on line 36
I am new to php and can't figure out what I am doing wrong. Thank you.
The answer is very easy. In short your problem is this:
a) leads to fatal error as described:
class Solution{
public function getHeight($a) {
if($a==true) {
return getHeight(false);
}
return "hello";
}
}
$a = new Solution();
echo $a->getHeight(true);
b) works:
class Solution{
public function getHeight($a) {
if($a==true) {
return $this->getHeight(false);
}
return "hello";
}
}
$a = new Solution();
echo $a->getHeight(true);
You need to reference to the class if you want to call a function inside the class. Use $this->.
In line 36 you have a recursive function call to get height. The function is not found. Correct solution is therefore:
<?php
class Node{
public $left,$right;
public $data;
function __construct($data)
{
$this->left=$this->right=null;
$this->data = $data;
}
}
class Solution{
public function insert($root,$data){
if($root==null){
return new Node($data);
}
else{
if($data<=$root->data){
$cur=$this->insert($root->left,$data);
$root->left=$cur;
}
else{
$cur=$this->insert($root->right,$data);
$root->right=$cur;
}
return $root;
}
}
public function getHeight($root) {
$heightLeft = 0;
$heightRight = 0;
if ($root->left != null) {
$heightLeft = $this->getHeight($root->left) + 1;
}
if ($root->right != null) {
$heightRight = $this->getHeight($root->right) + 1;
}
echo "heightRigh is $heightRight\n";
echo "heightLeft is $heightLeft\n";
$ans = ($heightLeft > $heightRight ? $heightLeft : $heightRight);
return $ans;
}
}//End of Solution
$myTree=new Solution();
$root=null;
$T=intval(fgets(STDIN));
while($T-->0){
$data=intval(fgets(STDIN));
$root=$myTree->insert($root,$data);
}
$height=$myTree->getHeight($root);
echo $height;
?>
I'm trying to create a priority queue using this code and I can't find where the problem is. Someone tell me where I went wrong.
<?php
class PriorityQueue implements Iterator , Countable
{
public function __construct() {
$flags = self::EXTR_DATA;
$items = array();
}
function compare ( mixed $priority1 , mixed $priority2 ){}
function count (){
return count($this->items);
}
function current (){
switch ($this->flags) {
case self::EXTR_BOTH:
$ret = array();
$ret['Patient'] = current($this->items);
$ret['Priority'] = $this->key();
break;
case self::EXTR_DATA:
$ret = current($this->items);
break;
case self::EXTR_PRIORITY:
$ret = $this->key();
break;
};
return $ret;
}
function extract (){
$ret = $this->current();
$this->next();
return $ret;
}
function insert ($name,$priority){
$patient = array();
return $patient[$name] = $priority;
}
function isEmpty ()
{
return empty($this->items);
}
function key (){
return substr(key($this->items), 0, 9);
}
function next (){
//array_shift($this->items);
return($this->items);
echo "<br />";
}
function recoverFromCorruption (){}
function rewind (){}
function setExtractFlags (int $flags ){
switch ($flags) {
case self::EXTR_BOTH:
case self::EXTR_DATA:
case self::EXTR_PRIORITY:
$this->flags = $flags;
break;
};
}
function top (){
return $this->current();
}
function valid () {
if (NULL !== key($this->items)) {
return TRUE;
}
return FALSE;
}// function valid
/**
* Extract the data.
*/
const EXTR_DATA = 1;
/**
* Extract the priority.
*/
const EXTR_PRIORITY = 2;
/**
* Extract an array containing both priority and data.
*/
const EXTR_BOTH = 3;
};
$objPQ = new splPriorityqueue();
$objPQ->insert('Richard',9);
$objPQ->insert('paul',1);
$objPQ->insert('Ken',8);
$objPQ->insert('peter',2);
$objPQ->insert('Rick',7);
$objPQ->insert('Dan',5);
echo "PATIENTS = ".$objPQ->count()."<br />";
//mode of extraction
$objPQ->setExtractFlags(splPriorityqueue::EXTR_BOTH);
//Go to TOP
$objPQ->top();
for($i=0,$j=$objPQ->count(); $i<$j; $i++){
//print_r($objPQ->current());
$patients = $objPQ->current();
foreach ($patients as $patient=>$value){
echo $patient."<br />".$value;
$objPQ->next();
echo "<br />";
}
}
?>
I'm now getting some weird result
data-patient Richard
priority-9
......
etc
I want to get results to be
Richard - 9
Ken - 8
Rick - 7
Dan - 5
Peter - 2
Paul - 1
Considering the priority given
The Standard PHP Library (SPL) implements the SplPriorityQueue class :
$pq = new SplPriorityQueue();
// The insert method inserts an element in the queue by shifting it up
$pq->insert('A', 3);
$pq->insert('B', 6);
$pq->insert('C', 1);
$pq->insert('D', 2);
// Count the elements
echo "count ->" . $pq->count() . PHP_EOL;
// Sets the mode of extraction (EXTR_DATA, EXTR_PRIORITY, EXTR_BOTH)
$pq->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
// Go at the node from the top of the queue
$pq->top();
// Iterate the queue (by priority) and display each element
while ($pq->valid()) {
print_r($pq->current());
echo PHP_EOL;
$pq->next();
}
Try this modified class:
class PriorityQueue implements Iterator, Countable {
/**
* Extract the data.
*/
const EXTR_DATA = 1;
/**
* Extract the priority.
*/
const EXTR_PRIORITY = 2;
/**
* Extract an array containing both priority and data.
*/
const EXTR_BOTH = 3;
private $flags;
private $items;
public function __construct() {
$this->flags = self::EXTR_DATA;
$this->items = array();
}
function compare($priority1, $priority2) {}
function count() {
return count($this->items);
}
function extract() {
$result = $this->current();
$this->next();
return $result;
}
function current() {
switch ($this->flags) {
case self::EXTR_BOTH:
$result = $this->key() . ' - ' . current($this->items);
break;
case self::EXTR_DATA:
$result = $this->key();
break;
case self::EXTR_PRIORITY:
$result = current($this->items);
break;
default:
$result = '';
}
return $result;
}
function key() {
return key($this->items);
}
function next() {
return next($this->items);
}
function insert($name, $priority) {
$this->items[$name] = $priority;
asort($this->items);
return $this;
}
function isEmpty() {
return empty($this->items);
}
function recoverFromCorruption() {}
function rewind() {}
function setExtractFlags($flags) {
switch ($flags) {
case self::EXTR_BOTH:
case self::EXTR_DATA:
case self::EXTR_PRIORITY:
$this->flags = $flags;
break;
};
}
function valid() {
return (null === key($this->items)) ? false : true;
}
}
Usage:
$patients = new PriorityQueue();
$patients->setExtractFlags(PriorityQueue::EXTR_BOTH);
$patients->insert('Richard', 9)
->insert('paul', 1)
->insert('Ken', 8)
->insert('peter', 2)
->insert('Rick', 7)
->insert('Dan', 5);
foreach($patients as $patient) {
echo $patient->current();
}
which is the best way to "prepare/store a function call"* for to, in a later point, actually execute it?
(* with an undetermined number of parameters)
what I have now:
function addCall($className, [$parameter [, $parameter ...]])
{
$this->calls[] = func_get_args();
}
then I'll do:
foreach($this->calls as $args)
{
$r = new ReflectionClass(array_shift($args));
$instances[] = $r->newInstanceArgs($args);
}
which doesn't look very OOP to me, including the "undetermined number of parameters" characteristic
how can I improve my code?
thank you in advance
You might be interested in the Command pattern.
How you implement it is up to you - or the framework you're using.
But those patterns usually stack up. So have a good read of the "surrounding" patterns, too, to be able to make a good choice regarding the actual implementation (or choosing an existing library).
completely informal:
<?php
function foo($a, $b) {
return 'foo#'.($a+$b);
}
function bar($a,$b,$c) {
return 'bar#'.($a-$b+$c);
}
$cmds = array();
$cmds[] = function() { return foo(1,2); };
$cmds[] = function() { return bar(1,2,3); };
$cmds[] = function() { return bar(5,6,7); };
$cmds[] = function() { return foo(9,7); };
$s = new stdClass; $s->x = 8; $s->y = 8;
$cmds[] = function() use($s) { return foo($s->x,$s->y); };
// somewhere else....
foreach($cmds as $c) {
echo $c(), "\n";
}
or something like
<?php
interface ICommand {
public function /* bool */ Execute();
}
class Foo implements ICommand {
public function __construct($id) {
$this->id = $id;
}
public function Execute() {
echo "I'm Foo ({$this->id})\n";
return true;
}
}
class Bar implements ICommand {
public function __construct($id) {
$this->id = $id;
}
public function Execute() {
echo "I'm Bar ({$this->id})\n";
return true;
}
}
$queueCommands = new SplPriorityQueue();
$queueCommands->insert(new Foo('lowPrio'), 1);
$queueCommands->insert(new Foo('midPrio'), 2);
$queueCommands->insert(new Foo('highPrio'), 3);
$queueCommands->insert(new Bar('lowPrio'), 1);
$queueCommands->insert(new Bar('midPrio'), 2);
$queueCommands->insert(new Bar('highPrio'), 3);
// somewhere else....
foreach( $queueCommands as $cmd ) {
if ( !$cmd->execute() ) {
// ...
}
}
or something else ...
I tried to learn Facade pattern, but got stuck with a problem. PHP doesnt output $totalprice from PrintPrice method. Also, here is additional information: var_dump after initializing and object gives me:
private 'SkiRent' =>
object(SkiRent)[2]
private 'SkiResortTicketSystem' =>
object(SkiResortTicketSystem)[3]
private 'HotelBookingSystem' =>
object(HotelBookingSystem)[4]
private 'totalprice' => null
but var_dump after calling HaveGoodRest gives me blank page.
I wonder if you could help me, here is the code:
<?php
class SkiRent
{
public function RentBoots($feetSize, $skierLevel)
{
return 20*$skierLevel*100/$feetSize;
}
public function RentSki($weight, $skierLevel)
{
return 40*$skierLevel*100/$weight;
}
public function RentPole($height)
{
return 5*$height/100;
}
};
class SkiResortTicketSystem
{
public function BuyOneDayTicket()
{
return 115;
}
public function BuyHalfDayTicket()
{
return 60;
}
};
class HotelBookingSystem
{
public function BookRoom($roomQuality)
{
switch ($roomQuality)
{
case 3:
return 250;
case 4:
return 500;
case 5:
return 900;
default:
throw new ArgumentException("roomQuality should be in [3;5]");
}
}
};
class SkiResortFacade
{
private $SkiRent;
private $SkiResortTicketSystem;
private $HotelBookingSystem;
private $totalprice;
function __construct()
{
$this->SkiRent = new SkiRent();
$this->SkiResortTicketSystem = new SkiResortTicketSystem();
$this->HotelBookingSystem = new HotelBookingSystem();
}
function HaveGoodRest($height, $weight, $feetSize, $skierLevel, $roomQuality)
{
$skiPrice = $SkiRent->RentSki($weight, $skierLevel);
var_dump($skiPrice);
$skiBootsPrice = $SkiRent->RentBoots($feetSize,$skierLevel);
$polePrice = $SkiRent->RentPole($height);
$oneDayTicketPr = $SkiResortTicketSystem->BuyOneDayTicket();
$hotelPrice = $HotelBookingSystem->BookRoom($roomQuality);
$this->totalprice = $skiPrice + $skiBootsPrice + $polePrice + $oneDayTicketPr + $hotelPrice;
}
public function HaveRestWithOwnSkis($roomQuality)
{
$oneDayTicketPr = $SkiResortTicketSystem->BuyOneDayTicket();
$hotelPrice = $HotelBookingSystem->BookRoom($roomQuality);
return $oneDayTicketPr + $hotelPrice;
}
public function PrintPrice()
{
echo $this->totalprice;
}
};
$rest = new SkiResortFacade();
var_dump($rest);
$height = 181.5;
$weight = 70.1;
$feetSize = 45.2;
$skierLevel = 1.2;
$roomQuality = 3;
$rest->HaveGoodRest($height, $weight, $feetSize, $skierLevel, $roomQuality);
var_dump($rest);
$rest->PrintPrice();
?>
Fatal error: Call to a member function RentSki() on a non-object on line 65
$skiPrice = $SkiRent->RentSki($weight, $skierLevel); // Line 65
$SkiRent isn't an object because you haven't instantiated it or passed it in as an argument in the HaveGoodRest() method
You have multiple calls to non-objects being acted on in your code.
You have defined $this->SkiRent attribute in SkiResortFacade class:
$this->SkiRent = new SkiRent();
but you have referenced it without $this:
$skiPrice = $SkiRent->RentSki($weight, $skierLevel);
it should be:
$skiPrice = $this->SkiRent->RentSki($weight, $skierLevel);
This is a working code, so you can compare woth your version:
<?php
class SkiRent
{
public function RentBoots($feetSize, $skierLevel)
{
return 20*$skierLevel*100/$feetSize;
}
public function RentSki($weight, $skierLevel)
{
return 40*$skierLevel*100/$weight;
}
public function RentPole($height)
{
return 5*$height/100;
}
};
class SkiResortTicketSystem
{
public function BuyOneDayTicket()
{
return 115;
}
public function BuyHalfDayTicket()
{
return 60;
}
};
class HotelBookingSystem
{
public function BookRoom($roomQuality)
{
switch ($roomQuality)
{
case 3:
return 250;
case 4:
return 500;
case 5:
return 900;
default:
throw new ArgumentException("roomQuality should be in [3;5]");
}
}
};
class SkiResortFacade
{
private $SkiRent;
private $SkiResortTicketSystem;
private $HotelBookingSystem;
private $totalprice;
function __construct()
{
$this->SkiRent = new SkiRent();
$this->SkiResortTicketSystem = new SkiResortTicketSystem();
$this->HotelBookingSystem = new HotelBookingSystem();
}
function HaveGoodRest($height, $weight, $feetSize, $skierLevel, $roomQuality)
{
$skiPrice = $this->SkiRent->RentSki($weight, $skierLevel);
var_dump($skiPrice);
$skiBootsPrice = $this->SkiRent->RentBoots($feetSize,$skierLevel);
$polePrice = $this->SkiRent->RentPole($height);
$oneDayTicketPr = $this->SkiResortTicketSystem->BuyOneDayTicket();
$hotelPrice = $this->HotelBookingSystem->BookRoom($roomQuality);
$this->totalprice = $skiPrice + $skiBootsPrice + $polePrice + $oneDayTicketPr + $hotelPrice;
}
public function HaveRestWithOwnSkis($roomQuality)
{
$oneDayTicketPr = $SkiResortTicketSystem->BuyOneDayTicket();
$hotelPrice = $HotelBookingSystem->BookRoom($roomQuality);
return $oneDayTicketPr + $hotelPrice;
}
public function PrintPrice()
{
echo $this->totalprice;
}
};
$rest = new SkiResortFacade();
$height = 181.5;
$weight = 70.1;
$feetSize = 45.2;
$skierLevel = 1.2;
$roomQuality = 3;
$rest->HaveGoodRest($height, $weight, $feetSize, $skierLevel, $roomQuality);
$rest->PrintPrice();