Skip to content

Event MVC Architecture

George Dawoud edited this page Apr 27, 2026 · 1 revision

Event MVC Architecture

ChurchCRM 7.2.0 completed a major refactoring of the Events module, migrating from a collection of legacy procedural PHP pages to a unified Slim 4 MVC architecture. This page explains the architecture for developers working on events or building event-adjacent features.


What Changed in 7.2.0

The Events epic (7.2.0) removed over 2,000 lines of legacy procedural code spread across multiple standalone PHP files and replaced them with:

Before (legacy) After (7.2.0 MVC)
EventEditor.php (standalone) Route handler in v2/routes/events.php
EventAttendance.php Route handler with Propel ORM queries
CheckInOut.php (inline HTML) Twig/PHP template in v2/templates/events/
Raw RunQuery() SQL calls Propel ORM via ChurchEventQuery, EventAttendQuery
Hard-wired Google Maps JS Leaflet.js map integration

Route Structure

Events are registered under the /v2/events prefix in src/v2/routes/events.php:

GET  /v2/events                 → Events dashboard
GET  /v2/events/list            → All events list
GET  /v2/events/add             → New event form
POST /v2/events/add             → Create event
GET  /v2/events/{id}            → Event detail / attendance
POST /v2/events/{id}/attendance → Record attendance
GET  /v2/events/{id}/checkin    → Child check-in page
POST /v2/events/{id}/checkin    → Process check-in
POST /v2/events/{id}/checkout   → Process checkout

Event types are at /v2/event-types:

GET  /v2/event-types            → Type list
GET  /v2/event-types/add        → New type form
POST /v2/event-types/add        → Create type
GET  /v2/event-types/{id}/edit  → Edit type
POST /v2/event-types/{id}/edit  → Update type

ORM Models Used

Model Table Purpose
ChurchEventQuery church_event Event CRUD + queries
EventTypeQuery event_types Event type management
EventAttendQuery event_attend Attendance records
EventCountNameQuery event_count_name Custom attendance count types

All queries use Propel ORM. Never write raw SQL for event data — use the query classes.


Unified Event Editor (7.3.0)

In 7.3.0, all three event entry points (Calendar offcanvas, Events Dashboard quick-add, Event detail page) were unified to render the same form component. If you modify the event form, your change applies everywhere automatically. The component is at:

src/v2/templates/events/event-form-fields.php

It is include-d by the relevant parent templates. Do not duplicate form logic.


Calendar Integration

The Calendar page (/v2/calendar) reads from the same ChurchEvent model. Events appear automatically when created via any entry point. Calendar events are rendered by FullCalendar.js, which fetches events from the API endpoint:

GET /api/events/calendar?start=...&end=...

This endpoint is in src/api/routes/Events.php and returns JSON in the FullCalendar event format.


Child Check-In / Check-Out

Check-in and check-out use the same EventAttend model as attendance, with an additional person_parent_id field linking each check-in row to the parent/guardian who performed pickup. The flow:

  1. Staff opens /v2/events/{id}/checkin
  2. Enters child's PersonID and parent's PersonID
  3. A PersonIDEventAttend row is created with a timestamp and parent link
  4. On checkout, the parent's PersonID is verified before the checkout timestamp is written

Kiosk Integration (7.3.0)

In 7.3.0, kiosk check-in was generalized from Sunday School classes only to any group type. Kiosk devices use a different, stripped-down UI at /kiosk, but the underlying EventAttend data model is identical. A kiosk is linked to a Group, which is linked to an Event — so attendance recorded via kiosk shows up in the same event attendance report.

See Kiosk-Architecture for the kiosk-side implementation notes.


Writing Tests

Cypress tests for Events are in cypress/e2e/ui/events.cy.js and cypress/e2e/api/events.cy.js. When adding new event functionality:

  1. Add an API test for any new endpoint in cypress/e2e/api/
  2. Add a UI test for user-visible flows in cypress/e2e/ui/
  3. Run npm run docker:test:start && npm run test:api to validate

Related Pages

🚀 Getting Started

docs.churchcrm.io for installation & setup


👥 For End Users

docs.churchcrm.io for user manuals


🔧 For Administrators

docs.churchcrm.io for admin manuals


👨‍💻 For Developers

Contributing to ChurchCRM


📚 Help & Reference

Clone this wiki locally