0

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! :)

1
  • 1
    Well var has not been a property definition used in quite some time. What manual are you using? PHP4 Commented Jun 16, 2017 at 19:22

3 Answers 3

3

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'));
Sign up to request clarification or add additional context in comments.

2 Comments

Glad to help. Since it seems like you are doing some learning exercises, it's understandable that you are putting multiple classes in the same script, but in professional/real world php, you want to always put your classes in seperate scripts, named accordingly. See this standard" php-fig.org/psr/psr-1 Doing so is very important now that php has namespaces and component libraries, and the composer tool that does dependency management and generates an autoloader to be used in your project.
@gview will definitely check the link out, thanks for the advice!
2

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
{

1 Comment

@trincot Also no var is needed in PHP
2
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

3 Comments

Yes, but you'd have to lose the var keyword.
An explanation as to why this answers the question would be helpful. Code-only answers are not really enlightening.
A good answer will always have an explanation of what was done and why it was done that way, not only for the OP but for future visitors to SO that may find this question and be reading your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.