haer.
haer.

Reputation: 3

How do I properly construct an array within a class in PHP?

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

Answers (3)

gview
gview

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

john Smith
john Smith

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

MaxZoom
MaxZoom

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

Related Questions