PHP trait : What is the logical error in this Code - php

I have invested approximately 4 hours on this code but not getting the Required Result while the Code Snippet is running normally. The Code is as follows:
trait CircleShape{
public function input($radius){
$this->$radius = $radius;
}
}
trait AngleShape{
public function input($height, $width){
$this->$height = $height;
$this->$width = $height;
}
}
trait GeneralMethod{
public function get($property){
return $this->$property;
}
}
class Shape{
private $height, $width, $radius;
const PI = 3.1415;
use GeneralMethod, AngleShape, CircleShape{
AngleShape::input insteadof CircleShape;
CircleShape::input as inputCircle;
}
}
class Circle extends Shape{
public function area(){
return parent::PI * $this->get('radius') * $this->get('radius');
}
}
class Rectangle extends Shape{
use GeneralMethod, AngleShape, CircleShape{
AngleShape::input insteadof CircleShape;
CircleShape::input as inputCircle;
}
public function area(){
return $this->get('height') * $this->get('width');
}
}
$rect = new Rectangle;
$rect->input(12, 2);
Echo "Area: " . $rect->area() . "\n";
$cir = new Circle;
$cir->inputCircle(10);
Echo "Circle Area : " . $cir->area() . "\n";
What is the Logic Error in this Code?
Why I am getting following Output:
Rectangle Area : 0
Circle Area : 0

$this->$radius = $radius;
should be
$this->radius = $radius;
And same with $height and $width.

here you are trying by The pseudo-variable $this and arrow operator (->) for calling one variable then you should drop off $ in-front of variable

Related

Practicing Loose'ly Coupling code in php

I'm new to PHP or any progamming language and im practic'n how to code a loose coupling
<?php
interface IPolygon{
public function getArea();
}
class Polygon{
private $ipolygon;
public function __construct(IPolygon $ipolygon){
$this->ipolygon = $ipolygon;
}
public function calArea(){
return this->ipolygon->getArea();
}
}
class Circle implements IPolygon{
private $radius;
private $pi = 3.14;
public function __construct($radius){
$this->radius = $radius;
}
public function getArea(){
return $pi*$radius*$radius;
}
}
class Triangle implements IPolygon{
private $base;
private $height;
public function __construct($base , $height){
$this->base = $base;
$this->height = $height;
}
public function getArea(){
return $base*$height/2;
}
}
$c = new Circle(14);
$p = new Polygon($c);
echo "<hr />";
$p->calArea();
?>
Error
Notice: Undefined variable: ipolygon in C:\xampp\htdocs\OOP\Polygon.php on line 16
Notice: Undefined variable: pi in C:\xampp\htdocs\OOP\Polygon.php on line 30
Notice: Undefined variable: radius in C:\xampp\htdocs\OOP\Polygon.php on line 30
Notice: Undefined variable: radius in C:\xampp\htdocs\OOP\Polygon.php on line 30
can someone explain me how is it done?
As a general rule all class properties are referenced using $this->
That means:
<?php
interface IPolygon{
public function getArea();
}
class Polygon{
private $ipolygon;
public function __construct(IPolygon $ipolygon){
$this->ipolygon = $ipolygon;
}
public function calArea(){
return $this->ipolygon->getArea();
}
}
class Circle implements IPolygon{
private $radius;
private $pi = 3.14;
public function __construct($radius){
$this->radius = $radius;
}
public function getArea(){
return $this->pi*$this->radius*$this->radius;
}
}
class Triangle implements IPolygon{
private $base;
private $height;
public function __construct($base , $height){
$this->base = $base;
$this->height = $height;
}
public function getArea(){
return $this->base*$this->height/2;
}
}
$c = new Circle(14);
$p = new Polygon($c);
echo "<hr />";
$p->calArea();
It works: http://sandbox.onlinephpfunctions.com/code/e7f79bb186ffac952ebc4c2b5a8098e1efaeb874

Which is best $this or self or static when referencing const variable?

