From 39476324938b37c90a63c6f5bbe999c10623376f Mon Sep 17 00:00:00 2001 From: John Doe <johndoe@example.com> Date: Fri, 27 Sep 2024 16:34:50 +0500 Subject: [PATCH] AsyncPHP added --- Async-PHP/Backend/db_connect.php | 26 ++++ .../Backend/multiple_async_get_outputs.php | 58 ++++++++ Async-PHP/Backend/template.php | 8 ++ Async-PHP/Backend/template_async.php | 18 +++ Async-PHP/app/.htaccess | 25 ++++ Async-PHP/app/reuseable_views/footer.php | 23 ++++ .../app/reuseable_views/footer_async.php | 31 +++++ Async-PHP/app/reuseable_views/footer_form.php | 38 ++++++ .../app/reuseable_views/footer_form.php.bak | 30 +++++ Async-PHP/app/reuseable_views/footer_json.php | 31 +++++ Async-PHP/app/reuseable_views/header.php | 11 ++ Async-PHP/app/template.php | 17 +++ Async-PHP/async_scripts/db_connect.php | 19 +++ Async-PHP/css/style.php | 80 +++++++++++ Async-PHP/index.php | 36 +++++ Async-PHP/index1.php | 57 ++++++++ Async-PHP/js/router_js.php | 126 ++++++++++++++++++ Async-PHP/lib/AsyncRunner.php | 38 ++++++ Async-PHP/router_links/links.php | 11 ++ 19 files changed, 683 insertions(+) create mode 100644 Async-PHP/Backend/db_connect.php create mode 100644 Async-PHP/Backend/multiple_async_get_outputs.php create mode 100644 Async-PHP/Backend/template.php create mode 100644 Async-PHP/Backend/template_async.php create mode 100644 Async-PHP/app/.htaccess create mode 100644 Async-PHP/app/reuseable_views/footer.php create mode 100644 Async-PHP/app/reuseable_views/footer_async.php create mode 100644 Async-PHP/app/reuseable_views/footer_form.php create mode 100644 Async-PHP/app/reuseable_views/footer_form.php.bak create mode 100644 Async-PHP/app/reuseable_views/footer_json.php create mode 100644 Async-PHP/app/reuseable_views/header.php create mode 100644 Async-PHP/app/template.php create mode 100644 Async-PHP/async_scripts/db_connect.php create mode 100644 Async-PHP/css/style.php create mode 100644 Async-PHP/index.php create mode 100644 Async-PHP/index1.php create mode 100644 Async-PHP/js/router_js.php create mode 100644 Async-PHP/lib/AsyncRunner.php create mode 100644 Async-PHP/router_links/links.php diff --git a/Async-PHP/Backend/db_connect.php b/Async-PHP/Backend/db_connect.php new file mode 100644 index 0000000..acdee90 --- /dev/null +++ b/Async-PHP/Backend/db_connect.php @@ -0,0 +1,26 @@ +<?php +$servername = ""; +$username = ""; +$password = ""; +$dbname = ""; +$port = ""; + +// Create connection +$conn = new mysqli($servername, $username, $password, $dbname, $port); + +// Check connection +if ($conn->connect_error) { + die("Connection failed: " . $conn->connect_error); + } + + + + +//else{ +// echo "Connected successfully"; +//} +// Make sure to stop connection in files where you will use this + + +?> + diff --git a/Async-PHP/Backend/multiple_async_get_outputs.php b/Async-PHP/Backend/multiple_async_get_outputs.php new file mode 100644 index 0000000..26c4399 --- /dev/null +++ b/Async-PHP/Backend/multiple_async_get_outputs.php @@ -0,0 +1,58 @@ +<?php + + +require_once '../lib/AsyncRunner.php'; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + echo "Received POST request.<br>"; // Debug statement + $path = '../async_scripts'; + $scripts = ["$path/script1.php", "$path/script2.php", "$path/script3.php"]; + + // Run the scripts asynchronously + $outputs = runScriptsAsync($scripts); // Call the function directly + echo "Scripts executed. Outputs:<br>"; // Debug statement + + // Initialize variables for individual outputs + $output1 = ''; + $output2 = ''; + $output3 = ''; + + // Assign outputs to individual variables + if (isset($outputs[0])) { + $output1 = trim($outputs[0]); // Script 1 output + } + if (isset($outputs[1])) { + $output2 = trim($outputs[1]); // Script 2 output + } + if (isset($outputs[2])) { + $output3 = trim($outputs[2]); // Script 3 output + } + + // Output the individual outputs + echo "Output 1: " . $output1 . "<br>"; + echo "Output 2: " . $output2 . "<br>"; + echo "Output 3: " . $output3 . "<br>"; + + // Initialize the sum + $sum = 0; + + // Calculate the sum only for non-empty outputs + if ($output1 !== '') { + $sum += floatval($output1); + } + if ($output2 !== '') { + $sum += floatval($output2); + } + if ($output3 !== '') { + $sum += floatval($output3); + } + + // Output the total sum + echo "<strong>Total Sum: " . $sum . "</strong>"; +echo "ok"; +} + + + + +?> diff --git a/Async-PHP/Backend/template.php b/Async-PHP/Backend/template.php new file mode 100644 index 0000000..e3cb372 --- /dev/null +++ b/Async-PHP/Backend/template.php @@ -0,0 +1,8 @@ +<?php + + +echo "hellow from AsyncPHP"; + + + +?> diff --git a/Async-PHP/Backend/template_async.php b/Async-PHP/Backend/template_async.php new file mode 100644 index 0000000..6e9f491 --- /dev/null +++ b/Async-PHP/Backend/template_async.php @@ -0,0 +1,18 @@ +<?php + +require_once '../lib/AsyncRunner.php'; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $path = '../async_scripts'; + $scripts = ["$path/db_script1.php", "$path/db_script2.php", "$path/db_script3.php"]; + + $outputs = runScriptsAsync($scripts); // Call the function directly + + foreach ($outputs as $output) { + echo "<pre>$output</pre>"; + } +} + +echo "Script executed successfully."; + +?> diff --git a/Async-PHP/app/.htaccess b/Async-PHP/app/.htaccess new file mode 100644 index 0000000..82cbaaf --- /dev/null +++ b/Async-PHP/app/.htaccess @@ -0,0 +1,25 @@ +<IfModule mod_rewrite.c> + RewriteEngine On + + # Redirect any requests with .php extension to the URL without the extension + RewriteCond %{THE_REQUEST} \s/([^.]+)\.php[\s?] [NC] + RewriteRule ^ /%1 [R=301,L] + + # Internally rewrite requests without .php to the actual .php file + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME}\.php -f + RewriteRule ^(.*)$ $1.php [L] + + +# Route /app to app/index.php +RewriteRule ^app/?$ /app/index.php [L] + +# If you want to handle all requests under /app (e.g., /app/something) +RewriteRule ^app/(.*)$ /app/index.php [L,QSA] + +</IfModule> + +# Enable the rewrite engine +Options +FollowSymLinks + diff --git a/Async-PHP/app/reuseable_views/footer.php b/Async-PHP/app/reuseable_views/footer.php new file mode 100644 index 0000000..4d764d7 --- /dev/null +++ b/Async-PHP/app/reuseable_views/footer.php @@ -0,0 +1,23 @@ +<script> + $(document).ready(function() { + // Use event delegation to handle click events for elements with class 'runScripts' + $(document).on('click', '.runScripts', function(e) { + e.preventDefault(); + var url = $(this).data('url'); // Get the URL from the data attribute + + $.ajax({ + url: url, + method: 'POST', + success: function(data) { + $('#output').html(data); + }, + error: function(jqXHR, textStatus, errorThrown) { + $('#output').html("Error: " + textStatus + " " + errorThrown); + } + }); + }); + }); +</script> +</body> +</html> + diff --git a/Async-PHP/app/reuseable_views/footer_async.php b/Async-PHP/app/reuseable_views/footer_async.php new file mode 100644 index 0000000..5b90903 --- /dev/null +++ b/Async-PHP/app/reuseable_views/footer_async.php @@ -0,0 +1,31 @@ +<script> + document.addEventListener('DOMContentLoaded', () => { + const button = document.querySelector('.runScripts'); + button.addEventListener('click', (e) => { + e.preventDefault(); + const url = button.getAttribute('data-url'); // Get the URL from the data attribute + + fetch(url, { + method: 'POST', // Change to POST + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' // Set content type + } + }) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok ' + response.statusText); + } + return response.text(); + }) + .then(data => { + document.getElementById('output').innerHTML = data; + }) + .catch(err => { + console.error('Error fetching output:', err); + document.getElementById('output').innerHTML = 'Error fetching output: ' + err.message; + }); + }); + }); +</script> +</body> +</html> diff --git a/Async-PHP/app/reuseable_views/footer_form.php b/Async-PHP/app/reuseable_views/footer_form.php new file mode 100644 index 0000000..7c213eb --- /dev/null +++ b/Async-PHP/app/reuseable_views/footer_form.php @@ -0,0 +1,38 @@ +<script> + $(document).ready(function() { + // Use event delegation to handle click events for elements with class 'runScripts' + $(document).on('click', '.runScripts', function(e) { + e.preventDefault(); + + // Get the URL from the data-url attribute of the button + var url = $(this).data('url'); + + // Get the form associated with the button that was clicked + var form = $(this).closest('form'); + + // Check if a form was found + if (form.length) { + // Gather form data using FormData object + var formData = new FormData(form[0]); + + $.ajax({ + url: url, + type: 'POST', + data: formData, + processData: false, // Do not process the data into a query string + contentType: false, // Do not set content type + success: function(data) { + $('#output').html(data); // Show response in the output div + }, + error: function(jqXHR, textStatus, errorThrown) { + $('#output').html("Error: " + textStatus + " " + errorThrown); + } + }); + } else { + $('#output').html("Error: No form associated with this button."); + } + }); + }); +</script> +</body> +</html> diff --git a/Async-PHP/app/reuseable_views/footer_form.php.bak b/Async-PHP/app/reuseable_views/footer_form.php.bak new file mode 100644 index 0000000..82cb418 --- /dev/null +++ b/Async-PHP/app/reuseable_views/footer_form.php.bak @@ -0,0 +1,30 @@ +<script> + $(document).ready(function() { + // Use event delegation to handle click events for elements with class 'runScripts' + $(document).on('click', '.runScripts', function(e) { + e.preventDefault(); + + // Get the URL from the data-url attribute of the button + var url = $(this).data('url'); + + // Gather form data using FormData object + var formData = new FormData($('#userForm')[0]); + + $.ajax({ + url: url, + type: 'POST', + data: formData, + processData: false, // Do not process the data into a query string + contentType: false, // Do not set content type + success: function(data) { + $('#output').html(data); // Show response in the output div + }, + error: function(jqXHR, textStatus, errorThrown) { + $('#output').html("Error: " + textStatus + " " + errorThrown); + } + }); + }); + }); +</script> +</body> +</html> diff --git a/Async-PHP/app/reuseable_views/footer_json.php b/Async-PHP/app/reuseable_views/footer_json.php new file mode 100644 index 0000000..c5727d8 --- /dev/null +++ b/Async-PHP/app/reuseable_views/footer_json.php @@ -0,0 +1,31 @@ +<script> + +$(document).ready(function() { + $(document).on('click', '.runScripts', function(e) { + e.preventDefault(); + var url = $(this).data('url'); // Get the URL from the data attribute + console.log("AJAX URL:", url); // Log the URL to console + + $.ajax({ + url: url, + method: 'POST', + success: function(data) { + console.log("AJAX Success:", data); // Log the response + $('#output').html(data); // Directly output the raw response data + }, + error: function(jqXHR, textStatus, errorThrown) { + console.error("AJAX Error:", textStatus, errorThrown); // Log error details + $('#output').html("Error: " + textStatus + " " + errorThrown); + } + }); + }); +}); + + + +</script> + + +</body> +</html> + diff --git a/Async-PHP/app/reuseable_views/header.php b/Async-PHP/app/reuseable_views/header.php new file mode 100644 index 0000000..e05e381 --- /dev/null +++ b/Async-PHP/app/reuseable_views/header.php @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title><?php echo isset($pageTitle) ? $pageTitle : 'Default Title'; ?></title> + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> + <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> +</head> +<body class="container"> + diff --git a/Async-PHP/app/template.php b/Async-PHP/app/template.php new file mode 100644 index 0000000..72236e5 --- /dev/null +++ b/Async-PHP/app/template.php @@ -0,0 +1,17 @@ +<?php +$pageTitle = 'Index'; // Set the page title +include 'reuseable_views/header.php'; ?> + + +<h1 class="mt-5">Logs</h1> +<button class="runScripts" class="btn btn-primary mb-3" data-url="../Backend/template.php">Run Scripts</button> +<h2>Script Outputs:</h2> +<div id="output" class="bg-light p-3"></div> + + + +<?php include 'reuseable_views/footer.php'; ?> + + + + diff --git a/Async-PHP/async_scripts/db_connect.php b/Async-PHP/async_scripts/db_connect.php new file mode 100644 index 0000000..a38108f --- /dev/null +++ b/Async-PHP/async_scripts/db_connect.php @@ -0,0 +1,19 @@ +<?php +$servername = ""; +$username = ""; +$password = ""; +$dbname = ""; +$port = ; + +// Create connection +$conn = new mysqli($servername, $username, $password, $dbname, $port); + +// Check connection +if ($conn->connect_error) { + die("Connection failed: " . $conn->connect_error); + } + + + +?> + diff --git a/Async-PHP/css/style.php b/Async-PHP/css/style.php new file mode 100644 index 0000000..c5d2482 --- /dev/null +++ b/Async-PHP/css/style.php @@ -0,0 +1,80 @@ +<style> +/* styles.css */ +body { + display: flex; + transition: margin-left 0.3s; /* Smooth transition */ +} + +.sidebar { + width: 250px; /* Adjust the width of the sidebar */ + background-color: #f8f9fa; + padding: 15px; + box-shadow: 2px 0 5px rgba(0,0,0,0.1); + position: fixed; /* Fix sidebar position */ + height: 100vh; /* Full height */ + overflow-y: auto; /* Enable scrolling if needed */ + transition: transform 0.3s; /* Smooth transition for hiding */ +} + +.sidebar.hidden { + transform: translateX(-100%); /* Move sidebar out of view */ +} + +.main-content { + flex-grow: 1; + padding: 20px; + transition: margin-left 0.3s; /* Smooth transition for margin */ + margin-left: 250px; /* Default margin for sidebar */ +} + +.main-content.shifted { + margin-left: 0; /* Shift content when sidebar is hidden */ +} + +/* Responsive Design */ +@media (max-width: 768px) { + .sidebar { + width: 200px; /* Adjust sidebar width on mobile */ + } + .main-content { + margin-left: 0; /* No margin when sidebar is hidden on mobile */ + } +} + +.dropbtn { + background-color: #04AA6D; + color: white; + padding: 16px; + font-size: 16px; + border: none; +} + +.dropdown { + position: relative; + display: inline-block; +} + +.dropdown-content { + display: none; + position: absolute; + background-color: #f1f1f1; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; +} + +.dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; +} + +.dropdown-content a:hover {background-color: #ddd;} + +.dropdown:hover .dropdown-content {display: block;} + +.dropdown:hover .dropbtn {background-color: #3e8e41;} + +</style> + diff --git a/Async-PHP/index.php b/Async-PHP/index.php new file mode 100644 index 0000000..2890a0a --- /dev/null +++ b/Async-PHP/index.php @@ -0,0 +1,36 @@ +<?php include "router_links/links.php"; ?> + +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Router Example</title> + <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> + <?php include "css/style.php"; ?> +</head> +<body> + <!-- Sidebar Navigation --> + <div class="sidebar" id="sidebar"> + <h4>Navigation</h4> + + <button id="toggleSidebar" class="btn btn-primary">Toggle Sidebar</button> + <ul class="nav flex-column"> + <?php foreach ($pageNames as $key => $name): ?> + <li class="nav-item"> + <a class="nav-link" href="#/<?php echo $key; ?>"><?php echo $name; ?></a> + </li> + <?php endforeach; ?> + </ul> + </div> + + <!-- Main Content Area --> + <div id="app" class="main-content"> + <button id="showSidebar" class="btn btn-secondary" style="display: none;">Show Sidebar</button> + <router-view></router-view> + </div> + + <?php include "js/router_js.php"; ?> +</body> +</html> + diff --git a/Async-PHP/index1.php b/Async-PHP/index1.php new file mode 100644 index 0000000..651f330 --- /dev/null +++ b/Async-PHP/index1.php @@ -0,0 +1,57 @@ +<?php include "router_links/links.php"; ?> +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Router Example</title> + <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"> + <?php include "css/style.php"; ?> +</head> +<body> + + + <!-- Sidebar Navigation --> + <div class="sidebar" id="sidebar"> + <h4>Navigation</h4> + + <button id="toggleSidebar" class="btn btn-primary">Toggle Sidebar</button> + <ul class="nav flex-column"> + <!-- Manual Links --> + <li class="nav-item"> + <a class="nav-link" href="#/app/index">Index</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#/app/async_calculation.php">Async Calculation</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#/app/100_async_time.php">Insert 100 timestamps</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#/app/run_without_reload.php">Run Without Reload</a> + </li> + <li class="nav-item"> + <div class="dropdown"> + <button class="dropbtn">Dropdown</button> + <div class="dropdown-content"> + + <a class="dropdown-item" href="#/app/insert_user_form_template.php">Insert User</a> + <a class="dropdown-item" href="#/app/insert_product_form_template.php">Insert Product</a> + </div> + </div> + </li> + </ul> + </div> + + <!-- Main Content Area --> + <div id="app" class="main-content"> + <button id="showSidebar" class="btn btn-secondary" style="display: none;">Show Sidebar</button> + <router-view></router-view> + </div> + + + +<?php include "js/router_js.php"; ?> +</body> +</html> + diff --git a/Async-PHP/js/router_js.php b/Async-PHP/js/router_js.php new file mode 100644 index 0000000..8468da9 --- /dev/null +++ b/Async-PHP/js/router_js.php @@ -0,0 +1,126 @@ + <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> + <script src="https://cdn.jsdelivr.net/npm/vue-router@3"></script> + <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> + <script> + function createComponent(path) { + return { + template: `<div id="${path}-content"></div>`, + mounted() { + this.loadContent(); + }, + methods: { + loadContent() { + const paths = <?php echo json_encode($pagePaths); ?>; + const currentPath = paths[this.$route.path.substring(1)] || paths['index']; + + fetch(currentPath) + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok ' + response.statusText); + } + return response.text(); + }) + .then(data => { + document.getElementById(`${path}-content`).innerHTML = data; + }) + .catch(err => { + console.error(`Error fetching ${path}:`, err); + document.getElementById(`${path}-content`).innerHTML = 'Error fetching content.'; + }); + } + } + }; + } + const routes = Object.keys(<?php echo json_encode($pagePaths); ?>).map(key => ({ + path: `/${key}`, + component: createComponent(key) + })); + const router = new VueRouter({ + mode: 'hash', + routes + }); + const app = new Vue({ + el: '#app', + router, + mounted() { + this.initGlobalEvents(); + }, + methods: { + initGlobalEvents() { + // Global event delegation for form submissions and button clicks + document.addEventListener('click', (e) => { + if (e.target.matches('.runScripts')) { + e.preventDefault(); + const url = e.target.getAttribute('data-url'); + + if (e.target.closest('form')) { + const form = e.target.closest('form'); + const formData = new FormData(form); + + axios.post(url, formData) + .then(response => { + document.getElementById('output').innerHTML = response.data; + }) + .catch(err => { + document.getElementById('output').innerHTML = 'Error: ' + err.message; + }); + } else { + axios.post(url) + .then(response => { + document.getElementById('output').innerHTML = response.data; + }) + .catch(err => { + document.getElementById('output').innerHTML = 'Error: ' + err.message; + }); + } + } + }); + + // Global event for form submissions + document.addEventListener('submit', (e) => { + if (e.target.matches('form')) { + e.preventDefault(); + const url = e.target.querySelector('.runScripts').getAttribute('data-url'); + const formData = new FormData(e.target); + + axios.post(url, formData) + .then(response => { + document.getElementById('output').innerHTML = response.data; + }) + .catch(err => { + document.getElementById('output').innerHTML = 'Error: ' + err.message; + }); + } + }); + } + } + }); + </script> + +<script> + // JavaScript for sidebar toggle + const toggleButton = document.getElementById('toggleSidebar'); + const sidebar = document.getElementById('sidebar'); + const mainContent = document.getElementById('app'); + const showSidebarButton = document.getElementById('showSidebar'); + + toggleButton.addEventListener('click', function() { + sidebar.classList.toggle('hidden'); // Hide/Show sidebar + mainContent.classList.toggle('shifted'); // Shift main content + + // Show or hide the "Show Sidebar" button + if (sidebar.classList.contains('hidden')) { + showSidebarButton.style.display = 'block'; // Show button to bring back sidebar + } else { + showSidebarButton.style.display = 'none'; // Hide the button if sidebar is visible + } + }); + + showSidebarButton.addEventListener('click', function() { + sidebar.classList.remove('hidden'); // Show sidebar + mainContent.classList.remove('shifted'); // Reset main content position + showSidebarButton.style.display = 'none'; // Hide the button + }); + </script> + + diff --git a/Async-PHP/lib/AsyncRunner.php b/Async-PHP/lib/AsyncRunner.php new file mode 100644 index 0000000..6d29aac --- /dev/null +++ b/Async-PHP/lib/AsyncRunner.php @@ -0,0 +1,38 @@ +<?php +function runScriptsAsync(array $scripts) { + $descriptorspec = [ + 0 => ["pipe", "r"], // stdin + 1 => ["pipe", "w"], // stdout + 2 => ["pipe", "w"], // stderr + ]; + + $processes = []; + $pipes = []; + $outputs = []; + + // Start processes for each script + foreach ($scripts as $index => $script) { + $process = proc_open("php $script", $descriptorspec, $pipes[$index]); + if (is_resource($process)) { + $processes[$index] = $process; + } else { + echo "Failed to start $script\n"; + } + } + + // Optionally, you can read output + foreach ($pipes as $index => $pipe) { + $outputs[$index] = stream_get_contents($pipe[1]); + fclose($pipe[1]); // Close stdout + } + + // Close the processes when done + foreach ($processes as $index => $process) { + proc_close($process); + } + + // Return the outputs if needed + return $outputs; +} +?> + diff --git a/Async-PHP/router_links/links.php b/Async-PHP/router_links/links.php new file mode 100644 index 0000000..61ff142 --- /dev/null +++ b/Async-PHP/router_links/links.php @@ -0,0 +1,11 @@ +<?php +$pagePaths = [ + 'app/template' => 'app/template.php', + +]; + +$pageNames = [ + 'app/template' => 'Index', + +]; +?>