A Laravel package for managing Cranleigh School Diploma tracking — Sixth Form, Intermediate, and Junior diplomas all on shared tables. Diploma types are represented as a PHP backed enum rather than a database table.
- PHP 8.5+
- Laravel 12 or 13
If hosted on a private VCS (e.g. GitHub), add the repository to your main project's composer.json first:
"repositories": [
{
"type": "vcs",
"url": "https://github.com/cranleighschool/diplomas"
}
]Then require it:
composer require cranleighschool/diplomasThe service provider is auto-discovered — no manual registration needed.
php artisan vendor:publish --tag=diplomas-configEdit config/diplomas.php to point at your Pupil model and table if they differ from the defaults:
'pupil_model' => App\Models\Pupil::class,
'pupil_table' => 'pupils',Or via .env:
DIPLOMAS_PUPIL_MODEL=App\Models\Pupil
DIPLOMAS_PUPIL_TABLE=pupils
php artisan migrateTo publish migrations into your project for customisation:
php artisan vendor:publish --tag=diplomas-migrations
php artisan migrateuse CranleighSchool\Diplomas\Traits\HasDiplomas;
class Pupil extends Model
{
use HasDiplomas;
}php artisan db:seed --class="CranleighSchool\Diplomas\Database\Seeders\SixthFormDiplomaSeeder"Or from your DatabaseSeeder:
use CranleighSchool\Diplomas\Database\Seeders\SixthFormDiplomaSeeder;
public function run(): void
{
$this->call(SixthFormDiplomaSeeder::class);
}Diploma types are a PHP backed string enum — no diploma_types table needed.
use CranleighSchool\Diplomas\Enums\DiplomaType;
DiplomaType::SixthForm->value; // 'sixth-form'
DiplomaType::Intermediate->value; // 'intermediate'
DiplomaType::Junior->value; // 'junior'
DiplomaType::SixthForm->label(); // 'Sixth Form Diploma'
DiplomaType::SixthForm->subtitle(); // 'Future Ready – World Ready – Life Ready'
DiplomaType::options();
// ['sixth-form' => 'Sixth Form Diploma', 'intermediate' => 'Intermediate Diploma', ...]use CranleighSchool\Diplomas\Enums\DiplomaType;
$pupil->enrolOnDiploma(DiplomaType::SixthForm);enrolOnDiploma() is idempotent — calling it twice won't create duplicate records or entries.
$diploma = $pupil->sixthFormDiploma; // HasOne shorthand
$diploma = $pupil->diploma(DiplomaType::SixthForm); // Or by enum
$diplomas = $pupil->diplomas; // All enrolments$entry = $diploma->entries()
->whereHas('category', fn($q) => $q->where('name', 'Mock Interview'))
->first();
$entry->markComplete('Completed via careers portal');
// Or mark incomplete
$entry->markIncomplete();Points are recalculated automatically on the parent PupilDiploma.
$diploma->total_points; // int — current earned points
$diploma->progressPercentage(); // float — e.g. 67.3
$diploma->isComplete(); // bool — all required sections satisfied
$diploma->progressBySections(); // Collection — section-by-section breakdownprogressBySections() returns a collection of arrays:
[
[
'section' => DiplomaSection,
'required' => 5,
'completed' => 3,
'section_complete' => false,
'entries' => Collection<PupilDiplomaCategoryEntry>,
],
// ...
]if ($diploma->isComplete()) {
$diploma->award(); // Sets awarded_at to now()
}The DiplomaType enum already includes Intermediate and Junior cases. Just create a new seeder following the same pattern as SixthFormDiplomaSeeder, using the appropriate enum value:
DiplomaSection::create([
'diploma_type' => DiplomaType::Intermediate->value,
'name' => 'Your Section Name',
// ...
]);No schema changes required.
| Table | Purpose |
|---|---|
diploma_sections |
Sections per diploma type (stores enum value as string), with optional required_count |
diploma_categories |
Individual activities/items with points, per section |
pupil_diplomas |
One record per pupil per diploma type — the enrolment anchor |
pupil_diploma_category_entries |
Per-category completion record per pupil |
| Class | Namespace |
|---|---|
DiplomaType |
CranleighSchool\Diplomas\Enums |
DiplomaSection |
CranleighSchool\Diplomas\Models |
DiplomaCategory |
CranleighSchool\Diplomas\Models |
PupilDiploma |
CranleighSchool\Diplomas\Models |
PupilDiplomaCategoryEntry |
CranleighSchool\Diplomas\Models |
HasDiplomas (trait) |
CranleighSchool\Diplomas\Traits |