PHP Array VS [ ] in Method and Variable Declaration

PHP array vs [ ] in method and variable declaration

PSR-2 and PSR-12 (by PHP Framework Interoperability Group) do not mention short array syntax. But as you can see in chapter 4.3 they use short array syntax to set the default value of $arg3 to be an empty array.

So for PHP >= 5.4 the short array syntax seems to be the de-facto standard. Only use array(), if you want your script to run on PHP <5.4.

The speed of variables vs arrays in php

Speed and memory are likely to be irrelevant. Write clean, direct code.

If you are going to be iterating or searching these values, use an array.

As a fundamental rule, I don't declare single-use variables. Only in fringe cases where readability is dramatically improved do I break this rule.

Should Class Properties be Stored as Variables or in an Array

It all depends on what you are trying to acchieve. Storing all properties in an (associative) array will make life easier for you if you wish to implement any of the Traversable interfaces, though there are ways to do this, too, with predefined properties.

If by best, you mean fastest: defining each property beforehand will make your classes more performant as I explained here already

There are, of course, a lot more reasons why the first approach is the better one I've listed them here

Basically, what you need to know is that PHP's "overloading" of objects is slow (O(1) for declared properties vs O(n) for overloaded properties). The same goes for magic methods, like __get and __set. They're slow. Consider this:

class Declared
{
private $foo = 123;
public function setFoo($val)
{
$this->foo = (int) $val;
return $this;
}
public function getFoo()
{
return $this->foo;
}
public function __get($name)
{
$name = 'get'.ucfirst($name);
if (method_exists($this, $name))
{
return $this->{$name}():
}
//return null or throw exception
throw new RuntimeExcpetion('attempted to access non-existing property using '.$name.' in '.__METHOD__);
}
public function __set($name, $val)
{
$mname = 'set'.ucfirst($name);
if (method_exists($this, $mname))
{
return $this->{$mname}($val):
}
throw new RuntimeException($name.' is an invalid property name');
}
}

Not only can I be certain that, at no point, new properties will be added, but because I'm using custom getters and setters, I can also ensure that the type of each property is what I want/expect it to be. In this example, I need $foo to be an integer, so in the setter, I cast whatever value that is being passed as an argument to an int. You can do that in a magic __set method, too, but the more properties you're dealing with the messier that method will become (tons of if's and else's).

Compare this, now, to this class:

class NotDeclared
{
private $data = array('foo' => 123);
public function __get($name)
{
return isset($this->data[$name]) ? $this->data[$name] : null;
}
public function __set($name, $value)
{
$this->[$data] = $value;
}
}

Now, this class does look a lot shorter, so I can see why this would appeal to anyone. Yet, let's compare both in terms of usage:

$declared = new Declared;
$notDeclared = new NotDeclared;
echo $declared->foo;//ok
echo $declared->getFoo();//ok
echo $notDeclared->foo;//ok
$declared->foo = 34;//fine
$declared->setFoo($declared->foo*2);//just fine
echo $declared->fo;//TYPO => exception
echo $notDeclared->fo;//no errors show, but echoes nothing: invisible bug?
//Worse, still: 2 mistakes in one go
$notDeclared->fo = 'Typo, meant foo, but assign string to expected integer property';
$declared->fo = 'asd';//throws excpetion at once
//singe $notDeclared->fo didn't throw excpetions, I'm assuming I reassigned $foo, yet
echo $notDeclared->foo;//ecoes old value

Because I'm restricting the usage of __set, by throwing excpetions when the user attempts to assign non-existing properties, any typo will throw an excpetion immediatly. If you don't do so, you might end up having to back-track an instance of your object, in order to spot a single, silly typo, like the example I have shown here with fo

What's more: You have to think about when the magic methods are called:

$instance->newProperty;

What is going on behind the scenes?

  • check object instance for a public property called newProperty
  • check object for method called newProperty (syntax error)
  • check object for __get method
  • invoke __get method

    1. lookup data property ($this->data)
    2. check array for newProperty key (isset)
    3. return result of ternary (ie null)

This means that $instance->newProperty requires PHP to lookup newPropery, then the __get method, then the $data property, then lookup the newPropery key in that array, and then return null, or the value. that's a lot of searching on one object.

That's why I'll always recommend the first option.

compact() vs manual array declaration on PHP

I think it's more a matter of preference.

Uses

If I have a bunch of local variables declared, and I happen to want my array keys to be named the same way, compact is very helpful.

I don't find that to be the case very often though. Typically I'm defining an array that is more complex:

$array = [
'foo' => $something->foo(),
'bar' => $bar,
'baz' => A_CONSTANT
];

To use compact here you'd have to define your variables $foo $bar and $baz first, which seems silly.

I like compact, I just don't find it to be all around helpful most of the time.

Performance

Ok I had to go do it. Here's a very basic non-scientific performance comparison:

https://3v4l.org/WTrOJ

In short, using compact is an order of magnitude slower.

And yet, you have to use it 100,000 (in this example) to matter a tiny fraction of a second.

In other words: use what makes the most sense for your code. Don't worry about the incredibly small performance difference!

In PHP, what is the difference between declaring a variable as global inside function, or passing the variable as an argument to the function?

There are a lot of questions here, I will try to walk through them...

What is the difference between declaring a variable within a function as global or public/private VS passing it to a function as an argument?

global is a type of variable scope. Declaring a variable as global is generally considered bad practice and you should try to avoid it. By passing the variable to a function as an argument, the code is more reusable because you know what the function expects and it isn't relying on some unknown mystery global variable.

public, private, protected are types of visibility used in object oriented programming. These basically determine how properties and methods within a class can be accessed by other classes.

it took me hours to figure out that I needed to pass it into the function as an argument by reference

Something to understand about functions is that unless you pass arguments by reference you are working with a copy of the variable, not the original.

why doesn't it work to pass the variable in as global then edit it and spit it back out with return or simply by doing something like concatenating to the variable array?

You wouldn't need to return a global variable, because you're working with the original value. Please refer again to the link above about scope.

Another example I recently ran into is by making a function for PHPMailer, where I am passing it several arguments, like email-to address and message body, but I also need to pass it authentication strings, like API key, etc.

There are several ways to approach this in addition to using global. If you are planning to use this authentication key in more than one place, the easiest solution would probably be to define a constant, for example:

define('AUTH', 'my_key');
function phpMailer( $mail_to = "to@email.com", $mail_from = "a@b.com" ) {
echo AUTH;
}

But again, the function is now less reusable because it is dependent on that constant. A better solution would probably be to wrap it in an object:

class phpMailer()
{
private $auth = 'my_key';

public function send($mail_to, $mail_from)
{
$this->auth;
}
}
$mail = new phpMailer();
$mail->send('to@email.com', 'a@b.com');

Hopefully this helps. The online PHP documentation found in the links above contain a wealth of information.

Is it necessary to declare PHP array before adding values with []?

If you don't declare a new array, and the data that creates / updates the array fails for any reason, then any future code that tries to use the array will E_FATAL because the array doesn't exist.

For example, foreach() will throw an error if the array was not declared and no values were added to it. However, no errors will occur if the array is simply empty, as would be the case had you declared it.



Related Topics



Leave a reply



Submit