I learned that static is better than self because self does late static binding.
But I wonder which would be best at referencing const variable.
class Black
{
const color = 'black';
public function byThis()
{
return $this::color;
}
public function bySelf()
{
return self::color;
}
public function byStatic()
{
return static::color;
}
}
I checked all of three getters work well. Which is the best choice? (I use PHP 7.0)
Keywords self and static are different in this way:
class White {
const color = "white";
public function byThis()
{
return $this::color;
}
public function bySelf()
{
return self::color;
}
public function byStatic()
{
return static::color;
}
}
class Black extends White
{
const color = "black";
}
$black = new Black;
echo "byThis: " . $black->byThis() . PHP_EOL;
echo "bySelf: " . $black->bySelf() . PHP_EOL;
echo "byStatic: " . $black->byStatic() . PHP_EOL;
Output:
byThis: black
bySelf: white
byStatic: black
I would expect output to be black with $black instance, so static is better in my opinion.
The PHP class constants documentation recommends the use of self:: for a constant within a class. I personally would stay with this.
Every one of the keywords return the same value, even if the class extends another class with another value for the constant, except for parent:: which returns the value of the parent class:
class White {
const color = "white";
}
class Black extends White
{
const color = "black";
public function byThis()
{
return $this::color;
}
public function bySelf()
{
return self::color;
}
public function byStatic()
{
return static::color;
}
public function byParent() {
return parent::color;
}
}
$black = new Black;
echo "byThis: " . $black->byThis() . PHP_EOL;
echo "bySelf: " . $black->bySelf() . PHP_EOL;
echo "byStatic: " . $black->byStatic() . PHP_EOL;
echo "byParent: " . $black->byParent() . PHP_EOL;
The output would be:
byThis: black
bySelf: black
byStatic: black
byParent: white

Calling my objects and its functions

I am new to php and trying using Factory Method.
I want to instantiate my class Shapes using 'build' function,such that when the class 'Circle' is instantiated its area and circumference is calculated and if the class 'Rectangle' is called ,its area and circumference is calculated and returned.
This is what I have so far and what i want to achieve.This doesnt work and i am sure there is a better way of doing it!
$allmyshapes = Shapes::build($initData);
foreach($allmyshapes as $value) {
if ($value =='Circle'){
$x = new Circle();
echo $x::area();
echo $x::circumference();
}
if ($value =='Rectangle'){
$y = new Rectangle();
echo $y::area();
echo $y::circumference();
}
}
My Class:
class Shapes {
public static function build($initData){
}
foreach($newlist as $value){
if($value[0]=='Circle'){
$shape1 =new Circle($value[1],$value[2]);
}
if($value[0]== 'Rectangle'){
$shape2 =new Rectangle($value[1],$value[2]);
}
}
return array($shape1,$shape2);
}
}
class Circle extends Shapes {
public $radius;
public $centre_point;
public function __construct($radius, $centre_point) {
$this->radius = $radius;
$this->centre_point = $centre_point;
}
public function area(){
return (pi() *$this->radius * $this->radius);
}
public function circumference(){
return 2 * pi() *$this->radius;
}
}
class Rectangle extends Shapes {
public $x;
public $y;
public function __construct($x, $y) {
$this->x= $x;
$this->y = $y;
}
public function area() {
return $this->x * $this->y;
}
public function circumference() {
return 2 * ($this->x+ $this->y);
}
}
There's nothing wrong with your classes, it was how you were using them to output information:
class Shapes {
public static function build($initData){
//$initdata is a heredoc
$newlist = explode("\n", $initData);
foreach($newlist as $key => $initData){
$newlist[$key] = explode("\t", $initData);
}
foreach($newlist as $value){
if($value[0] == 'Circle'){
$shape1 = new Circle($value[1], $value[2]);
}
if($value[0] == 'Rectangle'){
$shape2 = new Rectangle($value[1], $value[2]);
}
}
return array($shape1, $shape2);
}
}
class Circle extends Shapes {
public $radius;
public $centre_point;
public function __construct($radius, $centre_point){
$this->radius = $radius;
$this->centre_point = $centre_point;
}
public function area(){
return (pi() * $this->radius * $this->radius);
}
public function circumference(){
return 2 * pi() * $this->radius;
}
public function draw(){
return ( $this->radius.":".$this->centre_point);
}
}
class Rectangle extends Shapes {
public $x;
public $y;
public function __construct($x, $y){
$this->x = $x;
$this->y = $y;
}
public function area(){
return $this->x * $this->y;
}
public function circumference(){
return 2 * ($this->x + $this->y);
}
}
$initData = <<<ENDINIT
Circle 5 2
Rectangle 5 10
Ellipse 10 10 4 5
ENDINIT;
$allmyshapes = Shapes::build($initData);
foreach($allmyshapes as $value){
if(get_class($value) === 'Circle'){
echo nl2br("**Circle**\nArea: ".$value->area()."\nCircumference: ".$value->circumference()."\n");
}
if(get_class($value) === 'Rectangle'){
echo nl2br("**Rectangle**\nArea: ".$value->area()."\nCircumference: ".$value->circumference()."\n");
}
}
I added 2 functions to your provided code, get_class() & nl2br(). the nl2br can be removed if you are using this in CLI format, but its main function was for output readability when using a web browser to view the output.
get_class() will solve your issue of trying to figure out what constructor was used in the creation of the object.

