Access outer variables from anonymous class - php

I was trying an alternative way of doing this :
public function index()
{
$faker = Faker\Factory::create('fr_FR');
$ideas = [];
for ($i = 1; $i <= rand(10, 50); $i++) {
$idea = new \stdClass;
$idea->id = $i;
$idea->author = $faker->name;
//...
$ideas[] = $idea;
}
}
Instead of creating object and assigning attributes in the loop, I would like to create the object from a class, and populate $ideas[] with the array_pad() function :
public function index()
{
$faker = Faker\Factory::create('fr_FR');
$ideas = [];
$idea = new class {
private $id;
private $author;
function __construct() {
$this->id = count($ideas) + 1;
$this->author = $faker->name;
}
};
array_pad($ideas, rand(10, 50), new $idea);
}
So I need to access $faker and $ideas from the anonymous class. I tried to pass them to the class like this :
$idea = new class($ideas, $faker) {
private $id;
private $author;
private $ideas
private $faker
function __construct($ideas, $faker) {
$this->id = count($ideas) + 1;
$this->author = $faker->name;
}
};
But I get a
Too few arguments to function class#anonymous::__construct(), 0 passed

Sad news: you cant use array_pad for this.
Here the fixes you need to apply to get rid of the error:
// array_pad($ideas, rand(10, 50), new $idea);
array_pad($ideas, rand(10, 50), $idea); // remove new
Since you did the new already here:
$idea = new class($ideas, $faker) {
Even though this will fill $ideas. It will store the same reference to your $idea over and over. Which means if you alter one element this change will be on all elements (i guess this is not desired).
In order to get this working you will have to use a loop, which creates a new $idea for every entry:
$faker = Faker\Factory::create('fr_FR');
$ideas = [];
for ($i = rand(10, 50); $i > 0; $i--) {
$ideas[] = new class($ideas, $faker) {
private $id;
private $author;
function __construct($ideas, $faker) {
$this->id = count($ideas) + 1;
$this->author = $faker->name;
}
};
}
Working example.
Additional information
Instead of doing this
for ($i = 1; $i <= rand(10, 50); $i++)
better do this
for ($i = rand(10, 50); $i > 0; $i--)
The reason is the comparison is getting called on every loop, so you generating a new random number on every loop. Example
This is problematic because you tend to get way more low numbers like this. For example to get 50 loops the random has to return > $i every time - which is very unlikely.
One more thing: array_pad returns the filled array, so you'd have to write
$ideas = array_pad(...

Related

How to debug an issue in the code sum of digit?

I am having an issue in the code
Warning: Cannot use a scalar value as an array in /opt/lampp/htdocs/programe/sumDigit.php on line 410
Here is the code:
class SumOfDigit{
public $sum = 0;
public $num ;
public function __construct($n) {
$this->num = $n;
}
public function equation() {
for($i= 0; $i<strlen($this->num); $i++){
$this->num[$i] = array_map('intval', str_split($this->num));
$this->sum += $this->num[$i];
print_r($this->sum);
}
}
}
$obj = new SumOfDigit(232);
echo $obj->equation();
Based on the name of your class I assume you want to sum the digits in the value you create an object of the class with. In that case, you can simplify your code by using array_sum on the output of str_split:
Class SumOfDigit{
public $sum = 0;
public $num;
public function __construct($n){
$this->num = $n;
}
public function equation(){
$this->sum = array_sum(str_split($this->num));
return $this->sum;
}
}
$obj = new SumOfDigit(232);
echo $obj->equation();
Output:
7
Demo on 3v4l.org
In your code first you assigned a integer to "num"
$this->num = $n;
and inside the function equation() you are using the same value as array as well
$this->num[$i] = array_map('intval', str_split($this->num));
Change the name any one of the variable and try.
Hope it helps

Class with constructor is slower in PHP

I have created two classes:
class TestClass
{
public $id;
public $name;
public $time;
}
class TestClassCtor
{
public $id;
public $name;
public $time;
public function __construct()
{
}
}
Now I run a simple code:
$tt = microtime(true);
$data = array();
for ($i = 0; $i < 10000; $i++)
{
$t = new TestClass();
$t->id = rand();
$t->name = rand();
$t->time = rand();
$data[] = $t;
}
echo microtime(true) - $tt;
echo "\n";
$tt = microtime(true);
$data1 = array();
for ($i = 0; $i < 10000; $i++)
{
$t = new TestClassCtor();
$t->id = rand();
$t->name = rand();
$t->time = rand();
$data1[] = $t;
}
echo microtime(true) - $tt;
Now, the second code with TestClassCtor is around 30% slower. Why? (tested with PHP 5.6 and 7.1).
Edit:
The similar difference can be spotted with (in this case, I can understand it - passing arguments to method may be slower).
class TestClassCtorFill
{
public $id;
public $name;
public $time;
public function __construct($id, $name, $time)
{
$this->id = $id;
$this->name = $name;
$this->time = $time;
}
}
In this case, I can create class in one line as
for ($i = 0; $i < 10000; $i++)
{
$data1[] = new TestClassCtorFill(rand(), rand(), rand());
}
Yes, this is safer, because user must set all three parameters and he wont forget to set something.
However, when I use this inside my internal framework class, I can omit the ctor entirely and set members directly as with TestClass to save some time. For a few instances, this wont be a much of a difference. But if I create tousands of them, it could be.
Edit 2
I know about cost of a function call. However, constructor is called upon new, so if I write or not one, some constructor should be called. If there is no constructor provided by user a default one is caled. Memory for object must be allocated either way.

Is it faster to create a new class inside a function or pass it as a parameter in PHP

I've got a class that is used in a few functions independently from one another. So my question is: is it faster to pass the initiated class as a parameter to the function or to create a new instance every time the function is called upon?
Like this:
$class_a = new Class_a;
function rnd_fun($class_a){
... do stuff...
}
Or like this:
function rnd_fun(){
$class_a = new Class_a;
... do stuff...
unset($class_a);
}
I tried to do a benchmark and these are the results by using this
very creative class
class Class_a {
public $first_name = "";
public $age = "";
public function setVar($first_name, $age){
$this->first_name = $first_name;
$this->age = $age;
}
public function wasteTime(){
$i = 0;
while($i < 100){
$this->age = $this->age * $i;
$this->age = $this->age / pi();
$i++;
}
}
}
By passing the class as a parameter I got something around 0.46s using this code:
$class_a = new Class_a;
$i = 0;
while($i < 10000){
test($class_a);
$i++;
}
function test($class_a){
$class_a->setVar("Geronimo", "72.1");
$class_a->wasteTime();
}
This is by initiating a new class inside the function:
$i = 0;
while($i < 10000){
test();
$i++;
}
function test(){
$class_a = new Class_a;
$class_a->setVar("Geronimo", "72.1");
$class_a->wasteTime();
unset($class_a);
}
I have to point out though that the second method took a slightly higher time to execute (around 0.47s).
However I believe that the difference between the two is negligible since both run at around the same speed for this many iteration and their delay won't be noticeable in an average piece of code.

i am trying to make a array of a object in php

I'm trying to make an array of Spells.
My current code
class Spell
{
public $bomb = 0;
public $fire = 0;
function Spell()
{
$this->bomb =0;
$this->fire =0;
}
}
And I declare the object spell on my game class like this
class game
{
public $Spell=array();
function Game()
{
$this->Spell[0] = new Spell();
}
function s()
{
$this->Spell[1]->$bomb = $load($x)
$this->Spell[1]->$fire = $load($x);
$this->Spell[2]->$bomb = $load($y)
$this->Spell[3]->$bomb = $load($z)
}
}
It returns this error -- Warning: Creating default object from empty value in...
I guess this isn't the best way to create an array of objects. How to do it properly?
EDIT:
x y z, just return strings
The problem is that you have not created objects for $this->Spell[1], $this->Spell[2] and $this->Spell[3]. If you change your Game() constructor to this:
function Game()
{
for ($i = 1; $i <= 3; $i++) {
$this->Spell[$i] = new Spell();
}
}
It should probably work fine.
You seem to have more than just one problems in your code.
However, I will discuss the one you have asked the question for.
Instead of
$this->Spell[1]->$bomb = something;
Use
$this->Spell[1]->bomb = something;
Second, What do you intend to do by using $load($y)?
If you're using a function named "load", use load($y)
you must create object, then use it, look:
class Spell
{
public $bomb = 0;
public $fire = 0;
function __construct()
{
$this->bomb =0;
$this->fire =0;
}
}
class game
{
public $Spell=array();
function s()
{
$this->Spell[1] = new Spell();
$this->Spell[1]->bomb = 0 ; //or other value
}
}
<?php
class Spell
{
public $bomb = 0;
public $fire = 0;
function Spell()
{
$this->bomb =0;
$this->fire =0;
}
}
class game
{
public $Spell=array();
function Game($index)
{
$this->Spell[$index] = new Spell();
echo 'constructer called';
}
function s()
{
$this->Spell[1]->bomb = $load($x);
$this->Spell[1]->fire = $load($x);
$this->Spell[2]->bomb = $load($y);
$this->Spell[3]->bomb = $load($z);
}
}
$ob = new game();
//$ob->Game(1); to pass the index for array.
?>
You are using lots of undefined stuff, I would say the half of your script is missing.
I just added the comments down here:
class game
{
public $Spell=array();
function Game()
{
$this->Spell[0] = new Spell();
}
function s()
{
/**
down here you are using these undefined "variables":
$bomb
$load
$x
$y
$z
undefined means, you are using a varible which was not declared. so it´s just null.
I tried to fix it:
**/
$x = 1;
$y = 2;
$z = 3;
$this->Spell[1] = new Spell();
$this->Spell[2] = new Spell();
$this->Spell[3] = new Spell();
$this->Spell[1]->bomb = load($x); // add ;
$this->Spell[1]->fire = load($x);
$this->Spell[2]->bomb = load($y)
$this->Spell[3]->bomb = load($z)
}
}
function load($v)
{
return $v * 2;
}

PHP many objects with one Class

I'm very new with PHP and OOP techniques.
So I have no problem creating a object like so:
$member1 = new Member('person 1');
But is there a way to return a bunch of objects. So that I can iterate through them and put them in the DOM?
class Example
{
public function getPeople()
{
$objs = array();
for($i = 0; $i < 10; $i++)
{
$obj[] = new Person('Person ' . ($i + 1));
}
return $objs; // returning an array of Person objects
}
}
$example = new Example();
foreach($example->getPeople() as $person)
{
// Do something with $person
}
In order to get objects, one possible way is to use array :-
$members = new members( array(...));
// you can assess any member via $members->members[$some_id]
// class to return list of members
class members ()
{
public $members = array();
public function __construct( array $ids)
{
foreach ($id as $id)
{
$this->members[$id] = new Member($id);
}
}
}
class member()
{
public function __construct($id)
{
// any other thing you want to do
}
}

Categories