Customizable Online Poll Maker JavaScript, PHP
👤 Sharing: AI
```php
<?php
// Database Configuration (Adjust to your needs)
$host = "localhost";
$username = "root";
$password = "";
$database = "online_poll";
// Create Connection
$conn = new mysqli($host, $username, $password, $database);
// Check Connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// --- Handle New Poll Submission ---
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["create_poll"])) {
// Sanitize Input
$question = htmlspecialchars(trim($_POST["question"]));
$options = array_map('htmlspecialchars', array_map('trim', $_POST["options"])); //trim and sanitize
// Validate Input (Basic validation. More thorough validation is recommended)
if (empty($question) || count($options) < 2) {
$error_message = "Please enter a question and at least two options.";
} else {
// Prepare SQL statement to insert poll question
$stmt = $conn->prepare("INSERT INTO polls (question, created_at) VALUES (?, NOW())");
$stmt->bind_param("s", $question);
if ($stmt->execute()) {
$poll_id = $conn->insert_id; // Get the ID of the newly created poll
// Insert Options
$stmt_option = $conn->prepare("INSERT INTO poll_options (poll_id, option_text) VALUES (?, ?)");
$stmt_option->bind_param("is", $poll_id, $option_text);
foreach ($options as $option_text) {
$stmt_option->execute();
}
$stmt_option->close();
$stmt->close();
header("Location: index.php?poll_id=" . $poll_id . "&message=Poll created successfully!"); // Redirect to poll viewing page
exit();
} else {
$error_message = "Error creating poll: " . $stmt->error;
}
$stmt->close();
}
}
// --- Handle Voting ---
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["vote"])) {
$poll_id = $_POST["poll_id"];
$selected_option_id = $_POST["option"];
// Check if user has already voted (Basic implementation using cookies)
if (isset($_COOKIE["poll_voted_" . $poll_id])) {
$error_message = "You have already voted in this poll.";
} else {
// Prepare SQL statement to update the vote count
$stmt = $conn->prepare("UPDATE poll_options SET vote_count = vote_count + 1 WHERE id = ? AND poll_id = ?");
$stmt->bind_param("ii", $selected_option_id, $poll_id);
if ($stmt->execute()) {
// Set a cookie to prevent multiple votes from the same user (basic)
setcookie("poll_voted_" . $poll_id, true, time() + (86400 * 30), "/"); // Cookie expires in 30 days
$stmt->close();
header("Location: index.php?poll_id=" . $poll_id . "&message=Vote cast successfully!"); // Redirect to poll viewing page
exit();
} else {
$error_message = "Error casting vote: " . $stmt->error;
}
$stmt->close();
}
}
// --- Fetch Poll Data (if poll_id is set) ---
$poll = null;
$options = [];
if (isset($_GET["poll_id"])) {
$poll_id = $_GET["poll_id"];
// Fetch Poll Question
$stmt = $conn->prepare("SELECT id, question FROM polls WHERE id = ?");
$stmt->bind_param("i", $poll_id);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows > 0) {
$poll = $result->fetch_assoc();
} else {
$error_message = "Poll not found.";
}
$stmt->close();
// Fetch Poll Options
if ($poll) {
$stmt = $conn->prepare("SELECT id, option_text, vote_count FROM poll_options WHERE poll_id = ?");
$stmt->bind_param("i", $poll_id);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
$options[] = $row;
}
$stmt->close();
}
}
$conn->close();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Online Poll Maker</title>
<style>
body { font-family: sans-serif; }
.error { color: red; }
.message { color: green; }
.poll-results {
margin-top: 20px;
border: 1px solid #ccc;
padding: 10px;
}
.poll-results ul {
list-style: none;
padding: 0;
}
.poll-results li {
margin-bottom: 5px;
}
.poll-results .bar-container {
background-color: #f0f0f0;
height: 20px;
width: 100%;
position: relative;
}
.poll-results .bar {
background-color: #4CAF50;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.poll-results .percentage {
position: absolute;
right: 5px;
top: 0;
line-height: 20px;
}
</style>
</head>
<body>
<h1>Online Poll Maker</h1>
<?php if (isset($error_message)): ?>
<p class="error"><?php echo $error_message; ?></p>
<?php endif; ?>
<?php if (isset($_GET["message"])): ?>
<p class="message"><?php echo htmlspecialchars($_GET["message"]); ?></p>
<?php endif; ?>
<h2>Create a New Poll</h2>
<form method="POST">
<label for="question">Question:</label><br>
<input type="text" id="question" name="question" required><br><br>
<label for="options">Options (one per line):</label><br>
<div id="options-container">
<input type="text" name="options[]" required><br>
<input type="text" name="options[]" required><br>
</div>
<button type="button" onclick="addOption()">Add Option</button>
<button type="button" onclick="removeOption()">Remove Option</button>
<br><br>
<input type="submit" name="create_poll" value="Create Poll">
</form>
<hr>
<?php if ($poll): ?>
<h2><?php echo htmlspecialchars($poll["question"]); ?></h2>
<form method="POST">
<input type="hidden" name="poll_id" value="<?php echo $poll["id"]; ?>">
<?php foreach ($options as $option): ?>
<input type="radio" id="option_<?php echo $option["id"]; ?>" name="option" value="<?php echo $option["id"]; ?>" required>
<label for="option_<?php echo $option["id"]; ?>"><?php echo htmlspecialchars($option["option_text"]); ?></label><br>
<?php endforeach; ?>
<br>
<input type="submit" name="vote" value="Vote">
</form>
<h3>Results:</h3>
<div class="poll-results">
<ul>
<?php
$total_votes = array_sum(array_column($options, 'vote_count'));
foreach ($options as $option):
$percentage = ($total_votes > 0) ? round(($option['vote_count'] / $total_votes) * 100, 2) : 0;
?>
<li>
<?php echo htmlspecialchars($option['option_text']); ?>:
<div class="bar-container">
<div class="bar" style="width: <?php echo $percentage; ?>%;"></div>
<span class="percentage"><?php echo $percentage; ?>% (<?php echo $option['vote_count']; ?> votes)</span>
</div>
</li>
<?php endforeach; ?>
</ul>
<?php if ($total_votes == 0) : ?>
<p>No votes yet.</p>
<?php endif; ?>
</div>
<?php else: ?>
<?php if (isset($_GET["poll_id"])): ?>
<p>No poll selected or poll not found.</p>
<?php else: ?>
<p>Create a poll or select one from the list.</p>
<?php endif; ?>
<?php endif; ?>
<script>
function addOption() {
var container = document.getElementById("options-container");
var input = document.createElement("input");
input.type = "text";
input.name = "options[]";
input.required = true;
var br = document.createElement("br");
container.appendChild(input);
container.appendChild(br);
}
function removeOption() {
var container = document.getElementById("options-container");
// Remove the last input field and line break
var inputs = container.getElementsByTagName("input");
var breaks = container.getElementsByTagName("br");
if (inputs.length > 2) { // Keep at least two options
container.removeChild(inputs[inputs.length - 1]);
container.removeChild(breaks[breaks.length - 1]);
}
}
</script>
</body>
</html>
```
**Explanation:**
1. **Database Setup:**
* The code starts by defining the database connection details (`$host`, `$username`, `$password`, `$database`). **Important:** Update these values to match your MySQL database configuration. You'll also need to create the database and tables as described later.
* It establishes a connection to the database using `mysqli`.
* Error handling is included to check if the connection was successful. If it fails, the script will terminate with an error message.
2. **New Poll Creation (POST request with `create_poll`):**
* **Input Handling:** The code checks if the request method is POST and if the `create_poll` parameter is set, indicating a new poll submission.
* **Sanitization and Validation:**
* `htmlspecialchars()`: Crucially, input data from the form (question and options) are sanitized using `htmlspecialchars()` to prevent cross-site scripting (XSS) vulnerabilities. This converts special characters like `<`, `>`, `&`, `"` and `'` into their corresponding HTML entities.
* `trim()`: Leading and trailing whitespace is removed from the input using `trim()`.
* Basic validation: The script checks if the question is empty and if there are at least two options. **Important:** You should implement more robust validation, especially on the option fields to prevent empty or excessively long options.
* **Database Insertion:**
* **Prepared Statements:** Prepared statements are used to prevent SQL injection attacks. The SQL queries are prepared with placeholders (`?`), and the actual values are bound to the statement using `bind_param()`. This ensures that the input data is treated as data and not as part of the SQL query.
* The code first inserts the poll question into the `polls` table. The `created_at` column is set to the current timestamp using `NOW()`.
* After inserting the poll question, the code retrieves the auto-generated ID of the new poll using `$conn->insert_id`. This ID is needed to associate the poll options with the correct poll.
* The code then iterates through the array of options and inserts each option into the `poll_options` table. The `poll_id` is used to link the options to the correct poll.
* **Redirection:** After successfully creating the poll, the user is redirected to the poll viewing page (`index.php?poll_id=...`) with a success message. This is done using `header("Location: ...")` and `exit()`.
3. **Voting (POST request with `vote`):**
* **Input Handling:** Checks if the request is POST and if the `vote` parameter is set.
* **Basic Vote Prevention (Cookie-based):**
* The code checks if a cookie named `poll_voted_` + the poll ID exists. If it does, the user has already voted in that poll, and an error message is displayed. **Important:** This is a very basic and easily bypassed method of preventing multiple votes. For a more robust solution, consider using user accounts or IP address tracking (with appropriate privacy considerations) and storing vote information in the database.
* **Database Update:**
* A prepared statement is used to increment the `vote_count` in the `poll_options` table for the selected option.
* **Cookie Setting:** A cookie is set to indicate that the user has voted.
* **Redirection:** The user is redirected to the poll viewing page with a success message.
4. **Fetching Poll Data (GET request with `poll_id`):**
* **Check for `poll_id`:** The code checks if a `poll_id` is present in the GET request.
* **Fetch Poll Question:** If a `poll_id` is provided, the code retrieves the poll question from the `polls` table.
* Again, a prepared statement is used.
* **Fetch Poll Options:** The code then fetches the options associated with the poll from the `poll_options` table.
* Prepared statement is used again.
* **Error Handling:** If the poll is not found, an error message is displayed.
5. **HTML Structure:**
* The HTML provides the structure for the poll creation form, the poll voting form, and the display of results.
* **Form for Creating Polls:** A form with input fields for the poll question and options. The options are dynamically added and removed using JavaScript.
* **Form for Voting:** A form with radio buttons for each option, allowing the user to select their choice. The `poll_id` is passed as a hidden input.
* **Displaying Results:** If a poll has been selected, the results are displayed in an unordered list. A simple bar graph is created using HTML and CSS to visually represent the vote percentages. Includes logic to handle the case where there are no votes yet.
* **Error/Message Display:** Displays any error or success messages.
6. **JavaScript:**
* The JavaScript code provides the functionality for dynamically adding and removing options from the poll creation form.
* `addOption()`: Creates a new input field for an option and appends it to the options container.
* `removeOption()`: Removes the last input field from the options container, ensuring there are always at least two options.
**Database Tables:**
You need to create the following tables in your MySQL database:
```sql
CREATE TABLE polls (
id INT AUTO_INCREMENT PRIMARY KEY,
question VARCHAR(255) NOT NULL,
created_at DATETIME
);
CREATE TABLE poll_options (
id INT AUTO_INCREMENT PRIMARY KEY,
poll_id INT NOT NULL,
option_text VARCHAR(255) NOT NULL,
vote_count INT DEFAULT 0,
FOREIGN KEY (poll_id) REFERENCES polls(id)
);
```
**Important Considerations and Improvements:**
* **Security:**
* **SQL Injection:** The provided code uses prepared statements, which is a crucial step in preventing SQL injection. **However, carefully review the entire code base to ensure prepared statements are used correctly everywhere you interact with the database.**
* **Cross-Site Scripting (XSS):** The code uses `htmlspecialchars()` to sanitize user input, which is good. Make sure you sanitize output *everywhere* that user-provided data is displayed. Use the correct escaping function for the context (e.g., `htmlspecialchars()` for HTML, `urlencode()` for URLs).
* **Cross-Site Request Forgery (CSRF):** Implement CSRF protection to prevent malicious websites from making requests on behalf of authenticated users. This typically involves adding a hidden CSRF token to your forms and validating it on the server.
* **Input Validation:**
* **Server-Side Validation:** The basic validation provided (checking for empty fields) is not sufficient. You should implement more comprehensive validation on the server-side:
* **Data Types:** Ensure that data is of the expected type (e.g., integers for IDs, strings for text).
* **Length Limits:** Limit the length of input fields to prevent excessively long data from being stored in the database.
* **Regular Expressions:** Use regular expressions to validate the format of input fields (e.g., email addresses).
* **Client-Side Validation (Optional):** Client-side validation (using JavaScript) can provide immediate feedback to the user, but it should not be relied upon for security. Always perform validation on the server-side.
* **Vote Prevention:**
* The cookie-based vote prevention is easily bypassed. Consider the following alternatives:
* **User Accounts:** Require users to create accounts and log in before voting. This provides a more reliable way to track votes.
* **IP Address Tracking:** Track the IP addresses of voters. However, be aware that IP addresses can change, and users may share the same IP address (e.g., on a corporate network). Also, consider privacy implications.
* **Database Storage:** Store the vote information in the database, linking the vote to a user account or IP address.
* **Error Handling:**
* The error handling is basic. Implement more robust error handling to catch exceptions and log errors. This will help you identify and fix issues in your code. Display user-friendly error messages to the user.
* **User Interface (UI):**
* Improve the user interface to make the poll creation and voting process more intuitive and user-friendly.
* **Accessibility:**
* Make sure your poll application is accessible to users with disabilities. Use semantic HTML, provide alternative text for images, and ensure that your forms are properly labeled.
* **Scalability:**
* If you expect a large number of users, consider using a database that is designed for high scalability, such as MySQL with replication or a NoSQL database.
* **Code Organization:**
* For a larger application, consider separating the code into multiple files (e.g., database connection, poll creation, voting, display). Use functions and classes to organize the code and make it more maintainable.
* **Configuration:**
* Move the database connection details to a separate configuration file so that they can be easily changed without modifying the code.
* **Security Best Practices:**
* Keep your PHP installation and libraries up to date to patch security vulnerabilities.
* Use a strong password for your database user.
* Disable error reporting in production.
* Enable HTTPS to encrypt traffic between the client and server.
This improved example provides a more secure and robust foundation for your online poll maker. Remember to address the security and scalability considerations as your application grows. Good luck!
👁️ Viewed: 9
Comments