Jump to content

Strider64

Members
  • Posts

    470
  • Joined

  • Last visited

  • Days Won

    12

Posts posted by Strider64

  1. All you need is the `username` and `password` to get the user's credentials and you really should just store the `id` or `username` in sessions as you can pull the other information of the user when you need it from the database table. 

    and example of my login ->

        public function verify_credentials($username, $password): bool
        {
            $sql = "SELECT id, password FROM admins WHERE username =:username LIMIT 1";
            $user = $this->retrieve_credentials($sql, $username);
            if ($user && password_verify($password, $user['password'])) {
                session_regenerate_id(); // prevent session fixation attacks
                $_SESSION['user_id'] = $user['id'];
                return true;
            }
    
            return false;
        }
    
        protected function retrieve_credentials(string $sql, string $username): ?array
        {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute(['username' => $username]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result !== false ? $result : null;
        }

    It's a method part of a class that I wrote, but basically it's a function and could easily be written in procedural style. This is just an example. 

  2. I would suggest using Intervention Library as it makes handling images so much easier.

    I use the following for my own website ->

    <?php
    // Include the configuration file and autoload file from the composer.
    require_once __DIR__ . '/../config/clearwebconfig.php';
    require_once "vendor/autoload.php";
    use Intervention\Image\ImageManagerStatic as Image;
    // Import the ErrorHandler and Database classes from the clearwebconcepts namespace.
    use clearwebconcepts\{
        ErrorHandler,
        Database,
        ImageContentManager,
        LoginRepository as Login
    };
    
    $errorHandler = new ErrorHandler();
    
    // Register the exception handler method
    set_exception_handler([$errorHandler, 'handleException']);
    
    $database = new Database();
    $pdo = $database->createPDO();
    $checkStatus = new Login($pdo);
    
    // To check for either 'member' or 'sysop'
    if ($checkStatus->check_security_level(['sysop'])) {
        // Grant access
    } else {
        // Access denied
        header('location: dashboard.php');
        exit();
    }
    
    function is_ajax_request(): bool
    {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
    }
    
    
    $save_result = false;
    
    if (($_SERVER['REQUEST_METHOD'] === 'POST') && isset($_FILES['image'])) {
        $data = $_POST['cms'];
        $data['content'] = trim($data['content']);
        $errors = array();
        $exif_data = [];
        $file_name = $_FILES['image']['name']; // Temporary file:
        $file_size = $_FILES['image']['size'];
        $file_tmp = $_FILES['image']['tmp_name'];
        $thumb_tmp = $_FILES['image']['tmp_name'];
        $file_type = $_FILES['image']['type'];
        $file_ext = strtolower(pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION));
    
    
        /*
         * Set EXIF data info of image for database table that is
         * if it contains the info otherwise set to null.
         */
        if ($file_ext === 'jpeg' || $file_ext === 'jpg') {
    
            $exif_data = exif_read_data($file_tmp);
    
    
            if (array_key_exists('Make', $exif_data) && array_key_exists('Model', $exif_data)) {
                $data['Model'] = $exif_data['Make'] . ' ' . $exif_data['Model'];
            }
    
            if (array_key_exists('ExposureTime', $exif_data)) {
                $data['ExposureTime'] = $exif_data['ExposureTime'] . "s";
            }
    
            if (array_key_exists('ApertureFNumber', $exif_data['COMPUTED'])) {
                $data['Aperture'] = $exif_data['COMPUTED']['ApertureFNumber'];
            }
    
            if (array_key_exists('ISOSpeedRatings', $exif_data)) {
                $data['ISO'] = "ISO " . $exif_data['ISOSpeedRatings'];
            }
    
            if (array_key_exists('FocalLengthIn35mmFilm', $exif_data)) {
                $data['FocalLength'] = $exif_data['FocalLengthIn35mmFilm'] . "mm";
            }
    
        } else {
            $data['Model'] = null;
            $data['ExposureTime'] = null;
            $data['Aperture'] = null;
            $data['ISO'] = null;
            $data['FocalLength'] = null;
        }
    
        $data['content'] = trim($data['content']);
    
        $extensions = array("jpeg", "jpg", "png");
    
        if (in_array($file_ext, $extensions, true) === false) {
            $errors[] = "extension not allowed, please choose a JPEG or PNG file.";
        }
    
        if ($file_size >= 58720256) {
            $errors[] = 'File size must be less than or equal to 42 MB';
        }
    
        /*
         * Create unique name for image.
         */
        $image_random_string = bin2hex(random_bytes(16));
        $image_path = 'assets/image_path/img-entry-' . $image_random_string . '-2048x1365' . '.' . $file_ext;
        $thumb_path = 'assets/thumb_path/thumb-entry-' . $image_random_string . '-600x400' . '.' . $file_ext;
    
    
        move_uploaded_file($file_tmp, $image_path);
        move_uploaded_file($thumb_tmp, $thumb_path);
    
    
        // Load the image
        $image = Image::make($image_path);
    
        // Resize the image
        $image->resize(2048, 1365, function ($constraint) {
            $constraint->aspectRatio();
            $constraint->upsize();
        });
    
        // Save the new image
        $image->save($image_path, 100);
    
        // Load the image with Intervention Image
        $image = Image::make($image_path);
    
        // Resize the image while maintaining the aspect ratio
        $image->resize(600, 400, function ($constraint) {
            $constraint->aspectRatio();
            $constraint->upsize();
        });
    
        // Save the thumbnail
        $image->save($thumb_path, 100);
    
    
        $data['image_path'] = $image_path;
        $data['thumb_path'] = $thumb_path;
    
    
        /*
         * If no errors save ALL the information to the
         * database table.
         */
        if (empty($errors) === true) {
            // Save to Database Table CMS
            $timezone = new DateTimeZone('America/Detroit'); // Use your timezone here
            $today = new DateTime('now', $timezone);
            $data['date_updated'] = $data['date_added'] = $today->format("Y-m-d H:i:s");
            $cms = new ImageContentManager($pdo, $data);
            $result = $cms->create();
    
            if ($result) {
                header('Content-Type: application/json');
                echo json_encode(['status' => 'success']);
                exit();
            }
        } else {
            if (is_ajax_request()) {
                // Send a JSON response with errors for AJAX requests
                header('Content-Type: application/json');
                echo json_encode(['status' => 'error', 'errors' => $errors]);
            }
        }
    
    }

    I log my errors to a log file that I can only see and a person needs to be login to my website even to upload a file.

    Maybe the above can you help you out a little. Just remember nothing is full proof, but you should make the code as tight as possible.

  3. If you are trying to enter data, but you don't know exactly how many fields (columns) you are going to be saving to the table then you could do something like the following. Though would still need the correct table's column names and the corresponding data that goes with it. Here's an example ->

    function create(array $data, $pdo, $table) {
        try {
            /* Initialize an array */
            $attribute_pairs = [];
    
            /*
             * Set up the query using prepared states with the values of the array matching
             * the corresponding keys in the array
             * and the array keys being the prepared named placeholders.
             */
            $sql = 'INSERT INTO ' . $table . ' (' . implode(", ", array_keys($data)) . ')';
            $sql .= ' VALUES ( :' . implode(', :', array_keys($data)) . ')';
    
            /*
             * Prepare the Database Table:
             */
            $stmt = $pdo->prepare($sql);
    
            /*
             * Grab the corresponding values in order to
             * insert them into the table when the script
             * is executed.
             */
            foreach ($data as $key => $value)
            {
                if($key === 'id') { continue; } // Don't include the id:
                $attribute_pairs[] = $value; // Assign it to an array:
            }
    
            return $stmt->execute($attribute_pairs); // Execute and send boolean true:
    
        } catch (PDOException $e) {
    
            if ($e->errorInfo[1] === 1062) {
                return false;
            }
    
            throw $e;
        } catch (Exception $e) {
            echo 'Caught exception: ', $e->getMessage(), "\n"; // Not for a production server:
        }
    
        return true;
    }

     

  4. Here's a countdown clock that I did years ago, but I recently updated it a couple of months ago.

    countdown.js file

    "use strict";
    
    /**
     * Calculates the time remaining until a specified end time.
     * @param {string} endtime - The end time in a format parseable by Date.parse.
     * @returns {object} An object containing the total milliseconds and the breakdown in days, hours, minutes, and seconds.
     */
    const getTimeRemaining = (endtime) => {
        const total = Date.parse(endtime) - Date.now();  // Calculate the difference in milliseconds from now to the end time
        return {
            total,
            days: Math.floor(total / (1000 * 60 * 60 * 24)), // Convert milliseconds to days
            hours: Math.floor((total / (1000 * 60 * 60)) % 24), // Convert milliseconds to hours, modulo 24
            minutes: Math.floor((total / 1000 / 60) % 60), // Convert milliseconds to minutes, modulo 60
            seconds: Math.floor((total / 1000) % 60) // Convert milliseconds to seconds, modulo 60
        };
    };
    
    /**
     * Initializes a countdown clock on the webpage.
     * @param {string} id - The ID suffix of the countdown clock container.
     * @param {Date} endtime - The countdown end time.
     */
    const initializeClock = (id, endtime) => {
        const clock = document.getElementById(`display_clock${id}`); // Access the clock element by ID
        if (!clock) {
            console.error(`Clock with id 'display_clock${id}' not found.`);
            return; // Exit if no element is found
        }
    
        // Map each time unit to its corresponding DOM element within the clock container
        const fields = ['days', 'hours', 'minutes', 'seconds'].map(field =>
            clock.querySelector(`.${field}`)
        );
    
        if (fields.some(element => element === null)) { // Check if any elements are missing
            console.error('One or more clock elements not found:', fields);
            return; // Exit if missing elements are found
        }
    
        // Updates the countdown clock display every second
        const updateClock = () => {
            const { total, days, hours, minutes, seconds } = getTimeRemaining(endtime);
    
            // Update each field in the DOM with the new time
            [days, hours, minutes, seconds].forEach((val, i) => {
                fields[i].textContent = String(val).padStart(2, '0'); // Format with leading zeros
            });
    
            if (total <= 0) {
                clock.textContent = "Contest Finished, entry time expired";
                clearInterval(timeInterval); // Stop the timer if the countdown is complete
            }
        };
    
        updateClock();
        const timeInterval = setInterval(updateClock, 1000); // Set the timer to update every second
    };
    
    /**
     * Fetches the countdown data and initializes the clock using that data.
     */
    const fetchRoutine = () => {
        fetch('data.json') // Fetch the countdown data from a local JSON file
            .then(response => response.json())
            .then(data => {
                document.getElementById("countdown_date").textContent = data.date_format; // Set the formatted date
                document.getElementById("display_title").textContent = data.title; // Set the event title
                initializeClock(1, new Date(Date.parse(data.time_left))); // Initialize the clock with the fetched data
            })
            .catch(error => {
                console.error('Fetch error:', error); // Log any errors during fetch
            });
    };
    
    // Ensure all DOM content is loaded before executing the fetch routine.
    document.addEventListener('DOMContentLoaded', fetchRoutine);

    it pulls in data from data.json file

    {
      "time_left": "2024-08-27T11:59:59-04:00",
      "date_format": "Tuesday - August 28, 2024",
      "title": "Countdown to "
    }

    here is the HTML file:

    <!DOCTYPE html>
    
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Countdown Clock</title>
        <link rel="stylesheet" href="reset.css">
        <link rel="stylesheet" href="countdown.css">
    </head>
    <body>
    
    <div class="info">
        <h1 id="display_title"></h1>
        <h2 id="countdown_date"></h2>
    </div>
    <div id="display_clock1">
        <figure class="box">
            <div class="days"></div>
            <figcaption>Days</figcaption>
        </figure>
        <figure class="box">
            <div class="hours"></div>
            <figcaption>Hours</figcaption>
        </figure>
        <figure class="box">
            <div class="minutes"></div>
            <figcaption>Minutes</figcaption>
        </figure>
        <figure class="box">
            <div class="seconds"></div>
            <figcaption>Seconds</figcaption>
        </figure>
    </div>
    
    <script src="countdown.js"></script>
    
    </body>
    </html>

    and even the css file countdown.css

    *{
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
    }
    
    div.info {
        display: block;
        width: 100%;
        max-width: 300px;
        height: auto;
        text-align: center;
        padding: 2px;
        margin: 10px auto;
    }
    
    div.info::after { content: ''; display: block; clear: both; }
    
    h1 {
        font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
        font-size: 1.2em;
        line-height: 1.5;
    }
    h2 {
        font-family: Arial, Helvetica, sans-serif;
        font-size: 1.0em;
        font-style: italic;
        font-weight: 300;
    }
    
    div#display_clock1 {
        display: block;
        width: 100%;
        max-width: 190px;
        height: auto;
        margin: 5px auto;
        background-color: pink;
    }
    div#display_clock1 figure.box {
        float: left;
        display: block;
        width: 100%;
        max-width: 40px;
        height: 70px;
        color: #fff;
        text-align: center;
        padding: 0;
        margin-left: 5px;
    }
    
    div#display_clock1 figure.box div {
        background-color: #2e2e2e;
        height: 50px;
        line-height: 50px;
    }
    
    div#display_clock1 figure.box figcaption {
        font-family: Arial, Helvetica, sans-serif;
    
        font-size: 0.6em;
        line-height: 20px;
        font-weight: bold;
        color: #000;
    }

    It's a simple countdown clock, but can be modify to enhance. I did check it out that it still runs properly. Fetching the clock can be modify to add even more countdown counters by the `id` in this example there is only 1.

  5. I didn't create a Model, but a trait though maybe it will give you some ideas?

    <?php
    // NavigationMenuTrait.php
    
    namespace clearwebconcepts;
    
    use function htmlspecialchars;
    use function hash_equals;
    
    trait NavigationMenuTrait
    {
        public function regular_navigation(): void
        {
            $navItems = [
                'Home' => 'index.php',
                'About' => 'about.php',
                'Puzzle' => 'puzzle.php',
                'Portfolio' => 'portfolio.php',
                'Contact' => 'contact.php'
            ];
    
            // Check if the user is logged in
            $isLoggedIn = isset($_COOKIE['login_token']) && isset($_SESSION['login_token']) && hash_equals($_SESSION['login_token'], $_COOKIE['login_token']);
    
            if ($isLoggedIn) {
                unset($navItems['Home']); // Remove 'Home' from the navigation menu
                // Add 'Dashboard' to the start of the navigation menu
                $navItems = array('Dashboard' => 'dashboard.php') + $navItems;
            } else {
                $navItems['Login'] = 'login.php'; // Add 'Login' to the navigation menu
            }
    
    
            $navLinks = [];
    
            foreach ($navItems as $title => $path) {
                $href = $this->generateHref($path);
                $safeTitle = htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
                $navLinks[] = "<a href=\"{$href}\">{$safeTitle}</a>";
            }
    
            // Check if the user is logged in
            if ($isLoggedIn) {
                $navLinks[] = '<a href="logout.php">Logout</a>'; // Add 'Logout' to the end of the navigation menu
            }
    
            echo implode('', $navLinks);
        }
    
        public function showAdminNavigation(): void
        {
            $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https://' : 'http://';
            $host = $_SERVER['HTTP_HOST'];
    
            // Define your base path here
            $base_path = ($host === 'localhost:8888') ? '/clearwebconcepts' : '';
    
            $base_url = $protocol . $host . $base_path;
    
            $adminItems = [
                'Create Entry' => $base_url . '/create_cms.php',
                'Edit Entry' => $base_url . '/edit_cms.php',
                'Add to Portfolio' => $base_url . '/new_portfolio.php',
                'Edit Portfolio Page' => $base_url . '/edit_portfolio.php',
                'Add Jigsaw' => $base_url . '/add_to_puzzle.php',
                'Edit Jigsaw' => $base_url . '/edit_puzzle.php',
                'Service Form' => $base_url . '/service_form.php'
            ];
    
            echo '<div class="admin-navigation">';
            foreach ($adminItems as $adminTitle => $adminPath) {
                $adminSafeTitle = htmlspecialchars($adminTitle, ENT_QUOTES, 'UTF-8');
                echo "<a href=\"{$adminPath}\">{$adminSafeTitle}</a>";
            }
            echo '</div>';
        }
    
    
        private function generateHref(string $path): string
        {
            $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https://' : 'http://';
            $host = $_SERVER['HTTP_HOST'];
    
            // Define your base path here
            $base_path = ($host === 'localhost:8888') ? '/clearwebconcepts' : '';
    
            $base_url = $protocol . $host . $base_path;
    
            // Build the URL first, then validate it
            $url = $base_url . '/' . $path;
            $sanitized_url = filter_var($url, FILTER_SANITIZE_URL);
            $valid_url = filter_var($sanitized_url, FILTER_VALIDATE_URL);
    
            if ($valid_url === false) {
                die('Invalid URL');
            }
    
            return $valid_url;
        }
    }

     

  6. I create a simple error log for my own use and it comes in handy in debugging without the user knowing about it. I even created a simple error handler to sort the errors.

    class ErrorHandler implements ErrorHandlerInterface
    {
        public function handleException(Throwable $e): void
        {
            if ($e instanceof PDOException) {
                error_log('PDO Error: ' . $e->getMessage());
            } elseif ($e instanceof JsonException) {
                error_log('JSON Error: ' . $e->getMessage());
            } else {
                error_log('General Error: ' . $e->getMessage());
            }
        }
    }

    and in my configuration file

    // Set the path for the error log file
    ini_set('error_log', __DIR__ . '/error_log/error_log_file.log');

    this is the most import. part errors isn't seen by the public.

  7. That sure seems like a strange way in doing pagination. In my opinion the data should be come from a database table and broken down to something like the following ->

    // Grab the current page the user is on
    if (isset($_GET['page']) && !empty($_GET['page'])) {
        $current_page = urldecode($_GET['page']);
    } else {
        $current_page = 1;
    }
    
    $per_page = 2; // Total number of records to be displayed:
    
    
    // Grab Total Pages
    $total_pages = $cms->total_pages($total_count, $per_page);
    
    
    /* Grab the offset (page) location from using the offset method */
    /* $per_page * ($current_page - 1) */
    $offset = $cms->offset($per_page, $current_page);
    
    // Figure out the Links that you want the display to look like
    $links = new Links($current_page, $per_page, $total_count, $category);
    
    // Finally grab the records that are actually going to be displayed on the page
    $records = $cms->page($per_page, $offset, 'cms', $category);

    that way all you have to do is format. the HTML using CSS ->

    <main class="main_container" itemprop="mainContentOfPage">
        <?php
        foreach ($records as $record) {
            $imagePath = htmlspecialchars($record['image_path'], ENT_QUOTES, 'UTF-8');
            $heading = htmlspecialchars($record['heading'], ENT_QUOTES, 'UTF-8');
            $content = htmlspecialchars($record['content'], ENT_QUOTES, 'UTF-8');
    
            echo '<div class="image-header">';
            echo '<img src="' . $imagePath . '" title="' . $heading . '" alt="' . $heading . '">';
            echo '</div>';
            echo '<h1>' . $heading . '</h1>';
            echo '<p>' . nl2br($content) . '</p>';
            echo '<br><hr><br>';
        }
        ?>
    </main>

    The above is just an example, but if you breakdown the HTML/Code in smaller sections it's easier to read & debug. There are a lot of good pagination tutorials online.

  8. First get the PDO connection out of the function as that will cause you nothing but headaches.

    Here's an example of a generic PDO connection ->

    <?php
    $host = '127.0.0.1'; // or your database host
    $db   = 'your_database_name';
    $user = 'your_database_username';
    $pass = 'your_database_password';
    $charset = 'utf8mb4';
    
    $dsn = "mysql:host=$host;dbname=$db;charset=$charset";
    $options = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    
    try {
        $pdo = new PDO($dsn, $user, $pass, $options);
        // Use $pdo to perform database operations
    } catch (\PDOException $e) {
        throw new \PDOException($e->getMessage(), (int)$e->getCode());
    }
    ?>

    I would put this in a configuration file maybe name it config.php file?

    My example would entail explaining OOP, so maybe someone else will do a better example for you. But here is how I do it ->

            $sql = "SELECT id, password FROM admins WHERE username =:username LIMIT 1";
            $user = $this->retrieve_credentials($sql, $username);
            if ($user && password_verify($password, $user['password'])) {
                session_regenerate_id(); // prevent session fixation attacks
                $_SESSION['user_id'] = $user['id'];
                return true;
            }
    
            return false;

    and little more code

        protected function retrieve_credentials(string $sql, string $username): ?array
        {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute(['username' => $username]);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result !== false ? $result : null;
        }

     

    • Like 1
  9. Studying design patterns such as MVC (Model-View-Controller) and Active Record Design has enhanced my understanding of Object-Oriented Programming (OOP). Although many prefer Model-View-Controller, I found Active Record Design more helpful in solidifying my grasp of OOP. One constant with OOP is that there's always something new to learn, and there's always someone with a deeper understanding of it.

    I believe that beginners often find the structure of Object-Oriented Programming (OOP) challenging. Here's an example from some code on my website to illustrate this. ->

        // Display Record(s) by Pagination
        public function page($perPage, $offset, $page = "index", $category = "general"): array
        {
            $sql = 'SELECT * FROM '. $this->table . ' WHERE page =:page AND category =:category ORDER BY id ASC, date_added DESC LIMIT :perPage OFFSET :blogOffset';
            $stmt = $this->pdo->prepare($sql); // Prepare the query:
            $stmt->execute(['page' => $page, 'perPage' => $perPage, 'category' => $category, 'blogOffset' => $offset]); // Execute the query with the supplied data:
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }

    Initially, I would mix up my code by writing `$sql` and `$this->sql`, which made things confusing for me. However, everyone has their unique journey in learning Object-Oriented Programming (OOP). By coding in this manner, I'm able to more clearly identify key OOP components, such as recognizing `$this->pdo` and understanding that `$stmt->fetchAll(PDO::FETCH_ASSOC)` is an example of object-oriented code.

  10. My approach would be to divide the content into three files, although it's feasible to combine everything into a single file. Nonetheless, I'd still make an effort to keep the code and HTML distinct and separate as much as possible.

    1. Client's search page - example clients.php (form to search)
    2. JavaScript file - example clients.js
    3. PHP search results file - example client_results.php

    Here's an example of what I'm trying to express:

    My HTML form (edit_cms.php):

        <div class="search-form-container">
            <form id="searchForm">
                <div class="input-group">
                    <label for="heading">Heading:</label>
                    <select class="select-css" id="heading" name="heading">
                        <option value="" disabled selected>Select Heading</option>
                        <?php
                        foreach ($records as $record) {
                            echo '<option value="' . $record['heading'] . '">' . $record['heading'] . '</option>';
                        }
                        ?>
                    </select>
                </div>
                <div class="input-group">
                    <label for="searchTerm">Search Product Content:</label>
                    <input type="text" placeholder="Search Content" id="searchTerm" class="input-field" autofocus required>
                </div>
                <button class="search_button" type="submit">Search</button>
            </form>
        </div>

    A little bit of my JavaScript code (edit_cms.js):

            async function displayRecord(searchTerm = null, selectedHeading = null) {
                const requestData = {};
                if(searchTerm !== null) requestData.searchTerm = searchTerm;
                if(selectedHeading !== null) requestData.heading = selectedHeading;
    
                try {
                    const response = await fetch("search_cms_records.php", {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify(requestData),
                    });
    
                    const data = await response.json();
                    console.log(data); // Add this line
                    if (data.message) {
                        resultInput.value = '';
                        resultInput.placeholder = data.message;
                    } else if (data.error) {
                        console.error(data.error);
                    } else {
                        const row = data[0];
                        console.log(row);
                        idInput.value = row.id;
                        image_for_edit_record.src = row.thumb_path;
                        image_for_edit_record.alt = row.heading;
                        category.value = row.category;
                        category.textContent = `${row.category.charAt(0).toUpperCase()}${row.category.slice(1)}`;
                        heading.value = row.heading;
                        content.value = row.content;
                        resizeTextarea(content);
                    }
                } catch (error) {
                    console.error("Error:", error);
                }
            }

    and my PHP file with a little bit of the code that gets the results (search_cms_records.php):
     

        // Get the request body and decode it as JSON.
        $request = json_decode(file_get_contents('php://input'), true);
    
        // Extract the search term and heading from the request, if they exist.
        $searchTerm = $request['searchTerm'] ?? null;
        $heading = $request['heading'] ?? null;
    
        // If a search term was provided, use a full-text search on the 'content' field.
        // Before this can work, you'll need to make sure your content column is indexed for full-text searching.
        // You can do this with the following SQL command:
        // Example:
        // ALTER TABLE cms ADD FULLTEXT(content);
        if($searchTerm !== null) {
            $sql = "SELECT * FROM cms WHERE MATCH(content) AGAINST(:searchTerm IN NATURAL LANGUAGE MODE) LIMIT 1";
            $stmt = $pdo->prepare($sql);
            $stmt->bindValue(':searchTerm', $searchTerm);
    
            // If a heading was provided, search for exact matches on the 'heading' field.
        } else if($heading !== null) {
            $sql = "SELECT * FROM cms WHERE heading = :heading LIMIT 1";
            $stmt = $pdo->prepare($sql);
            $stmt->bindValue(':heading', $heading);
    
            // If neither a search term nor a heading was provided, throw an exception.
        } else {
            throw new Exception("No valid search term or heading provided");
        }
    
        // Execute the prepared statement.
        $stmt->execute();
    
        // Fetch the results and handle them as needed.
        $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
    
        // If results were found, return them to the client as JSON.
        if ($results) {
            echo json_encode($results);
        } else {
            echo json_encode(['message' => 'No results found.']);
        }

    My argument is that debugging becomes simpler when most of the code is organized and separated as much as possible within its respective programming language.

  11. Instead of using `if` statements you should be using `functions`, plus PHP has a great way of doing pagination (The following is just an example of what I'm talking about) ->

        // Display Record(s) by Pagination
        public function page($perPage, $offset, $page = "index", $category = "general"): array
        {
            $sql = 'SELECT * FROM '. $this->table . ' WHERE page =:page AND category =:category ORDER BY id ASC, date_added DESC LIMIT :perPage OFFSET :blogOffset';
            $stmt = $this->pdo->prepare($sql); // Prepare the query:
            $stmt->execute(['page' => $page, 'perPage' => $perPage, 'category' => $category, 'blogOffset' => $offset]); // Execute the query with the supplied data:
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        }

    I would look into pagination tutorials as that will save you a lot headaches.

  12. You might want to check that your CSS is the same on both servers and that is correct. For example if you have `display:none;` the image won't show. 

    Ensure that the file permissions for the image are set correctly. The web server should have read access to the image file.

    If you're using an Apache web server, check your .htaccess file and server configuration for any rules that might be affecting image loading.

  13. I'd also point out that you aren't using prepared statements. I'd recommend learning PDO over mysqli. Additionally, you seem to rely heavily on sessions when ideally, only the user's ID should be stored in them and maybe a token.

  14. // Import the arrayOfObjects from the data module.
    const arrayOfObjects = require("./data");
    
    // Iterate through each object in the arrayOfObjects.
    for (const obj of arrayOfObjects) {
      // Log the id and name properties of the current object to the console.
      console.log(`ID: ${obj.id}, Name: ${obj.name}`);
    }

    For the data module that contains the array of objects:

    // Define an array of objects with properties id and name.
    const arrayOfObjects = [
      { "id": 1, "name": "bla bla" },       // Object with id 1 and name 'bla bla'
      { "id": 2, "name": "bla bla bla" }   // Object with id 2 and name 'bla bla bla'
    ];
    
    // Export the arrayOfObjects so it can be imported and used in other modules.
    module.exports = arrayOfObjects;

     

  15. 3 minutes ago, LeonLatex said:

    @mac_gyver, If you look in bottom of my first posting you find my login form. I dont have a registration form yet because so early in the development process i manually put the testing user accounts in mysql manually. I dont have time to use more time on this now, so i will start develop another system, and this time with email confirmation and a confirmation code. Is less use of time to put a new one together than looking for errors in this login system. I dont think there is only one error. The system has going through many changes through the last year, so it's time to let the old one rest. Any way, thanks for using time for trying to help 😃

    You don't need a registration form/page as all you have to do is hash your password that you want to use. That's what I do when I develop my website(s).

  16. You need to do something like this ->

            // Add an event listener to the edit form's submit event
            editForm.addEventListener("submit", async function (event) {
                // Prevent the default form submit behavior
                event.preventDefault();
    
                // Create a FormData object from the edit form
                const formData = new FormData(editForm);
                //console.log("form data", formData);
                // Send a POST request to the edit_update_blog.php endpoint with the form data
                const response = await fetch("edit_update_blog.php", {
                    method: "POST",
                    body: formData,
                });
    
                // Check if the request was successful
                if (response.ok) {
                    const result = await response.json();
                    console.log(result);
                    // If the response has a "success" property and its value is true, clear the form
                    if (result.success) {
                        resultInput.value = '';          // Clear the current value of the search input field
                        resultInput.placeholder = "New Search"; // Set the placeholder to `New Search`
                        image_for_edit_record.src = "";
                        image_for_edit_record.alt = "";
                        editForm.reset(); // Resetting the edit form
                        searchForm.reset(); // Resetting the search form
    
                        // Reset select box to default (first) option
                        const selectBox = document.querySelector('select[name="heading"]');
                        selectBox.selectedIndex = 0;
                    }
    
                } else {
                    console.error(
                        "Error submitting the form:",
                        response.status,
                        response.statusText
                    );
                    // Handle error response
                }
            });

    also using `console.log` helps in debugging, plus your `sql_connection.php` is expecting back json data back.

    • Great Answer 1
  17. 19 minutes ago, Adamhumbug said:

    Hi All,

    As i am trying to learn more and more i wanted to know if there was a way of looking at a raw fetchall() when running functions in php.

    I have a function call on my page which is set to var_dump the return.

    Is it possible to show the whole array on that page?

    Sure, I just do something like this

    echo "<pre>" . print_r($results, 1) . "</pre>";

    It's a great way to debug also.

  18. /* ----- Upload File / Image ----- */
    function uploadFile(uid) {
        const url = 'process.php';
        const form = document.querySelector('form');
        
        form.onsubmit = function(e) {
            e.preventDefault();
    
            const files = document.querySelector('[type=file]').files;
            const formData = new FormData();
    
            for (let i = 0; i < files.length; i++) {
                let file = files[i];
                formData.append('files[]', file);
                formData.append('uploadid', uid);
            }
    
            fetch(url, {
                method: 'POST',
                body: formData
            }).then(response => {
                return response.text();
            }).then(data => {
                console.log(data);
            });
        };
        
        return;
    }

    Instead of using the addEventListener method for the form submission, you can directly bind the function to the form's onsubmit?

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.