Development Guide
Guide for developers contributing to the Helpline Service.
Development Environment Setup
Prerequisites
- Docker & Docker Compose
- Git
- Code editor (VS Code recommended)
- Basic knowledge of PHP, JavaScript, MySQL
- Familiarity with REST APIs
Quick Start
bash
# 1. Clone repository
git clone https://github.com/openchlai/ai.git
cd ai/helplinev1
# 2. Setup environment
cp .env.example .env
# 3. Configure for development
# Edit .env:
APP_ENV=development
APP_DEBUG=true
LOG_LEVEL=debug
# 4. Start containers
docker-compose up -d
# 5. Access application
open http://localhost:8888Project Structure
helplinev1/
├── application/ # Frontend (PHP, JS, CSS)
│ ├── views/ # UI templates
│ ├── assets/ # CSS, JS, images
│ └── config/ # Frontend configuration
├── rest_api/ # Backend API
│ ├── api/ # Endpoint implementations
│ ├── lib/ # Core libraries
│ │ ├── rest.php
│ │ ├── session.php
│ │ └── database.php
│ └── config/ # Database schemas
├── docker/ # Docker configuration
│ ├── nginx/ # Nginx configuration
│ ├── php/ # PHP configuration
│ └── mysql/ # MySQL init scripts
└── docker-compose.yml # Service orchestrationDevelopment Workflow
1. Create Feature Branch
bash
# Update main
git checkout main
git pull origin main
# Create feature branch
git checkout -b feature/your-feature
# Verify you're on the right branch
git branch2. Make Changes
bash
# Frontend changes
# Edit files in application/
# Backend changes
# Edit files in rest_api/
# Database changes
# Update sql files in docker/mysql/3. Test Changes
bash
# Development server automatically hot-reloads
# Just refresh your browser
# Clear cache if needed
docker-compose exec helpline-php php -r "system('rm -rf storage/cache/*');"
# Check logs for errors
docker-compose logs -f helpline-php4. Debug with Logging
php
// In PHP code
error_log("Debug message: " . json_encode($data));
// View logs
docker-compose logs -f helpline-php | grep "Debug message"5. Commit and Push
bash
# Stage changes
git add .
# Commit with message
git commit -m "Add feature: description"
# Push to remote
git push origin feature/your-featureBackend Development (PHP REST API)
Creating New API Endpoint
- Create endpoint handler in
rest_api/api/:
php
<?php
// rest_api/api/v1/cases.php
class CasesAPI {
protected $db;
public function __construct($db) {
$this->db = $db;
}
public function create($request) {
// Validate input
if (empty($request['case_type'])) {
return ['error' => 'Case type required'];
}
// Create case
$query = "INSERT INTO cases (case_type, description, created_at)
VALUES (?, ?, NOW())";
$stmt = $this->db->prepare($query);
$stmt->execute([$request['case_type'], $request['description']]);
return ['id' => $this->db->lastInsertId(), 'status' => 'created'];
}
}- Register route in router:
php
// rest_api/lib/router.php
$router->post('/cases', 'CasesAPI@create');- Test endpoint:
bash
curl -X POST http://localhost:8888/api/v1/cases \
-H "Content-Type: application/json" \
-d '{"case_type": "abuse", "description": "..."}'Database Queries
php
// Simple query
$query = "SELECT * FROM users WHERE id = ?";
$stmt = $db->prepare($query);
$stmt->execute([$id]);
$result = $stmt->fetch();
// Insert
$query = "INSERT INTO cases (type, description) VALUES (?, ?)";
$stmt = $db->prepare($query);
$stmt->execute([$type, $description]);
// Update
$query = "UPDATE cases SET status = ? WHERE id = ?";
$stmt = $db->prepare($query);
$stmt->execute([$status, $id]);
// Always use prepared statements to prevent SQL injectionFrontend Development (JavaScript/CSS)
File Organization
application/
├── views/
│ ├── cases/
│ │ ├── list.php
│ │ ├── create.php
│ │ └── detail.php
│ ├── dashboard.php
│ └── layout.php
├── assets/
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ ├── app.js
│ │ └── api.js
│ └── images/Creating New Page
- Create view file
application/views/cases/list.php:
php
<?php include '../layout.php'; ?>
<div class="container">
<h1>Cases</h1>
<button onclick="newCase()" class="btn-primary">New Case</button>
<table id="casesTable">
<thead>
<tr>
<th>ID</th>
<th>Type</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="casesBody"></tbody>
</table>
</div>
<script>
function loadCases() {
fetch('/api/v1/cases')
.then(r => r.json())
.then(data => {
// Populate table
});
}
window.onload = loadCases;
</script>Add route in router
Style with CSS in
assets/css/style.css
Testing
Manual Testing
bash
# Test in browser
http://localhost:8888
# Test API directly
curl http://localhost:8888/api/v1/cases
# Test with Postman
# Import endpoints into Postman
# Set base URL to http://localhost:8888/api/v1Running Tests
bash
# If using PHPUnit
docker-compose exec helpline-php ./vendor/bin/phpunit
# If using Jest for JavaScript
docker-compose exec helpline-php npm testDatabase Migrations
Create New Table
- Create migration file
docker/mysql/migrations/001_create_cases.sql:
sql
CREATE TABLE IF NOT EXISTS cases (
id INT PRIMARY KEY AUTO_INCREMENT,
case_type VARCHAR(50) NOT NULL,
description TEXT,
status VARCHAR(20) DEFAULT 'open',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE INDEX idx_case_type ON cases(case_type);
CREATE INDEX idx_status ON cases(status);- Apply migration:
bash
# Migrations run automatically on container start
# Or manually:
docker-compose exec helpline-mysql mysql -u root -p$MYSQL_ROOT_PASSWORD \
-D $MYSQL_DATABASE < migrations/001_create_cases.sqlCommon Development Tasks
View Live Logs
bash
# PHP logs
docker-compose logs -f helpline-php
# Nginx logs
docker-compose logs -f helpline-nginx
# MySQL logs
docker-compose logs -f helpline-mysqlAccess Container Shell
bash
# PHP container
docker-compose exec helpline-php bash
# Run PHP directly
docker-compose exec helpline-php php -r "phpinfo();"
# MySQL container
docker-compose exec helpline-mysql bash
docker-compose exec helpline-mysql mysql -u root -p$MYSQL_ROOT_PASSWORDClear Application Cache
bash
docker-compose exec helpline-php php -r "
@array_map('unlink', glob('storage/cache/*'));
echo 'Cache cleared';
"Restart a Service
bash
docker-compose restart helpline-php
docker-compose restart helpline-nginx
docker-compose restart helpline-mysqlInstall PHP Dependencies
bash
docker-compose exec helpline-php composer installCode Standards
PHP Code Style
php
<?php
// Use PSR-12 coding standards
class CaseManager {
private $database;
public function __construct($db) {
$this->database = $db;
}
public function getCase($id) {
// Method body
return $case;
}
}
// 4-space indentation
// No trailing spaces
// Single quotes for strings (unless interpolation)JavaScript Style
javascript
// Use ES6+ syntax
const CaseAPI = {
async getCase(id) {
const response = await fetch(`/api/v1/cases/${id}`);
return response.json();
},
async createCase(data) {
const response = await fetch('/api/v1/cases', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
return response.json();
}
};Git Workflow Reminder
bash
# Create feature branch
git checkout -b feature/feature-name
# Make changes and commit
git add .
git commit -m "Description of changes"
# Push to remote
git push origin feature/feature-name
# Create Pull Request (GitHub)
# Request review
# Wait for approval
# Merge to dev (automatic staging deploy)
# Test in staging: http://192.168.10.119/helplineDebugging Tips
Enable Debug Mode
bash
# In .env
APP_DEBUG=true
LOG_LEVEL=debug
# Restart
docker-compose restartCheck Error Logs
bash
# View full error details
docker-compose logs -f helpline-php | grep -A 10 "Error"
# Or check log file directly
docker-compose exec helpline-php tail -f /var/log/helpline/error.logDatabase Debugging
bash
# Connect to MySQL
docker-compose exec helpline-mysql mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE
# Run queries
SELECT * FROM cases LIMIT 5;
EXPLAIN SELECT * FROM cases WHERE id = 1;