Open Menu

Bundled Checks#^ TOP

This article documents each of the checks bundled with the workshop framework and how to use them. Remember the exercise types from the Exercise Types documentation? CLI, CGI & CUSTOM?

Well, checks can support one or more of these exercise types types. So inspect the table below to see if the check you want to use actually supports your exercise type.

Bundled Checks
  • PhpSchool\PhpWorkshop\Check\FileExistsCheck

    Interface to implement:
    PhpSchool\PhpWorkshop\Exercise\ExerciseInterface
    Type:
    Simple
    Compatible Exercise Types:
    CLI, CGI
    This check verifies that the student's solution file actually exists. This check is always registered as the first check and verifying will abort if it fails.

    Note: You do not need to require this check yourself, it is done so automatically.

  • PhpSchool\PhpWorkshop\Check\CodeParseCheck

    Interface to implement:
    PhpSchool\PhpWorkshop\Exercise\ExerciseInterface
    Type:
    Simple
    Compatible Exercise Types:
    CLI, CGI
    This check verifies that the student's solution file can actually be parsed. Parsing is done with nikic/php-parser.

    Note: You do not need to require this check yourself, it is done so automatically.

  • PhpSchool\PhpWorkshop\Check\PhpLintCheck

    Interface to implement:
    PhpSchool\PhpWorkshop\Exercise\ExerciseInterface
    Type:
    Simple
    Compatible Exercise Types:
    CLI, CGI
    This check verifies that the student's solution file contains valid PHP syntax. This is as simple as php -l <submission-file>.

    Note: You do not need to require this check yourself, it is done so automatically.

  • PhpSchool\PhpWorkshop\Check\FunctionRequirementsCheck

    Interface to implement:
    PhpSchool\PhpWorkshop\ExerciseCheck\FunctionRequirementsExerciseCheck
    Type:
    Simple
    Compatible Exercise Types:
    CLI, CGI
    This check verifies that the students submission contains usages of some required functions and also does not use certain functions. This check is useful if you want to ban a certain way of achieving something, for example, teaching how to manually write a function that already existing in the standard library.

    Learn how to use

  • PhpSchool\PhpWorkshop\Check\ComposerCheck

    Interface to implement:
    PhpSchool\PhpWorkshop\ExerciseCheck\ComposerExerciseCheck
    Type:
    Simple
    Compatible Exercise Types:
    CLI, CGI
    This check verifies that the student used Composer to install the required dependencies of the exercise. It checks that a composer.lock files exists and contains entries for the required packages.

    Learn how to use

  • PhpSchool\PhpWorkshop\Check\DatabaseCheck

    Interface to implement:
    PhpSchool\PhpWorkshop\ExerciseCheck\DatabaseExerciseCheck
    Type:
    Listener
    Compatible Exercise Types:
    CLI, CGI
    This check sets up a database and a PDO object. It prepends the database DSN as a CLI argument to the student's solution so they can connect to the database. The PDO object is passed to the exercise before and after the student's solution has been executed, allowing you to first seed the database and then verify the contents of the database.

    Learn how to use

Functional Requirements Check#^ TOP

Here is an example of how to force the student to use the function curl_exec and ban the usage of file_get_contents. This could be useful if you wanted to teach advanced configuration of data transfers.

class MyExercise extends AbstractExercise
        implements ExerciseInterface, FunctionRequirementsExerciseCheck
{
    ...snip

    /**
     * @param ExerciseDispatcher $dispatcher
     */
    public function configure(ExerciseDispatcher $dispatcher)
    {
        $dispatcher->requireCheck(FunctionRequirementsCheck::class);
    }

    /**
     * @return string[]
     */
    public function getRequiredFunctions()
    {
        return ['curl_exec'];
    }

    /**
     * @return string[]
     */
    public function getBannedFunctions()
    {
        return ['file_get_contents'];
    }
}

If a student submitted something like:

<?php

echo file_get_contents('http://example.com');

The output would be something along the lines of:

Composer Check#^ TOP

Here is an example of how to force the student to require the nikic/fast-route package via Composer. This is useful if you want to focus on a specific problem or promote popular/battle tested packages.

class MyExercise extends AbstractExercise
        implements ExerciseInterface, ComposerExerciseCheck
{
    ...snip

    /**
     * @param ExerciseDispatcher $dispatcher
     */
    public function configure(ExerciseDispatcher $dispatcher)
    {
        $dispatcher->requireCheck(ComposerCheck::class);
    }

    /**
     * @return array
     */
    public function getRequiredPackages()
    {
        return [
            'nikic/fast-route'
        ];
    }
}

A number of failures can occur here, the student may not even have a composer.json or a composer.lock file. If this is the case, the check will fail and a message will be printed. If the required files are present, but the package has not been found, the output will look like the following:

Database Check#^ TOP

Here is an example where we require that the student insert a record in to the users table which we will create in the seed method of our check. We will then verify that there are some records in the users table.

class MyExercise extends AbstractExercise
        implements ExerciseInterface, DatabaseExerciseCheck
{
    ...snip

    /**
     * @param ExerciseDispatcher $dispatcher
     */
    public function configure(ExerciseDispatcher $dispatcher)
    {
        $dispatcher->requireCheck(DatabaseCheck::class);
    }

    /**
     * @param PDO $db
     * @return void
     */
    public function seed(PDO $db)
    {
        $db->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER, gender TEXT)');
    }

    /**
     * @param PDO $db
     * @return bool
     */
    public function verify(PDO $db)
    {
        return $db->query('select COUNT(*) from users')->fetchColumn() > 0;
    }
}

If the student did not insert into the database, for example, if they submitted the following:

<?php

echo "Where is the database?";

Then they would receive the following failure:

If they submitted a proper solution, like the following:

<?php

$dsn = $argv[1];
$db = new PDO($dsn);
$stmt = $db->prepare('INSERT INTO users (name, age, gender) VALUES (:name, :age, :gender)');
$stmt->execute([':name' => 'Karl Renner', ':age' => 80, ':gender' => 'Male']);

They would receive this success: