I created this little guy to get large session IDs for my own purposes:
// returns a 1024-byte hash for session IDs
class sha512_session {
private $IDvalue = '';
private $IDMAX_SALT = mt_getrandmax();
for ($i = 0; $i < 8; $i++) {
$seed = mt_rand(100, $IDMAX_SALT);
$IDvalue .= strtoupper(hash('sha512', $seed, false));
}
public function getID() {
return $IDvalue;
}
}
Outside of a class context, the for() loop works like it should. When I put this (working) code in the class above, PHP returns the following:
Parse error: syntax error, unexpected '(', expecting ',' or ';' in ../sha-iterator.php on line ... ( line # for "private $IDMAX_SALT = mt_getrandmax()" )
So, it works fine outside a class and breaks inside a class. Where did I mess up?
The For loop must be placed within a function. I think you should place it in a constructor.
class sha512_session {
private $IDvalue = '';
private $IDMAX_SALT;
function __construct() {
$this->IDMAX_SALT = mt_getrandmax();
for ($i = 0; $i < 8; $i++) {
$this->seed = mt_rand(100, $this->IDMAX_SALT);
$this->IDvalue .= strtoupper(hash('sha512', $this->seed, false));
}
}
public function getID() {
return $this->IDvalue;
}
}
Ok a comment on here answered my question. Class property initialization during declaration must be a constant at compile time, but mt_getrandmax() is runtime info, so it fails. The correct way here is to declare the variable, then initialize it separately:
class sha512_session {
private $IDvalue = '';
private $IDMAX_SALT;
private function getRandomMax() {
$this->IDMAX_SALT = mt_getrandmax();
return $this->IDMAX_SALT;
}
function __construct() {
for ($i = 0; $i < 8; $i++) {
$this->seed = mt_rand(100, $this->getRandomMax());
$this->IDvalue .= strtoupper(hash('sha512', $this->seed, false));
}
}
public function getID() {
return $this->IDvalue;
}
}
$sessionID = new sha512_session();
echo $sessionID->getID();
Or any variation on that theme.
Related
This question already has answers here:
PHP parse/syntax errors; and how to solve them
(20 answers)
Reference - What does this error mean in PHP?
(38 answers)
Closed 3 years ago.
Parse error: syntax error, unexpected 'public' (T_PUBLIC), expecting end of file in C:\xampp\htdocs\example.php on line 9
I'm getting this error, but can't see nothing wrong with the code.
What did I wrong? Won't return the expected results.
The program is supposed to show: echo $myorder->OrderTotal();
<?php
class CartEntry
{
//changing to private
private $Price;
private $Quantity;
}
//Adding functions to get price and quantity,
public function __construct($Price, $Quantity)
{
$this->Price = $Price;
$this->Quantity = $Quantity;
}
public function ReturnPrice() {
return $this->Price;
}
public function ReturnQuantity() {
return $this->Quantity;
}
}
//
class CartContents
{
//Changed to private
private $items = array();
}
//Adding function to return items, same as above
public function __construct($items) {
$this->items = $items;
}
public function ReturnItems() {
return $this->items;
}
}
class Order
{
private $cart;
private $salesTax;
//cartcontents function removed
function __construct( float $salesTax, Array $items){
$this->salesTax = $salesTax;
$this->items = $items;
}
function OrderTotal()
{
$cartTotal = 0;
for ($i = 0; $i < count($this->items); $i++) {
$cartTotal += $this->items[$i]->Price * $this->items[$i]->Quantity;
}
$cartTotal += $cartTotal * $this->salesTax;
return $cartTotal;
}
}
$entry1 = new CartEntry();
$entry1->Price = 1.2;
$entry1->Quantity = 120;
$entry2 = new CartEntry();
$entry2->Price = 2.2;
$entry2->Quantity = 200;
$mycart = new CartContents();
$mycart->items = array($entry1, $entry2);
$items = $mycart->ReturnItems();
$mytax = 0.2;
//Items variable can be changed with mycart
$myorder = new Order($items, $mytax);
echo $myorder->OrderTotal();
?>
Here is the corrected code:
<?php
class CartEntry
{
//changing to private
private $Price;
private $Quantity;
public function __construct($Price, $Quantity)
{
$this->Price = $Price;
$this->Quantity = $Quantity;
}
public function ReturnPrice() {
return $this->Price;
}
public function ReturnQuantity() {
return $this->Quantity;
}
}// end class
class CartContents
{
//Changed to private
private $items = array();
public function __construct($items) {
$this->items = $items;
}
public function ReturnItems() {
return $this->items;
}
} // end class
class Order
{
private $cart;
private $salesTax;
function __construct( float $salesTax, Array $items){
$this->salesTax = $salesTax;
$this->items = $items;
}
function OrderTotal()
{
$cartTotal = 0;
for ($i=0, $max=count($this->items); $i < $max; $i++) {
$cartTotal += $this->items[$i]->ReturnPrice() * $this->items[$i]->ReturnQuantity();
}
$cartTotal += $cartTotal * $this->salesTax;
return $cartTotal;
}
}
$entry1 = new CartEntry(1.2, 120);
$entry2 = new CartEntry(2.2,200);
$mycart = new CartContents([$entry1,$entry2]);
$items = $mycart->ReturnItems();
$mytax = 0.2;
//Items variable can be changed with mycart
$myorder = new Order($mytax,$items);
echo $myorder->OrderTotal();
See live code.
One should avoid putting a brace after declaring class properties if the class has methods; that's what caused the error message that the OP encountered. As per the online Manual:
... class definitions begin with the keyword class, followed by a
class name, followed by a pair of curly braces which enclose the
definitions of the properties and methods (emphasis mine) belonging to the class.
Don't let the term 'function' fool you. If it's in a class it is a method; see this discussion.
But after fixing that issue there were others.
If you are suppose to initialize properties in a constructor, then you need to pass in the correct parameters when you instantiate an object, instead of trying to set those properties as if they were public.
Note, also that when an object has methods for reading private properties then you need to use those methods instead of trying to access the private properties directly.
Lastly, I changed this line of code
for ($i=0; $i < count($this->items); $i++) which executes correctly but it is more efficient to count the items just once instead of doing it on every iteration, so I inserted instead:
for ($i=0, $max=count($this->items); $i < $max; $i++){
You should put all your methods inside the class. In your code, the class CartEntry only contains 2 private variables:
class CartEntry
{
//changing to private
private $Price;
private $Quantity;
}
Anything outside the class will be considered invalid.
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.
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
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;
}
I had some free time and decided to benchmark a couple of options for a custom logging system I will be implementing in my application. The point is to simply log events during execution from different classes and functions into an array that can later be examined.
While trying these out I saw something that puzzled me: Using a trait to modify a variable in another class takes longer than modifying a variable in "self". It also takes longer than modifying the variable directly.
I'm not exactly interested in miniscule performance gains, and have not yet decided on the final implementation either. I'm just curious about why this happens.
Here's the code to test it. I also did some other tests, but they were slower for obvious reasons.
class ExternalStore {
public static $log = [];
}
trait LoggerTrait {
public static function addLog($time, $event) {
return [$time, $event];
}
}
echo "<h1>Changing external variable directly</h1>";
class ExternalAppend {
public function doStuff() {
for ($i = 0; $i < 100000; $i++) {
ExternalStore::$log += [microtime(), "Stuff done"];
}
}
}
$ExternalAppend = new ExternalAppend;
$start = microtime(true);
$ExternalAppend->doStuff();
$time = microtime(true) - $start;
echo "Execution time: $time<hr>"; // ~0.18...
echo "<h1>Using a trait to change internal variable</h1>";
class TraitUser {
use LoggerTrait;
public static $log = [];
public function doStuff() {
for ($i = 0; $i < 100000; $i++) {
self::$log += self::addLog(microtime(), "Stuff done");
}
}
}
$TraitUser = new TraitUser();
$start = microtime(true);
$ExternalAppend->doStuff();
$time = microtime(true) - $start;
echo "Execution time: $time<hr>"; // ~0.18...
echo "<h1>Using a trait to change external variable</h1>";
class TraitUserExternal {
use LoggerTrait;
public function doStuff() {
for ($i = 0; $i < 100000; $i++) {
ExternalStore::$log += self::addLog(microtime(), "Stuff done");
}
}
}
$TraitUserExternal = new TraitUserExternal();
$start = microtime(true);
$TraitUserExternal->doStuff();
$time = microtime(true) - $start;
echo "Execution time: $time<hr>"; // ~0.30...
Finally had some time to look into this and the solution was simple. The problem was calling $ExternalAppend->doStuff() instead of $TraitUser->doStuff() on line 41. After fixing this the execution times of TraitUser and TraitUserExternal are similar. There is also a mistake of using $var += [$val1, $val2] instead of $var[] = [$val1, $val2], but that doesn't seem to affect the differences. Only the total execution time.
Slower performance in TraitUser andTraitUserExternal compared to ExternalAppend comes from the combined overhead of calling a function and using a return value.
The following code confirms the findings. Modifying a variable directly without calling any functions is the fastest way. Calling a function and modifying the variable there is the second fastest. Third (marginally slower than the second) way is modifying a variable with a value returned from a function.
The fourth function doStuff4() also shows a better way of using a trait to modify a variable in another class.
<?php
trait Logger {
protected static function modifyInternalValue($time, $event) {
self::$internalLog[] = [$time, $event];
}
protected static function returnValue($time, $event) {
return [$time, $event];
}
protected static function modifyExternalValue($time, $event) {
ExternalLogger::$externalLog[] = [$time, $event];
}
}
class ExternalLogger {
public static $externalLog = [];
public static function modifyValue($time, $event) {
self::$externalLog[] = [$time, $event];
}
}
class LoggerUser {
use Logger;
public static $internalLog = [];
protected static $iterations = 10000;
public function doStuff1() {
echo "<h1>1 - Directly modifying an internal variable</h1>";
for ($i = 0; $i < self::$iterations; $i++) {
self::$internalLog[] = [microtime(), "Stuff done"];
}
}
public function doStuff2() {
echo "<h1>2 - Trait returns a value to internal variable</h1>";
for ($i = 0; $i < self::$iterations; $i++) {
self::$internalLog[] = self::returnValue(microtime(), "Stuff done");
}
}
public function doStuff3() {
echo "<h1>3 - Trait modifies a variable inside a function</h1>";
for ($i = 0; $i < self::$iterations; $i++) {
self::modifyInternalValue(microtime(), "Stuff done");
}
}
public function doStuff4() {
echo "<h1>4 - Trait modifies a variable of an external class</h1>";
for ($i = 0; $i < self::$iterations; $i++) {
self::modifyExternalValue(microtime(), "Stuff done");
}
}
public function doStuff5() {
echo "<h1>5 - External class modifies a variable in itself</h1>";
for ($i = 0; $i < self::$iterations; $i++) {
ExternalLogger::modifyValue(microtime(), "Stuff done");
}
}
}
function profileFunction($function) {
$LoggerUser = new LoggerUser();
$start = microtime(true);
$LoggerUser->$function();
$time = microtime(true) - $start;
echo "Execution time: $time<hr>";
}
profileFunction("doStuff1"); // Fast | Direct modification
profileFunction("doStuff2"); // Slowest | Function returns a value
profileFunction("doStuff3"); // Slower | Function modifies a value
profileFunction("doStuff4"); // Slower | Function modifies external class
profileFunction("doStuff5"); // Slower | External class modifies itself