PHPackages                             fcosrno/exam-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. fcosrno/exam-php

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

fcosrno/exam-php
================

PHP library to create, display, and grade exams.

v1.0.0(11y ago)387507[3 issues](https://github.com/fcosrno/exam-php/issues)MITPHP

Since Sep 10Pushed 11y ago5 watchersCompare

[ Source](https://github.com/fcosrno/exam-php)[ Packagist](https://packagist.org/packages/fcosrno/exam-php)[ RSS](/packages/fcosrno-exam-php/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (0)

Exam
====

[](#exam)

PHP library to create, display, and grade exams.

Bonus: you can use it to generate surveys (just ignore the grading feature).

[![Build Status](https://camo.githubusercontent.com/f030d5f381526764038373229b9d18cc15944641b82bb8b226d6409d32fc6319/68747470733a2f2f7472617669732d63692e6f72672f66636f73726e6f2f6578616d2d7068702e737667)](https://travis-ci.org/fcosrno/exam-php) [![Latest Stable Version](https://camo.githubusercontent.com/b594f2bf51949a3523372a5ef68925225f0d2352e6fe85451c9270af3ced5dcf/68747470733a2f2f706f7365722e707567782e6f72672f66636f73726e6f2f6578616d2d7068702f762f737461626c652e737667)](https://packagist.org/packages/fcosrno/exam-php)

Setup
-----

[](#setup)

```
composer require fcosrno/exam-php

```

Quick Usage
-----------

[](#quick-usage)

```
// Create instance of exam
$exam = new Exam();

// Add your questions
$exam->ask('Is the sky blue?')->setChoices('Always','Never','Sometimes')->setAnswer('Sometimes');
$exam->ask('Select things you may see at nighttime')->setSelections('Stars','Sun','Moon')->setAnswer('Stars','Moon');
$exam->ask('Is this a question?')->truefalse('true');

// Generate the HTML form (optional)
$view = $exam->generateHtml();

// Grade the exam
$myAnswers = array_values($_POST);
$percent = $exam->grade($myAnswers); // returns percent

```

Adding questions
----------------

[](#adding-questions)

You can create a question by asking it.

```
$exam->ask('Is the sky blue?');

```

However, asking a question won't work by itself. Exam needs to know the question's choices or selections. You do this by method chaining `setChoices()` or `setSelections()` to the question.

In this example we want a multiple choice question so we'll use `setChoices()`.

```
$exam->ask('Is the sky blue?')->setChoices('Always','Never','Sometimes');

```

If you're going to be grading this exam, then you also need to define an answer.

```
$exam->ask('Is the sky blue?')->setChoices('Always','Never','Sometimes')->setAnswer('Sometimes');

```

Now our multiple choice question is defined. Let's render it as a form input so we can send it to the browser and ask it to the user.

```
echo $exam->generateHtml();

```

Our multiple choice question will be rendered as an HTML form input using radios.

```
Is the sky blue?

		Always

	Never

	Sometimes

```

### Question types

[](#question-types)

This library allows two types of questions: **multiple choice** and **select all that apply**. There is also a third type, **true or false**, which is really just a handy shortcut for a multiple choice with two options: True or False. Other types of questions are being considered but have yet to be built if requested by the community.

The question type is defined for you depending on what method you use when asking the question. For example, if you use `setChoices()` the question type will be "multiple choice", but if you use `setSelections()` the question type will be "select all that apply". You can always override this by using the `setType()` property (only useful for debugging).

#### Multiple choice (Radios)

[](#multiple-choice-radios)

Multiple choice (radios) uses `setChoices()` and is type `multiple`. This will probably be the most common type of question.

```
// Quickest way (recommended)
$exam->ask('Is the sky blue?')->setChoices('Always','Never','Sometimes')->setAnswer('Sometimes');

// Fallback with type defined (redundant, yet consistent)
$exam->ask('Is the sky blue?')->setType('multiple')->setChoices('Always','Never','Sometimes')->setAnswer('Sometimes');

```

#### Select all that apply (Checkboxes)

[](#select-all-that-apply-checkboxes)

Select all that apply (checkboxes) uses `setSelections()` and is type `select`.

```
// Quickest way (recommended)
$exam->ask('Select things you may see at nighttime')->setSelections('Stars','Sun','Moon')->setAnswer('Stars','Moon');

// Fallback with type defined (redundant, yet consistent)
$exam->ask('Select things you may see at nighttime')->setChoices('Stars','Sun','Moon')->setType('select')->setAnswer('Stars','Moon');

```

Notice the order of the answers do not have to match the order of the options.

#### True or false (Radios)

[](#true-or-false-radios)

This is a helpful wrapper for a multiple choice with only true or false as the options.

```
// You can do this (recommended)
$exam->ask('Is this a question?')->truefalse('true');

// Which is the same as this (a little more typing)
$exam->ask('Is this a question?')->truefalse()->setAnswer('True');

// Which is also the same as this (long way, but works)
$exam->ask('Is this a question?')->setChoices('True','False')->setAnswer('True');

```

#### Other

[](#other)

Other types of questions are being considered but have yet to be built if requested by the community. These are some ideas for other types of questions:

- Matching would be type `match`.
- Text (input) would have to validate exactly as the answer, with casing options considered.

Grading the exam
----------------

[](#grading-the-exam)

To grade the exam, pass the user's answers to the `grade()` method. It is important that you pass the same number of answers as there are questions, otherwise Exam will balk. If the user left an answer blank, make sure your POST process defines it as an empty string.

```
$exam->grade($answers);

```

This will return the grade as a percent string, ie "75%". However, you can also get the grade as a decimal, fraction or percentage.

```
// this will return a decimal, ie 0.66666666666666663 (numeric)
$exam->grade($answers)->asDecimal();

// this will return a fraction, ie 2 / 3 (string)
$exam->grade($answers)->asFraction();

// this will return a percentage, ie 75 (integer)
$exam->grade($answers)->asPercentage();

```

**A quick note on Percentage vs Percent**

The word percent (or the symbol %) accompanies a specific number, whereas the more general word percentage is used without a number. By default, the grade function returns a percent string, but you can request the percentage instead.

```
// this will return percent, ie "75%" (string)
$exam->grade($answers);

// this will return percentage, ie 75 (integer)
$exam->grade($answers)->asPercentage();

```

Working example
---------------

[](#working-example)

There is a working example in *./doc/example.php* that allows you take an exam and shows you the results after submitting your answers.

Testing
-------

[](#testing)

Tests are built with PHPUnit.

Make sure you install with dev requirements.

```
composer install

```

Go to the root of the project then run all tests by typing in the terminal:

```
phpunit --bootstrap vendor/autoload.php tests/

```

With coverage report:

```
phpunit --coverage-html ./tests/report --bootstrap vendor/autoload.php tests/

```

Last test run with with PHPUnit 4.1.4.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity27

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

4269d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/bd49761575d11cdd4ec59918d312e20fcb3666f6c58c4609c9507963ee82febb?d=identicon)[fcosrno](/maintainers/fcosrno)

---

Top Contributors

[![fcosrno](https://avatars.githubusercontent.com/u/583992?v=4)](https://github.com/fcosrno "fcosrno (8 commits)")

---

Tags

surveyEvaluationexamquestionnaireGradingAssessment

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/fcosrno-exam-php/health.svg)

```
[![Health](https://phpackages.com/badges/fcosrno-exam-php/health.svg)](https://phpackages.com/packages/fcosrno-exam-php)
```

###  Alternatives

[matt-daneshvar/laravel-survey

Create surveys inside your Laravel app

28770.3k](/packages/matt-daneshvar-laravel-survey)[tapp/filament-survey

Filament Laravel Survey plugin.

3119.2k](/packages/tapp-filament-survey)[codefog/contao-polls

polls extension for Contao Open Source CMS

152.6k](/packages/codefog-contao-polls)[tapp/filament-form-builder

User facing form builder using Filament components

131.2k1](/packages/tapp-filament-form-builder)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