How to assign a value to public properties from outside of the class in PHP OOP

I want to assign a value to a property of an object. I think it should be something like this:
$object->property = "value";
So, in my case I do:
$circle_obj->radius = 4;
So, I expected that property radius should be 4. Unfortunately, this is not the case in my situation. Can you understand why?
Below you can see my code.
<?php
class BaseClass{
public function calcSurface(){
//empty method
}
}
class Subclass_Circle extends BaseClass{
public $radius;
public function calcSurface(){
global $radius;
return M_PI * ($radius * $radius);
}
}
$circle_obj = new Subclass_Circle();
$circle_obj->radius = 4;
echo "Oppervlakte van circle is: " . $circle_obj->calcSurface(); //ouput: 0
echo "<br>";
class Subclass_Square extends BaseClass{
public $width;
public $height;
public function calcSurface(){
global $width;
global $height;
return $width * $height;
}
}
$square_obj = new Subclass_Square();
$square_obj->width = 4;
$square_obj->height = 4;
echo "Oppervlakte van vierkant is: " . $square_obj->calcSurface(); //output: 0
?>
You shouldn't be using global, but instead $this, like so:
public function calcSurface(){
return M_PI * ($this->radius * $this->radius);
}
Check out the PHP OOP tutorial for more information.
And look at the variable scope tutorial to better understand the global keyword.

I want to initialize attribute without creating object

when I run the below code I got error in line echo $attribute;
The error code: "Catchable fatal error: Object of class SomeShape could not be converted to string in ":
What wrong in this code?
Thanks.
<?php
class Shape
{
static public $width;
static public $height;
}
class SomeShape extends Shape
{
public function __construct()
{
$test=self::$width * self::$height;
echo $test;
return $test;
}
}
class SomeShape1 extends Shape
{
public function __construct()
{
return self::$height * self::$width * .5;
}
}
Shape::$width=60;
Shape::$height=5;
echo Shape::$height;
$attribute = new SomeShape;
echo $attribute;
$attribute1 = new SomeShape1;
echo $attribute1;
?>
What you are trying to do is echo an object, its like you are echoing an array(worst than echoing an array since echoing an object throuws error), while what you should be doing is accessing it's attribute or method etc. However if u wanna c what is in your object, you gotto use var_dump instead of echo .
In short, echo $attribute is wrong. Use var_dump($attribute)
Don't do a return in a constructor.
If you want to echo a value, trys to add a __toString() function (manual)
You cannot echo an object without implementing the __toString method.
Alternatively you could var_dump the object:
var_dump($attribute);
But what I think you are actually trying to do is more like this:
class Shape {
public $width;
public $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
}
class SomeShape extends Shape {
public function getArea() {
return $this->width * $this->height;
}
}
class SomeShape1 extends Shape {
public function getHalfArea() {
return $this->width * $this->height * .5;
}
}
$shape = new SomeShape(10, 20);
echo $shape->getArea();
$shape = new SomeShape1(10, 20);
echo $shape->getHalfArea();
the solution that I found is:
I don't want to add more attribute to class shape but this solve my problem as I wish.may be there is more similar solution I will love to see. but this is my idea I define in class shape "public $attribute;" Inside the class SomeShape I wrote on "public function __construct()" "$this->attribute=self::$width * self::$height;" In the main scope I wrote "echo $object->attribute."";"
<?php
class Shape
{
static public $width;
static public $height;
public $attribute;
}
class SomeShape extends Shape
{
public function __construct()
{
$this->attribute=self::$width * self::$height;
}
}
class SomeShape1 extends Shape
{
public function __construct()
{
$this->attribute=self::$width * self::$height * .5;
}
}
Shape::$width=60;
Shape::$height=5;
$object = new SomeShape;
echo $object->attribute."<br />";
$object1 = new SomeShape1;
echo $object1->attribute;
?>

Categories