Overview
This example demonstrates how to use Now.js with a PHP backend to create a simple CRUD application. We'll build a task management system that includes:
- User authentication
- Task creation and management
- Real-time updates
- Data persistence with MySQL
Architecture
├── frontend/ # Now.js frontend
│ ├── index.html
│ ├── components/
│ │ ├── TaskList.js
│ │ ├── TaskForm.js
│ │ └── TaskItem.js
│ └── css/
│ └── styles.css
│
├── backend/ # PHP backend
│ ├── api/
│ │ ├── tasks.php
│ │ └── auth.php
│ ├── config/
│ │ └── database.php
│ └── models/
│ └── Task.php
│
└── database/ # Database schema
└── schema.sql
Installation
Requirements
- PHP 7.4+
- MySQL 5.7+
- Apache/Nginx web server
Setup Steps
# Clone the repository
git clone https://github.com/username/nowjs-php-example
cd nowjs-php-example
# Import database schema
mysql -u your_user -p your_database < database/schema.sql
# Configure database connection
cp backend/config/database.example.php backend/config/database.php
# Edit database.php with your credentials
Frontend Implementation
Task List Component
// components/TaskList.js
Now.component('task-list', {
template: `
{{title}}
{{#each tasks}}
{{/each}}
`,
state: {
title: 'My Tasks',
tasks: []
},
methods: {
async loadTasks() {
try {
const response = await fetch('/api/tasks.php');
const data = await response.json();
this.state.tasks = data;
} catch (error) {
console.error('Failed to load tasks:', error);
}
},
async handleSubmit(task) {
try {
const response = await fetch('/api/tasks.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(task)
});
const newTask = await response.json();
this.state.tasks.push(newTask);
} catch (error) {
console.error('Failed to create task:', error);
}
},
async handleUpdate(task) {
try {
await fetch(`/api/tasks.php?id=${task.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(task)
});
const index = this.state.tasks.findIndex(t => t.id === task.id);
this.state.tasks[index] = task;
} catch (error) {
console.error('Failed to update task:', error);
}
}
},
mounted() {
this.loadTasks();
}
});
Task Item Component
// components/TaskItem.js
Now.component('task-item', {
template: `
{{task.title}}
`,
props: ['task'],
methods: {
async toggleComplete() {
const updatedTask = {
...this.props.task,
completed: !this.props.task.completed
};
this.emit('update', updatedTask);
},
handleDelete() {
this.emit('delete', this.props.task);
}
}
});
Backend Implementation
Database Configuration
'localhost',
'database' => 'tasks_db',
'username' => 'your_username',
'password' => 'your_password'
];
Tasks API
getAll());
break;
case 'POST':
$data = json_decode(file_get_contents('php://input'), true);
$newTask = $task->create($data);
echo json_encode($newTask);
break;
case 'PUT':
$id = $_GET['id'];
$data = json_decode(file_get_contents('php://input'), true);
$task->update($id, $data);
echo json_encode(['success' => true]);
break;
case 'DELETE':
$id = $_GET['id'];
$task->delete($id);
echo json_encode(['success' => true]);
break;
}
Task Model
db = $db;
}
public function getAll() {
$stmt = $this->db->query('SELECT * FROM tasks ORDER BY created_at DESC');
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function create($data) {
$stmt = $this->db->prepare(
'INSERT INTO tasks (title, completed) VALUES (?, ?)'
);
$stmt->execute([$data['title'], $data['completed'] ?? false]);
return [
'id' => $this->db->lastInsertId(),
'title' => $data['title'],
'completed' => $data['completed'] ?? false
];
}
public function update($id, $data) {
$stmt = $this->db->prepare(
'UPDATE tasks SET title = ?, completed = ? WHERE id = ?'
);
$stmt->execute([
$data['title'],
$data['completed'],
$id
]);
}
public function delete($id) {
$stmt = $this->db->prepare('DELETE FROM tasks WHERE id = ?');
$stmt->execute([$id]);
}
}
Database Schema
-- database/schema.sql
CREATE TABLE tasks (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
completed BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Security Considerations
- Always validate and sanitize input data
- Use prepared statements for database queries
- Implement proper CSRF protection
- Add appropriate authentication middleware
- Set up proper CORS headers if needed
Live Demo
Task List
Complete documentation
Add new features