Spond holds the club's player, event and reply data. Squad Manager brings that data together with skill reviews and match-day plans. Coaches can build a squad for one match without changing each player's long-term record.
Reviewed 1 October 2026. Based on source revision 6c759212ae1bbc9ba8871d87889ab287a1cd0bae. This review checks the code, not the live host or its database.
The old workflow needed staff to add players and fixtures by hand. For the connected Wirral U12 group, those records now come from Spond. A scheduled job creates or updates the local records. Staff keep their coaching work in Squad Manager.
| Area | How it works now | Benefit |
|---|---|---|
| Players | The sync links Spond members to local players. | Less retyping and fewer name errors. |
| Fixtures and sessions | Spond supplies titles, dates, times and venue details. | One place to make event changes. |
| Player replies | Spond replies become local availability states. | Coaches can plan from the latest saved replies. |
| Coach replies | Linked Spond organisers supply coach responses. | The sheet shows who has confirmed. |
| Match-day choices | A separate record holds each player's team and position for one session. | Late changes leave normal teams and positions intact. |
| Team sheets | The browser builds an A4 PDF from the saved sheet. | A clear plan to print or share. |
These changes apply to Spond-connected records. Legacy records and groups without an active connection can still follow a different path.
The site uses PHP for server code, MySQL through PDO for storage, and JavaScript for charts and PDF exports. PHP cURL calls Spond over HTTPS. The job runs through PHP on the host. It does not run the Python Olen/Spond package. That project is a reference for the Spond API approach.
cron/spond-sync.php.The client makes a login request to obtain a token. Its group and event requests read data. The reviewed code has no path that sends player edits, fixture edits or match-day plans back to Spond.
| Data | Source | What a sync does |
|---|---|---|
| Player name | Spond | Refreshes the linked player's name. |
| Player status | Import logic | Sets imported players to active. Absence from the import does not disable them. |
| Event title, date, time and venue | Spond | Refreshes supported fields. |
| Player availability | Spond replies | Replaces local status for each returned, linked response. |
| Normal and transition team, usual position, player notes | Squad Manager | Leaves these fields in place. |
| Skill reviews and scores | Squad Manager | Leaves these records in place. |
| Session type, coaching notes and result | Squad Manager | Leaves these fields in place. |
| Match-day team and position | Squad Manager | Leaves choices in place while the session exists. |
The setup guide calls for an hourly PHP cron job on Hostinger. The code does not set that schedule itself. I don't know the live cron times from the repository. The job rejects web requests and runs only through the command line.
The local config selects one age group, a Spond group and an optional subgroup. The current job uses one configured connection per run. It does not loop through all clubs. It requests events from 1 September to a timestamp at the start of 31 May for the current season, with a limit of 500. There is no paging loop in the reviewed client.
With a subgroup set, the roster comes from invitation-response IDs on upcoming events. If those IDs are absent, the code tries direct subgroup membership. This is an event-based view of the roster, so it may not list every member of the club.
| Tables | Purpose |
|---|---|
spond_connections, spond_sync_log | Connection scope, last sync, errors and run counts. |
spond_members, spond_events, spond_event_responses | Local Spond records, stable IDs and source payloads. |
spond_player_links, spond_session_links | Links between imported data and existing site records. |
spond_group_people, spond_coach_links, spond_coach_event_responses | A separate directory, coach links and coach replies. |
players, schedule_sessions, schedule_availability | Records used by the site after core import. |
schedule_assignments | One-session team and position choices. |
The first phase used separate Spond tables. The current core import also writes to the main player and schedule tables when SPOND_CORE_IMPORT_ENABLED is true. The split still helps keep source data and coaching choices apart.
For a player, the sync first checks a saved Spond ID link. If none exists, it searches for an exact first and last name in the same age group. It reuses the record only if there is one match. Otherwise it creates a new active player with no position or notes. The saved ID link then supports later name changes.
For an event, the sync first checks the saved event link. If none exists, it looks for one local session with the same age group, local date and cleaned title. If it cannot find one clear match, it creates a session. New sessions start as Event. The Head Coach must choose Match, Training or Festival where needed.
Names and titles are used only for the first match. They are not unique IDs. A renamed or duplicate record can need a link review.
Source event timestamps are stored in UTC. Session dates and times are converted to Europe/London. The Team Sheet also reads Spond's meet-up time from the saved event payload.
For a Match, explicit Spond home or away data takes priority. Otherwise, configured venue text or postcode matches set Home. A non-matching venue sets Away for a Match and Other for other types. A blank venue sets Other. Check this after setting the session type and allowing the next sync to run.
| Spond reply | Local player state |
|---|---|
| Accepted | Available |
| Declined | Unavailable |
| Unanswered, unconfirmed or waiting list | Awaiting |
Coach replies come from the event's organiser list. The client tries the parent-group event view to fill in organiser data missing from the subgroup view. Existing coach accounts are linked by a normalised full name or through the Map Spond coaches page. The sync does not create coach accounts.
The main data writes run in a database transaction. If a required step fails, those writes roll back. The connection and log record the error. The job exits with code 1. A successful run records counts and the last sync time.
Some coach features are optional and catch their own errors. A successful player sync does not prove coach replies are complete.
The job also removes stored events no longer returned by Spond. It deletes linked imported sessions only when created_by is null. Their availability and match-day assignments are deleted too. Manually created sessions are kept.
This cleanup trusts the returned event list. The client does not prove that the list is complete or page beyond 500. A narrower scope or incomplete response can therefore affect cleanup. A player missing from the roster is kept and needs a membership review.
The Head Coach opens a session through Update Sheet. They can set its type, notes and result, then choose availability, a match-day team and a match-day position. Spond-owned fixture fields are kept from the saved record even if a form request tries to change them.
The key for schedule_assignments is the pair session_id and player_id. A choice therefore belongs to one player at one session. Saving it does not update players.team_id or players.position.
For example, a player can keep their normal team and usual scrum-half role, then play in another team at centre this Sunday. The one-match choice appears on Sunday's sheet. Their normal player record stays in place for future plans.
The edit form starts with the normal team, then the transition team if no normal team exists. The display sheet uses a saved match-day team first, then a transition team, then the normal team. This fallback order differs between the two pages. Save an explicit match-day choice where the player has a transition team.
The sheet includes only players marked Available. Position display uses the saved match-day position or the usual position. A blank choice falls back to the usual data. It does not force a blank printed position. Saving a player as Awaiting or Unavailable clears their match-day choices. A later Spond sync changes availability without clearing those choices.
The balance indicator compares player counts by team. It does not measure skill balance or pick the teams for you. Position options come from the usual positions already held by active players in that age group.
The sheet label changes from Draft to Final at 20:00 on the day before the session, using UK local time. This is a time-based label. The reviewed save code still allows later edits. It is not a lock or a record of coach approval.
The server prepares the report data when the sheet opens. The browser uses the bundled pdfmake library and Roboto fonts to build an A4 PDF. It includes the date, meet time, kick-off time, location, confirmed coaches, suggested format, notes and available players grouped by team.
Open the saved PDF to print it. It is a snapshot of the page data. Refresh the page and download a new copy after a sync or planning change. A downloaded copy does not update on its own.
The format suggestion uses fixed player-count rules. It does not track each player's minutes or prove that a plan meets the RFU rules.
Coaches still record dated skill scores and notes in Squad Manager. The assessment form can start with earlier scores. A save creates a new record. The form stores a category score against its linked subcategories so the position-weight tools can use it.
Skill charts, the squad heatmap and small-group tools help coaches spot needs and plan drills. These records stay separate from Spond replies and one-match choices.
The stats page uses Spond accepted replies to calculate rates and trends. Those figures show confirmed replies. They do not prove that a player attended or played on the day. Training Analysis shows Spond training turnout by date and a player's current team. It can group by season, the last eight weeks or the last four weeks.
| Role | Current purpose |
|---|---|
Platform administrator, stored as god | Platform setup and the read-only Spond diagnostic. Schedule pages explicitly reject this role. |
Head Coach, stored as head_coach | Club coaching access, coach management and session planning. Active age-group access still needs a saved assignment. |
| Coach | Views sheets and works with player coaching data in assigned age groups. Cannot update session planning. |
Login checks an active coach account and a hashed password. PHP sessions hold the signed-in user and current age group. The age-group guard checks a saved coach assignment and an active group. The platform role is not a blanket bypass for these pages.
Spond-managed field protection relies on the connection being Active. A failed sync marks it Error. The current checks may then treat linked records as unmanaged until the next successful run. Keep edits to source fields in Spond during that gap.
These are expected benefits of the design. The code review does not measure time saved or prove live data quality. The value depends on clear Spond replies, sound links and a working cron job.
A host needs PHP with cURL, PDO MySQL, sessions and cron support. JavaScript is needed for PDF exports and charts. Set up HTTPS and outbound email for account invites and resets. The repository has dated migrations, but this review has not proved a complete fresh install from those files alone.
Keep Spond settings in includes/spond.config.local.php. The required keys cover the login, group, subgroup and local age-group ID. Core import is a separate switch. Home venue matches are optional. See the server setup notes for the key list and migrations. The client does not implement a two-factor login flow.
| Issue | First checks |
|---|---|
| Missing player | Age group, filters, upcoming subgroup invitations and player links. |
| Missing event | Group scope, season window, the 500-event limit, event link and cron output. |
| Wrong reply | Spond reply, last successful sync and whether a local edit was later replaced. |
| Missing coach reply | Coach mapping, organiser list, parent-group fetch and optional tables. |
| Wrong time or venue | Source event, UK time conversion, schema fields, type and home venue matches. |
| Old PDF | Refresh the sheet and create a new PDF. |
| Failed sync | Local config, login, PHP cURL, schema, connection error and sync log. |
Player exports and raw Spond payloads hold personal data. Limit access and use the club's approved sharing routes. Keep secrets out of Git and review backup and retention settings. The existing setup notes flag the tracked database config for a separate planned fix.
This document verifies the code paths listed below. I don't know the live host's cron settings, applied migrations, config values, backups or latest successful run without checking that host.
These files support the behaviour described here. The older Phase 1 title does not mean the current job writes only to separate tables.
cron/spond-sync.php: CLI entry point, output and failure exit.includes/spond.php: config, HTTPS client, login, event scope and roster selection.includes/spond_sync.php: matching, import, reply mapping, transaction, logs and cleanup.includes/spond_management.php: active-connection checks for managed records.includes/schedule.php: schema, queries, access helper, format and Draft/Final label.schedule/edit.php: Head Coach form and session-specific saves.schedule/sheet.php: available players, coach replies, fallbacks and PDF data.assets/js/schedule-pdf.js: A4 PDF build and download.includes/auth.php: login, roles and age-group access.assessments/add.php, includes/functions.php: skill records and position weights.tools/stats.php: reply-based trends and the Training Analysis summary link.tools/training-analysis.php: period-filtered training turnout by date and current team.sql/2026-09-30-*.sql: schema changes for schedule and Spond features.Coach Guide · Administrator Runbook · Olen/Spond reference project