Ready for the next step?
Use the PHP School workshop documentation to build you own workshop and help teach others PHP!
Open Menu
After a student's solution has been verified, the result set is rendered to the console. The result set is made up of several individual results. Verification is deemed to have failed if any one of those results is a failure. Each result represents a different thing, for example, each check will likely inject a result in to the result set. The output verification will be a single result, the parsing of the file will be a single result, and so on.
Each Result class has an associated renderer, the renderers job is to take the information from the result and render in to the console.
Results are what Exercise Checks should return and inject. You will learn more about how to actually use the results in your checks in a later article.
The result set is an instance of PhpSchool\PhpWorkshop\ResultAggregator
and results are added to it
with add(ResultInterface $result)
. Note the interface
PhpSchool\PhpWorkshop\Result\ResultInterface
. Every result must implement this interface.
So, how do we know if a result is a success or failure? Well there are two other interfaces, extending from
ResultInterface
, which are:
PhpSchool\PhpWorkshop\Result\SuccessInterface
PhpSchool\PhpWorkshop\Result\FailureInterface
Both of these interfaces add no extra methods, they are purely for determining whether a result is considered a success or failure.
The interface for ResultInterface
is very simple:
<?php
interface ResultInterface
{
/**
* @return string
*/
public function getCheckName();
}
This method should just return the name of the check associated with this result. This is used when rendering the result to the console.
There are default implementations for SuccessInterface
& FailureInterface
for you to use
in your checks. If you need something more bespoke to render the failure of your check, you should
create your own.
As you saw from the interface, the only required piece of information is the check name. So construction would look like the following.
<?php
use PhpSchool\PhpWorkshop\Result\Success;
$success = new Success('My Check');
If you are within a Check (eg $this
refers to PhpSchool\PhpWorkshop\Check\CheckInterface
)
then you can use the static constructor fromCheck(CheckInterface $check)
which just pulls the check
name from the actual check for convenience.
<?php
namespace PhpSchool\PhpWorkshop\Check;
use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface;
use PhpSchool\PhpWorkshop\Result\Success;
class MyCheck implements SimpleCheckInterface
{
...snip
public function check(ExerciseInterface $exercise, $fileName)
{
return Success::fromCheck($this);
}
}
The default implementation of FailureInterface
needs one more piece of information
other than the check name: the reason for the failure. Construction is fairly similar:
<?php
use PhpSchool\PhpWorkshop\Result\Failure;
//constructor
$failure = new Failure('My Check', 'Something went wrong!');
//static constructor
$failure = Failure::fromNameAndReason('My Check', 'Something went wrong!');
//static constructor with check
$myCheck = new MyCheck;
$failure = Failure::fromCheckAndReason($check, 'Something went wrong!');
There are a number of FailureInterface
implementations bundled with the framework
for some of the other checks:
PhpSchool\PhpWorkshop\Result\Cgi\GenericFailure
PhpSchool\PhpWorkshop\Result\Cgi\RequestFailure
PhpSchool\PhpWorkshop\Result\Cli\GenericFailure
PhpSchool\PhpWorkshop\Result\Cli\RequestFailure
PhpSchool\PhpWorkshop\Result\FunctionRequirementsFailure
PhpSchool\PhpWorkshop\Result\ComparisonFailure
When you want to report information that is not simple a message, you will need to create your own result class. If you would build a check that verifies the contents of a database, you may want to provide a list of missing records as an array instead of just a message. You would then write a renderer that may render each row as a new line with a bullet point preceding it. Learn how to create your own checks in a later article.
Each result renderer must implement the interface PhpSchool\PhpWorkshop\ResultRenderer\ResultRendererInterface
which looks like
below.
<?php
namespace PhpSchool\PhpWorkshop\ResultRenderer;
use PhpSchool\PhpWorkshop\Result\ResultInterface;
interface ResultRendererInterface
{
/**
* @param ResultsRenderer $renderer
* @return string
*/
public function render(ResultsRenderer $renderer);
}
PhpSchool\PhpWorkshop\ResultAggregator
is rendered by PhpSchool\PhpWorkshop\ResultRenderer\ResultsRenderer
. It loops each
result, passing the result to PhpSchool\PhpWorkshop\Factory\ResultRendererFactory
which returns the correct renderer. The
render
method is called and then the output of each is written to the console.
When each renderer is created, it is passed the ResultInterface
as the first constructor
argument. render
is called with an instance of PhpSchool\PhpWorkshop\ResultRenderer\ResultsRenderer
and
it should return a string representation of the ResultInterface
instance it was constructed with.
PhpSchool\PhpWorkshop\ResultRenderer\ResultsRenderer
has some helper methods on it for rendering
styling:
style($string, $colourOrStyle)
- Use to style a string, eg. bold
, green
. It accepts an array of styles or one style as a stringlineBreak()
- Use to render a line break, to separate content.center()
- Pad a string according to the terminal width so it displays in the centerThe workshop framework picks a result renderer based on the mappings in PhpSchool\PhpWorkshop\Factory\ResultRendererFactory
.
The default mappings are:
Result Class | Result Renderer Class |
PhpSchool\PhpWorkshop\Result\Cgi\GenericFailure |
PhpSchool\PhpWorkshop\ResultRenderer\FailureRenderer |
PhpSchool\PhpWorkshop\Result\Cgi\RequestFailure |
PhpSchool\PhpWorkshop\ResultRenderer\Cgi\RequestFailureRenderer |
PhpSchool\PhpWorkshop\Result\Cli\GenericFailure |
PhpSchool\PhpWorkshop\ResultRenderer\FailureRenderer |
PhpSchool\PhpWorkshop\Result\Cli\RequestFailure |
PhpSchool\PhpWorkshop\ResultRenderer\Cli\RequestFailureRenderer |
PhpSchool\PhpWorkshop\Result\ComparisonFailure |
PhpSchool\PhpWorkshop\ResultRenderer\ComparisonFailureRenderer |
PhpSchool\PhpWorkshop\Result\FunctionRequirementsFailure |
PhpSchool\PhpWorkshop\ResultRenderer\FunctionRequirementsFailureRenderer |
PhpSchool\PhpWorkshop\Result\Failure |
PhpSchool\PhpWorkshop\ResultRenderer\FailureRenderer |
If you create a new implementation of FailureInterface
you will need to map it to an existing renderer,
or most likely you will need to write a custom renderer, and map it to that.
The whole process may sound complicated, however, this is not true. To summarise, your check should return a result. The result should be mapped to a renderer. The results are rendered by the framework. It will pick the correct renderer based on the mapping.
In the next set of articles we will learn about and build a check. Once the check is complete, we will build a custom result and result renderer for it, you can jump straight there if you want.