Personal Finance Tracker JavaScript, PHP, MySQL
👤 Sharing: AI
Okay, here's a basic example of a personal finance tracker using JavaScript (for the front-end), PHP (for the back-end), and MySQL (for the database). I'll provide code snippets and explanations for each part. This is a simplified example to illustrate the core concepts. A real-world application would be more robust and secure.
**Conceptual Overview**
1. **Database (MySQL):**
* Stores user data, transaction details, categories, etc.
2. **Back-end (PHP):**
* Handles requests from the front-end (e.g., adding a transaction, retrieving data).
* Interacts with the database to read and write data.
* Provides an API (Application Programming Interface) that the front-end can communicate with.
3. **Front-end (JavaScript, HTML, CSS):**
* Provides the user interface for interacting with the application.
* Sends requests to the PHP back-end.
* Displays the data received from the back-end.
**1. Database (MySQL)**
```sql
-- Database Name: finance_tracker
CREATE DATABASE IF NOT EXISTS finance_tracker;
USE finance_tracker;
-- Table: users
CREATE TABLE IF NOT EXISTS users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL, -- Store hashed passwords!
email VARCHAR(100) UNIQUE
);
-- Table: categories
CREATE TABLE IF NOT EXISTS categories (
category_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
category_name VARCHAR(50) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
);
-- Table: transactions
CREATE TABLE IF NOT EXISTS transactions (
transaction_id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
category_id INT,
transaction_date DATE NOT NULL,
description VARCHAR(255),
amount DECIMAL(10, 2) NOT NULL, -- Up to 10 digits, 2 decimal places
type ENUM('income', 'expense') NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE,
FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE SET NULL --category can be deleted and tranasction should be keeped
);
```
**Explanation:**
* `finance_tracker`: The name of the database.
* `users`: Stores user information (username, hashed password, email). **Important:** Always hash passwords before storing them in the database. Use functions like `password_hash()` in PHP.
* `categories`: Stores transaction categories (e.g., "Food", "Rent", "Salary"). Links to a specific user.
* `transactions`: Stores individual transaction details (date, description, amount, type - income/expense). Links to a specific user and category.
* `FOREIGN KEY`: Ensures data integrity by linking tables together. For example, a transaction must belong to a valid user.
* `ON DELETE CASCADE`: If a user is deleted, all their related categories and transactions are also deleted.
* `ON DELETE SET NULL`: If a category is deleted, the `category_id` in associated transactions will be set to `NULL`.
**2. Back-end (PHP)**
Create a directory structure. Let's assume:
```
finance_tracker/
??? api/
? ??? db_connect.php
? ??? add_transaction.php
? ??? get_transactions.php
? ??? ... other API endpoints ...
??? ... other files ...
```
**`api/db_connect.php` (Database Connection):**
```php
<?php
$servername = "localhost"; // Or your database host
$username = "your_db_username";
$password = "your_db_password";
$dbname = "finance_tracker";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$conn->set_charset("utf8"); //Set the character to utf8
?>
```
**Explanation:**
* This file establishes a connection to your MySQL database. **Replace** `"your_db_username"` and `"your_db_password"` with your actual database credentials.
* `$conn`: A variable to store the database connection object.
* Error handling: Checks if the connection was successful.
* `$conn->set_charset("utf8")`: Set connection encoding to utf8 to ensure that all strings are properly encoded and no characters are lost.
**`api/add_transaction.php` (Add a Transaction):**
```php
<?php
header("Content-Type: application/json"); // Send JSON response
require_once 'db_connect.php';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user_id = $_POST['user_id'] ?? null; // Use null coalescing operator
$category_id = $_POST['category_id'] ?? null; // Allow null category
$transaction_date = $_POST['transaction_date'] ?? null;
$description = $_POST['description'] ?? ''; // Empty string if not provided
$amount = $_POST['amount'] ?? null;
$type = $_POST['type'] ?? null;
// Validate data (basic example)
if (empty($user_id) || empty($transaction_date) || empty($amount) || empty($type)) {
http_response_code(400); // Bad Request
echo json_encode(array("message" => "Missing required fields."));
exit;
}
$amount = floatval($amount); // Convert to float
if (!in_array($type, ['income', 'expense'])) {
http_response_code(400);
echo json_encode(["message" => "Invalid transaction type."]);
exit;
}
// Prepare and execute the SQL query
$sql = "INSERT INTO transactions (user_id, category_id, transaction_date, description, amount, type)
VALUES (?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
if ($stmt === false) {
http_response_code(500); // Internal Server Error
echo json_encode(["message" => "Database error: " . $conn->error]);
exit;
}
$stmt->bind_param("iisssd", $user_id, $category_id, $transaction_date, $description, $amount, $type); // "iisssd" specifies data types
if ($stmt->execute()) {
http_response_code(201); // Created
echo json_encode(array("message" => "Transaction added successfully."));
} else {
http_response_code(500);
echo json_encode(array("message" => "Error adding transaction: " . $stmt->error));
}
$stmt->close();
$conn->close();
} else {
http_response_code(405); // Method Not Allowed
echo json_encode(array("message" => "Method not allowed. Use POST."));
}
?>
```
**Explanation:**
* `header("Content-Type: application/json")`: Sets the response content type to JSON.
* `require_once 'db_connect.php'`: Includes the database connection file.
* `$_SERVER["REQUEST_METHOD"] == "POST"`: Checks if the request method is POST.
* `$_POST['...'] ?? null`: Retrieves data from the POST request. The `?? null` is the null coalescing operator: If the POST value is not set, it defaults to `null`. This handles cases where optional fields are missing.
* **Data Validation:** Basic validation is performed to ensure required fields are present and the transaction type is valid. **Crucially, you need more robust validation in a real application.** Sanitize the data to prevent SQL injection and cross-site scripting (XSS) attacks.
* **Prepared Statements:** Uses prepared statements (`$conn->prepare()`, `$stmt->bind_param()`, `$stmt->execute()`) to prevent SQL injection. This is a **must** for security.
* `$stmt->bind_param("iisssd", ...)`: Binds parameters to the prepared statement. The string "iisssd" specifies the data types:
* `i`: integer
* `s`: string
* `d`: double (decimal)
* Error handling: Includes checks for database errors and returns appropriate HTTP status codes and JSON error messages.
* HTTP Status Codes:
* `201 Created`: Transaction added successfully.
* `400 Bad Request`: Missing or invalid data.
* `405 Method Not Allowed`: Used wrong request method (e.g., GET instead of POST).
* `500 Internal Server Error`: Database error.
**`api/get_transactions.php` (Get Transactions):**
```php
<?php
header("Content-Type: application/json");
require_once 'db_connect.php';
if ($_SERVER["REQUEST_METHOD"] == "GET") {
$user_id = $_GET['user_id'] ?? null;
if (empty($user_id)) {
http_response_code(400);
echo json_encode(array("message" => "Missing user_id."));
exit;
}
$sql = "SELECT transaction_id, category_id, transaction_date, description, amount, type
FROM transactions
WHERE user_id = ?";
$stmt = $conn->prepare($sql);
if ($stmt === false) {
http_response_code(500);
echo json_encode(["message" => "Database error: " . $conn->error]);
exit;
}
$stmt->bind_param("i", $user_id);
$stmt->execute();
$result = $stmt->get_result();
$transactions = array();
while ($row = $result->fetch_assoc()) {
$transactions[] = $row;
}
echo json_encode($transactions);
$stmt->close();
$conn->close();
} else {
http_response_code(405);
echo json_encode(array("message" => "Method not allowed. Use GET."));
}
?>
```
**Explanation:**
* Similar to `add_transaction.php`, but retrieves transactions from the database.
* Uses a `GET` request.
* Requires a `user_id` in the query string (e.g., `get_transactions.php?user_id=1`).
* Fetches the results into an array `$transactions` and encodes it as JSON.
**Example of other API endpoints:**
* `get_categories.php`: Retrieve categories for a user.
* `add_category.php`: Add a new category.
* `update_transaction.php`: Update an existing transaction.
* `delete_transaction.php`: Delete a transaction.
* `register.php`: Register a new user.
* `login.php`: Authenticate a user.
**3. Front-end (JavaScript, HTML, CSS)**
Create the following directory structure.
```
finance_tracker/
??? api/
? ??? db_connect.php
? ??? add_transaction.php
? ??? get_transactions.php
? ??? ... other API endpoints ...
??? public/
??? index.html
??? style.css
??? script.js
??? ... other files ...
```
**`public/index.html` (HTML Structure):**
```html
<!DOCTYPE html>
<html>
<head>
<title>Personal Finance Tracker</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Personal Finance Tracker</h1>
<div id="transaction-form">
<h2>Add Transaction</h2>
<form id="add-transaction-form">
<label for="user_id">User ID:</label>
<input type="number" id="user_id" name="user_id" required><br><br>
<label for="category_id">Category ID:</label>
<input type="number" id="category_id" name="category_id"><br><br>
<label for="transaction_date">Date:</label>
<input type="date" id="transaction_date" name="transaction_date" required><br><br>
<label for="description">Description:</label>
<input type="text" id="description" name="description"><br><br>
<label for="amount">Amount:</label>
<input type="number" step="0.01" id="amount" name="amount" required><br><br>
<label for="type">Type:</label>
<select id="type" name="type" required>
<option value="income">Income</option>
<option value="expense">Expense</option>
</select><br><br>
<button type="submit">Add Transaction</button>
</form>
</div>
<div id="transaction-list">
<h2>Transactions</h2>
<ul id="transactions">
<!-- Transactions will be displayed here -->
</ul>
</div>
<script src="script.js"></script>
</body>
</html>
```
**`public/script.js` (JavaScript):**
```javascript
document.addEventListener('DOMContentLoaded', function() {
const transactionForm = document.getElementById('add-transaction-form');
const transactionsList = document.getElementById('transactions');
// Function to fetch and display transactions
function fetchTransactions(userId) {
fetch(`api/get_transactions.php?user_id=${userId}`) // Replace with your API endpoint
.then(response => response.json())
.then(data => {
transactionsList.innerHTML = ''; // Clear existing list
data.forEach(transaction => {
const listItem = document.createElement('li');
listItem.textContent = `${transaction.transaction_date} - ${transaction.description} - ${transaction.amount} (${transaction.type})`;
transactionsList.appendChild(listItem);
});
})
.catch(error => console.error('Error fetching transactions:', error));
}
// Handle form submission
transactionForm.addEventListener('submit', function(event) {
event.preventDefault(); // Prevent default form submission
const formData = new FormData(transactionForm); // Create FormData object
fetch('api/add_transaction.php', { // Replace with your API endpoint
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
alert(data.message); // Show success/error message
const userId = document.getElementById('user_id').value;
fetchTransactions(userId); // Refresh transaction list
transactionForm.reset(); // Clear the form
})
.catch(error => console.error('Error adding transaction:', error));
});
// Initial load of transactions (example: for user ID 1)
fetchTransactions(1); // Load transactions for user 1 initially
});
```
**Explanation:**
* `DOMContentLoaded`: Ensures the script runs after the HTML is fully loaded.
* `fetch()`: Used to make HTTP requests to the PHP back-end.
* `FormData`: A convenient way to collect form data for sending in a request.
* `response.json()`: Parses the JSON response from the server.
* `transactionsList.innerHTML = '';`: Clears the existing transaction list before displaying new data.
* The code iterates through the received transaction data and creates list items (`<li>`) to display each transaction.
* Event Listener: The form has an event listener. On submit, fetch is called with 'api/add_transaction.php' and method: 'POST'.
* `transactionForm.reset();`: After submitting, the form is cleared
**`public/style.css` (CSS Styling - Optional):**
```css
body {
font-family: sans-serif;
margin: 20px;
}
#transaction-form {
margin-bottom: 20px;
border: 1px solid #ccc;
padding: 10px;
}
#transaction-list ul {
list-style-type: none;
padding: 0;
}
#transaction-list li {
border-bottom: 1px solid #eee;
padding: 5px 0;
}
```
**Important Considerations and Next Steps:**
* **Security:** This is a very basic example and lacks proper security measures. **You must implement robust security practices in a real-world application:**
* **Password Hashing:** Use `password_hash()` in PHP to securely store passwords. Never store plain text passwords.
* **Input Validation and Sanitization:** Thoroughly validate and sanitize all user input to prevent SQL injection, XSS attacks, and other vulnerabilities. Use functions like `htmlspecialchars()`, `filter_var()`, and prepared statements.
* **Authentication and Authorization:** Implement a proper authentication system to verify user identities and authorization to control access to resources. Use sessions or JWT (JSON Web Tokens).
* **CSRF Protection:** Protect against Cross-Site Request Forgery (CSRF) attacks.
* **Error Handling:** Improve error handling on both the front-end and back-end. Log errors for debugging.
* **User Interface (UI):** This example has a very basic UI. Use CSS to style the application and make it more user-friendly. Consider using a JavaScript framework like React, Angular, or Vue.js for a more complex UI.
* **Database Design:** As your application grows, you might need to normalize your database schema further.
* **API Design:** Design your API endpoints in a RESTful manner.
* **Deployment:** Consider how you will deploy your application to a web server.
* **Testing:** Write unit tests and integration tests to ensure the code works correctly.
* **Session management**: You should implement a login functionality using PHP sessions so the application can store user data while using it.
**How to Run This Example:**
1. **Set up a web server (e.g., Apache or Nginx) with PHP and MySQL.**
2. **Create the `finance_tracker` database in MySQL.**
3. **Create the tables using the SQL script.**
4. **Configure the `db_connect.php` file with your database credentials.**
5. **Place the PHP files in a directory accessible by your web server (e.g., `/var/www/html/finance_tracker/api`).**
6. **Place the HTML, CSS, and JavaScript files in a publicly accessible directory (e.g., `/var/www/html/finance_tracker/public`).**
7. **Access the `index.html` file in your web browser (e.g., `http://localhost/finance_tracker/public/index.html`).**
This example provides a basic foundation for building a personal finance tracker. Remember to prioritize security and follow best practices as you develop the application further.
👁️ Viewed: 8
Comments