Scenario 1: The "Slow Report" Problem
Question: A client complains that a custom report plugin you built times out when run for the entire university (50,000 students). It works fine for small courses. How do you fix it?
Analysis: The script is likely hitting PHP's max_execution_time or memory limit due to loading all records at once.
Solution:
- Use RecordSets: Replace
$DB->get_records()with$DB->get_recordset()to iterate row-by-row instead of loading everything into RAM. - Ad-hoc Task: Move the generation to a background Ad-hoc task. The user clicks "Generate", and receives a notification when it's ready.
- Pagination: If it must be on-screen, implement pagination using Moodle's
table_sqlclass. - Read Replica: If the query is complex, direct it to the read-only database replica.
Scenario 2: External System Integration
Question: The university wants to automatically enrol students into Moodle courses based on data from their SIS (Student Information System). The SIS exposes a REST API. How do you design this?
Design:
- Plugin Type: Create an
enrolplugin (e.g.,enrol_sis) or alocalplugin with a scheduled task. - Synchronization: Use a Scheduled Task running nightly.
- Logic:
- Fetch data from SIS API.
- Check if the user exists (create if not).
- Check if the course exists (create if not).
- Call
enrol_try_internal_enrol()or use the manual enrolment plugin instance to enrol the user.
- Optimization: Use the "Delta" approach—only fetch changes since the last run, rather than the full dataset every night.
Scenario 3: The "Hacked" Site
Question: You inherit a Moodle site that has been compromised. Spam forum posts are appearing. What are your immediate steps?
- Maintenance Mode: Immediately put the site in maintenance mode via CLI.
- Check Accounts: Look for new admin accounts or modified permissions in
mdl_role_assignments. - Code Integrity: Use
git statusto check for modified core files. If not using git, compare against a fresh Moodle download. - Uploads: Check
moodledataand/pixfolders for executable PHP files (webshells). - Logs: Analyze web server access logs for suspicious POST requests.
- Patch: Update Moodle to the latest security release.
Scenario 4: Custom Dashboard
Question: A client wants a completely custom dashboard for students, different from the standard Moodle Dashboard. It needs to show progress bars, upcoming deadlines, and a custom "Gamification" score.
Approach:
- Theme vs. Plugin: Do not hack the core dashboard. Create a
localplugin or a customblock. - Page Override: In the theme config, you can override the layout for the dashboard page, or redirect the user to a custom page in your local plugin upon login.
- Data Aggregation:
- Progress: Use
\core_completion\progressAPI. - Deadlines: Query the
mdl_eventtable (Calendar API). - Gamification: Store points in a custom table in your plugin.
- Progress: Use
- Frontend: Use a Mustache template and an AMD module to render the charts (e.g., ChartJS) asynchronously.
Scenario 5: High Availability Session Issue
Question: You deployed Moodle on two web servers behind a load balancer. Users report being logged out randomly as they navigate pages. What is wrong?
Diagnosis: Sessions are likely stored on the local file system of each server (default behavior). When a user hits Server A, they get a session. If the next request goes to Server B, that server doesn't know the session.
Fix:
- Shared Storage: Configure
$CFG->session_handler_classto use Redis, Memcached, or the Database. - Sticky Sessions: Alternatively, configure the Load Balancer for "Sticky Sessions" (Session Affinity), though shared storage is the more robust cloud-native solution.
Scenario 6: The Disappearing File
Question: You built a form with a file manager element. The user uploads a file, saves the form, and sees the success message. But when they reload the page, the file is gone. What step did you miss?
Diagnosis: The file is likely still in the "draft" area. Moodle file uploads go to a temporary draft area first.
Fix: You must process the files upon form submission.
- Draft Area: When the form loads, prepare the draft area using
file_prepare_standard_filemanager(). - Save: On submit, use
file_save_draft_area_files()to move the file from the draft area to the permanent file area (e.g.,mod_myplugin,attachment,$id). - Database: Update the database record to reference the new item ID if necessary (though usually the item ID is constant).