Lesson Weekend

Get All Tasks

Let's write our new getAll() method. Type out this test for Task::getAll() in your test file:

tests/TaskTest.php
function testGetAll()
  {
    //Arrange
    $description = "Wash the dog";
    $description_2 = "Water the lawn";
    $test_task = new Task($description);
    $test_task->save();
    $test_task_2 = new Task($description_2);
    $test_task_2->save();

    //Act
    $result = Task::getAll();

    //Assert
    $this->assertEquals([$test_task, $test_task_2], $result);
  }

Now here is the code to implement it:

src/Task.php
static function getAll()
  {
    $returned_tasks = $GLOBALS['DB']->query("SELECT * FROM tasks;");
    $tasks = array();
    foreach($returned_tasks as $task) {
        $description = $task['description'];
        $new_task = new Task($description);
        array_push($tasks, $new_task);
    }
    return $tasks;
  }

It's worth mentioning at this point that our PDO objects are capable of MUCH more than we have time to integrate in the next couple weeks. The PHP Data Object library of methods is a robust set of functionality meant to interface with databases efficiently and securely. Reading the documentation would be a great idea if you felt like a challenge. For our sake let's look at the documentation for the 'query()' method specifically.

PDO::query()

According to php.net, "PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object."

That's a lot of technical terms. Let's find a definition for one of them...

Take a look at the documentation on PDOStatement objects. This is the data-type of the return value of our PDO::query() calls. After looking through the documentation we see that the value of $returned_tasks isn't a list of objects, or even key value pairs in SQL. What we get back from the PDO::query() method is actually a secure SQL statement with a bunch of other methods. These additional methods are concerned with eliminating the chance of incorrectly representing SQL data and defending against SQL injection.

Now for the cool part. This PDOStatement object KNOWS what a PHP foreach loop looks like, and uses the syntax to traverse our database, accessing the information requested by our SQL statement. Then we can instantiate PHP objects using the returned associative arrays in our foreach loop. With that, we have an array of current Task objects.

Pretty cool huh? Feel free to keep digging into the linked resources above. The more you learn, the more versatile you'll be using PHP and SQL!

Passing our Tests

But if we run our tests again, we'll see that they fail - there are duplicates of all the tasks we've created. This is because we aren't clearing out our database after running each test. Let's update our deleteAll() method, so that we can call it after each test run.

Here is the spec:

tests/TaskTest.php
function testDeleteAll()
  {
    //Arrange
    $description = "Wash the dog";
    $description_2 = "Water the lawn";
    $test_task = new Task($description);
    $test_task->save();
    $test_task_2 = new Task($description_2);
    $test_task_2->save();

    //Act
    Task::deleteAll();

    //Assert
    $result = Task::getAll();
    $this->assertEquals([], $result);
  }

And the code to make it pass:

src/Task.php
static function deleteAll()
  {
    $executed = $GLOBALS['DB']->exec("DELETE FROM tasks;");
    if ($executed) {
       return true;
    } else {
       return false;
    }
  }

Now we can add the following to the top of our TaskTest.php file.

tests/TaskTest.php
class TaskTest extends PHPUnit_Framework_TestCase
  {

      protected function tearDown()
      {
          Task::deleteAll();
      }
...
  }

PHPUnit will automatically run the tearDown() method after each test, clearing the database.