I am trying to convert some classes from Ruby to PHP for a project I am working on. I think I almost have it, but I am unversed in Ruby so I am struggling with understanding some aspects and what the equivalencies would be in PHP.
So the Ruby class is as follows:
class Log
def initialize (x,y,list,url)
#line = 0
#x=x
#y=y
#url=url
#list=list
#points = Hash.new(0)
#list.each do |point|
#points[point.xy] +=1
end
#reps = #points.values.max
end
attr_reader :x, :y, :list, :reps, :url
def next
coord = #list[#line]
#line += 1
return coord
end
end
Here is what I have written in PHP thus far: (I also added a note for what the original is supposed to be doing)
<?php
/*
* Stores all the values pertinent to a single URL and gives accessors to them.
* There’s also a “next” method that returns next click within the same URL
*/
class Log
{
private $x;
private $y;
private $url;
private $list;
private $reps;
private $points;
function __construct($x,$y,$list,$url)
{
$this->line = 0;
$this->x = $x;
$this->y = $y;
$this->url = $url;
$this->list = $list;
$this->points = array();
foreach ($list as $l_attr => $l_val) {
if($l_attr == 'xy'){
$this->points[$l_val];
}
}
$this->reps = count($this->points);
return $this;
}
function next(){
$coord = next($this->list);
return $coord;
}
public function __get($property) {
if (property_exists($this, $property)) {
return $this->$property;
}
}
}
I am trying to keep everything OOP to match the rest of my project.
I would really just like to know if I am doing this right or if I am way off. ;)
I'm not good at ruby so I have a hard time understanding the code but this should be pretty accurate:
<?php
class Log {
private $line = 0;
private $x;
private $y;
private $url;
private $list;
private $reps;
public function __construct($x, $y, $url, $list)
{
$this->x = $x;
$this->y = $y;
$this->url = $url;
$this->list = $list;
$points = [];
foreach ($list as $point) {
$points[$point['xy']] += 1;
}
$this->reps = max($points);
}
public function getX()
{
return $this->x;
}
public function getY()
{
return $this->y;
}
public function getUrl()
{
return $this->url;
}
public function getList()
{
return $this->list;
}
public function getReps()
{
return $this->reps;
}
public function next()
{
$coord = $this->list[$this->line];
$this->line += 1;
return $coord;
}
}
I'm not sure about the $points[$point['xy']] += 1; part as it doesn't really make sense to me so be sure to fix that as you see fit. Also, it is recommended to define setters manually instead of using the magic methods like __get().
Related
How can'i create a classe calculator witch can do ita differents operations like : addition , multiplication but with this format $test->two()->add()->one() ==> the result is 3.
Can you help me ?
thank you
class Test
{
private $result;
function __construct()
{
$this->result = 0;
}
function one()
{
$this->result = 1;
return $this;
}
function two()
{
$this->result = 2;
return $this;
}
function add()
{
$this->result += $this->result;
return $this;
}
function getResult()
{
return $this->result;
}
}
$test = new Test();
$a = $test->One()->add()->two();
var_dump($a->getResult());
I did this programm but i didn't had the correct response
the result returned is 2 but i must have 3 (1+2)
Here is a solution.
It works on the basis that add() or subtract() doesn't directly carry out any work, it simply sets a "pending" operation, and that one() or two() (I've shortcut that style to key($num) for simplicity though, I think it's better and more flexible as well) actually does the the last operation specified by add() or subtract(), using the number specified in the input.
It works by using PHP's ability to specify a function to call using a string value. Bit hacky but it seems to work.
class Calculator
{
private $result;
private $nextOp;
function __construct()
{
$this->result = 0;
$this->nextOp = "addVal";
}
function key($num)
{
$this->{$this->nextOp}($num);
return $this;
}
function add()
{
$this->nextOp = "addVal";
return $this;
}
function subtract()
{
$this->nextOp = "subtractVal";
return $this;
}
private function addVal($num)
{
$this->result += $num;
}
private function subtractVal($num)
{
$this->result -= $num;
}
function result()
{
return $this->result;
}
}
$test = new Calculator();
$a = $test->key(1)->add()->key(2)->key(3)->subtract()->key(2)->result();
var_dump($a);
This outputs 4.
N.B. It assumes that if you wrote e.g. key(1)->add()->key(2)->key(2) the second call to key(2) would also do an add, because that was the last operation specified (so the result would be 5 in that case), and also the initial operation is always add as well (although I guess you could allow that to be specified in the constructor). I don't know if these assumptions are acceptable in your scenario, you didn't specify what should happen if the user write something like this, or what the class should do with the initial value.
Live demo: http://sandbox.onlinephpfunctions.com/code/0be629f803261c35017ae49a51fa24385978568d
this is my response. It's worked very fine
// Interface des opérations
interface Operation {
public function plus();
public function minus();
public function divededInto();
public function times();
public function doOperation($value);
}
// Class Calculator
class Calculator implements Operation {
private $result;
private $operation;
private $numbers;
public function __construct($numbers) {
$this->numbers = $numbers;
$this->result = 0;
$this->operation = null;
}
//Surcharge de la méthode __call
public function __call($name, $arguments){
$name = strtolower($name);
$this->doOPeration($this->numbers[$name]);
$this->operation = null;
return $this;
}
// Exécution de l’opération
public function doOperation($value){
switch ($this->operation ){
case '+':
$this->result += $value;
break;
case '-':
$this->result -= $value;
break;
case '/':
$this->result = intDiv($this->result,$value);
break;
case '*':
$this->result *= $value;
break;
default : $this->result = $value;
}
}
class Point
{
private $x, $y;
public __construction ($x, $y)
{
$this->x = $x;
$this->y = $y;
}
public function getX()
{
return $this->x;
}
public function getY()
{
return $this->y;
}
}
first I would write this:
class Item
{
private $point; // Point
public __construction()
{
$this->point = new Point(0,0);
}
public function getPoint()
{
return $this->point;
}
}
and then:
$p = new Item();
$p->getPoint()->getX();
but they say it violates that law. After refactoring:
class Item
{
private $point; // Point
public __construction()
{
$this->point = new Point(0,0);
}
public function getPointX()
{
return $this->point->getX();
}
public function getPointY()
{
return $this->point->getY();
}
}
and then:
$p = new Item();
$p->getPointX();
this time getPointX() and getPointY() is just a redundant "transmission" method. I understand that ig Point has 1000 other methods, it would be unsafe to just return this all object as return $this->point. But this time all properties are covered.
Source
Because your $p requires more information about Point than it needs:
In particular, an object should avoid invoking methods of a member object returned by another method
I gave myself an exercise to understand the Command design pattern. I created interfaces for Placeable, Placer, and Placement where the idea was Placer would use the Placement command to change Placeable. I used simple x,y values for the place values. X and y in Placeable are private. (Shouldn't they be? Otherwise anything could change the location.) As you can see in the code below, my 'invoker' ended up inside the 'receiver.' This doesn't look like the examples I found online. Like this https://en.wikipedia.org/wiki/Command_pattern#Java. But, those examples use public properties. Have I done something really wrong in my exercise? As an aside, aren't examples which use public properties bad in terms of encapsulation? What is the point of Command designs if anything could access public properties or methods?
<?php
// receiver
interface Placeable
{
public function locate();
public function toPlace(Placement $placement);
}
// client
interface Placer
{
public function place(Placeable $placeable, $x=0, $y=0);
}
// command
interface Placement
{
public function setX($x=0);
public function setY($y=0);
public function getX();
public function getY();
}
///////////////////////////////////////////////////////////////////////
// receiver
class Book implements Placeable
{
private $x = 0;
private $y = 0;
public function locate()
{
return '(' . $this->x . ',' . $this->y . ')';
}
// invoker is inside the receiver, because the command changes private properties
public function toPlace(Placement $placement)
{
$this->x = $placement->getX();
$this->y = $placement->getY();
}
}
// command
class PlacementCommand implements Placement
{
private $x = 0;
private $y = 0;
public function setX($x=0)
{
$this->x = $x;
}
public function setY($y=0)
{
$this->y = $y;
}
public function getX()
{
return $this->x;
}
public function getY()
{
return $this->y;
}
}
// client
class Person implements Placer
{
public function place(Placeable $placeable, $x=0, $y=0)
{
$placement_command = new PlacementCommand();
$placement_command->setX($x);
$placement_command->setY($y);
$placeable->toPlace($placement_command);
}
}
?>
<pre>
<?php
$book = new Book();
$person = new Person();
$person->place($book, 3, 4);
//
echo var_dump($book);
?>
</pre>
For example consider class X that has some utility methods ('foo','bar') that do some operation on some property of X. These method are also useful for other external variable.
Some may implement X and staticX classes as below:class Foo
class StaticX
{
public static function foo($p)
{
return $p * $p;
}
}
class X
{
private $p=4;
public function foo()
{
return StaticX::foo($this->p);
}
}
$x= new x;
echo $x->foo();
echo StaticX::foo(3);
But this approach has some maintainability issues.
Is there any better solution?
class X
{
private $p;
public function foo()
{
return self::doFoo($this->p);
}
public static function doFoo($p)
{
return $p * $p;
}
}
I like foolishSeths answer, but what about this?
class X
{
private static $p;
public static function foo($p=null)
{
if ( is_null( $p ) ) {
$p = self::$p;
}
return $p * $p;
}
}
Since PHP 5.4 you can make use of traits. See http://www.php.net/manual/en/language.oop5.traits.php
trait fooBehavior {
function getFoo() { return self::foo($this->p); }
static function foo($p) { return $p * $p; }
}
class X {
use fooBehavior;
private $p;
public function __construct($p) { $this->p = $p; }
}
$x = new X(2);
echo $x->getFoo(); // echoes 4
echo $x::foo(2); // echoes 4
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;
}