Reputation: 3
Currently I'm working on a simple OOP script in PHP, it needs to compare the ID and the DATE of the array and sort them in the right order.
I was wondering why my constructor in the first class doesn't pass the $elements array properly.
The error I'm getting:
Notice: Undefined variable: elements in /Applications/XAMPP/xamppfiles/htdocs/strategy-pattern-.php on line 58
Catchable fatal error: Argument 1 passed to ObjectCollection::__construct() must be of the type array, null given, called in ... on line 58 and defined in ... on line 12
Code:
<?php
class ObjectCollection
{
var $elements = array(
array('id' => 2, 'date' => '2017-01-01',),
array('id' => 1, 'date' => '2017-02-01'));
var $comparator;
function __construct(array $elements)
{
$this->elements = $elements;
}
function sort()
{
if (!$this->comparator) {
throw new \LogicException('Comparator is not set');
}
uasort($this->elements, [$this->comparator, 'compare']);
return $this->elements;
}
function setComparator(ComparatorInterface $comparator)
{
$this->comparator = $comparator;
}
}
interface ComparatorInterface
{
function compare($a, $b);
}
class DateComparator implements ComparatorInterface
{
function compare($a, $b)
{
$aDate = new \DateTime($a['date']);
$bDate = new \DateTime($b['date']);
return $aDate <> $bDate;
}
}
class IdComparator implements ComparatorInterface
{
function compare($a, $b)
{
return $a['id'] <> $b['id'];
}
}
$collection = new ObjectCollection($elements);
$collection->setComparator(new IdComparator());
$collection->sort();
echo "Sorted by ID:\n <br>";
print_r($collection->elements);
$collection->setComparator(new DateComparator());
$collection->sort();
echo "<br>Sorted by date:\n <br>";
print_r($collection->elements);
?>
I know there may just be a rookie mistake somewhere but I'm really curious what I'm doing wrong haha.
Thanks in advance! :)
Upvotes: 0
Views: 103
Reputation: 15361
At the bottom of your script you have:
$collection = new ObjectCollection($elements);
However, the $elements
variable is not defined. This is why you are getting the error.
The specific error is related to the fact that you used a type declaration in your class constructor requiring that an 'array' be passed. Prior to the addition of type declarations to php, the php runtime engine did not care what variables you passed, so long as you passed a number of variables equal to the number of required parameters to a function or method.
As also pointed out in another answer, many of us are assuming that your placement of the --
var $elements = array(
array('id' => 2, 'date' => '2017-01-01',),
array('id' => 1, 'date' => '2017-02-01'));
was never meant to be inside the class. With that said, doing so creates and initializes the $elements class variable, which is a valid technique that has many uses in OOP. However, the syntax used is obsolete, and if you really did want to initialize a class variable to a set value at object creation time, you should be using the syntax that includes a variable visibility keyword like:
protected $elements = array(
array('id' => 2, 'date' => '2017-01-01',),
array('id' => 1, 'date' => '2017-02-01'));
In conclusion, the answer to your question is that either you should define $collection to be an array at the bottom of the script, or pass an array in when you create the ObjectCollection
object.
$collection = new ObjectCollection(array(
array('id' => 2, 'date' => '2017-01-01'),
array('id' => 1, 'date' => '2017-02-01'));
Upvotes: 3
Reputation: 17906
class ObjectCollection
{
// define as property
private $elements;
private $comparator;
function __construct(array $elements)
{
$this->elements = $elements;
}
function sort()
{
if (!$this->comparator) {
throw new \LogicException('Comparator is not set');
}
uasort($this->elements, [$this->comparator, 'compare']);
return $this->elements;
}
function setComparator(ComparatorInterface $comparator)
{
$this->comparator = $comparator;
}
}
...
// you need to define $elements to pass
$elements = array(
array('id' => 2, 'date' => '2017-01-01',),
array('id' => 1, 'date' => '2017-02-01'));
// them to the constructor
$collection = new ObjectCollection($elements);
// the way you did it, your $elements definition was in class scope so you got the error they are "NULL" / Not defined
Upvotes: 2
Reputation: 7743
You have declared the elements
variable inside the class instead outside
$elements = array(
array('id' => 2, 'date' => '2017-01-01',),
array('id' => 1, 'date' => '2017-02-01'));
class ObjectCollection
{
Upvotes: 2