Jump to content

Strider64

Members
  • Posts

    466
  • Joined

  • Last visited

  • Days Won

    12

Posts posted by Strider64

  1. I personally like Active Record Pattern and I implement on my websites that I develop and design as it makes the job easier. The website goes up faster and lot less coding when all you have to do is transport the classes over and make a few minor modifications to the code. I didn't use a library and learn how to do ARP by watching a tutorial which is kind of ironic as the person who did the tutorial was using mysqli, but I like using PDO so I just switched it over to that. Active Record is good for small to medium size websites in my opinion and if I was building a large website I probably go with MVC or something like that.  The reason I don't use libraries is I like to code and see how it basically it is done at the native level when it comes to PHP and I don't use libraries like jQuery with JavaScript as I use plain Vanilla js. I see comments all the time that a person writes more code with Vanilla JavaScript, but I personally don't think it is all that much more code being written (other than the helper functions). Sorry getting off topic a little bit.

  2. I just want to point out that ids are great for buttons if you are changing a single button's appearance or you want a certain button to do a certain action. A good example is doing a trivia game as you can have each button be a possible answer.

    You would still use a class for general styling of the buttons and the id to personalize the button either in CSS or JavaScript (Which I did a lot in developing a trivia game).

     

    Here's an example:

                        <div id="questionBox">
                            <h2 id="question">What is the Question?</h2>
                            <button class="buttonStyle" id="ans1">Ans1</button>
                            <button class="buttonStyle" id="ans2">Ans2</button>
                            <button class="buttonStyle" id="ans3">Ans3</button>
                            <button class="buttonStyle" id="ans4">Ans4</button>
                        </div>

    Though I am using JavaScript to control the buttons.

    A small snippet -

        let q = document.querySelector('#question');
        let answer1 = document.querySelector('#ans1');
        let answer2 = document.querySelector('#ans2');
        let answer3 = document.querySelector('#ans3');
        let answer4 = document.querySelector('#ans4');
        let index = 0;
        let totalRecords = 0;
        let triviaData = null;
    
        const checkAnswer = () => {
    
        }
    
        const displayData = ({ans1, ans2, ans3, ans4, id, question}) => {
    
            console.log('trivia data', question);
    
            console.log(`The database table id is ${id}`)
            q["textContent"] = question;
            answer1["textContent"] = ans1;
            answer2["textContent"] = ans2;
            answer3["textContent"] = ans3;
            answer4["textContent"] = ans4;

    I am updating my online Trivia Game, but I just wanted to show that ids can be important to the <button></button> element.

     

    The CSS

            .buttonStyle {
                display: block;
                width: 100%;
                height: 3.125em;
                border: none;
                outline: none;
                cursor: pointer;
                background-color: #F5F5F5;
                font-family: 'Rubik', sans-serif;
                font-size: 1.2em;
                color: #2E2E2E;
                text-transform: capitalize;
                text-align: left;
                padding-left: 0.625em;
                margin: 0 auto;
            }

     

  3. I'll add my .02 cents to the discussion.

     

    What I like do is to design the web page first and if I know something is going to repeat itself (though it's also good for non-repeating code as well) then I just add the PHP to the HTML when I am coding it.

    As an example a blog or a page that will have more than one article to the page ->

        <?php
        foreach ($cms as $record) {
    
            echo '<header class="sectionHeader">';
            echo '<h2 class="sectionHeadingText">'. $record['heading'] . '</h2>';
            echo '</header>';
            echo '<article class="sectionArticle">';
            echo '<img class="imageArticle right-side" src="' . $record['image_path'] . '" alt="LEGO Bookstore">';
            echo '<p class="articleText">' . nl2br($record['content']). '</p>';
            echo ' </article>';
            echo '<footer class="sectionFooter">';
            echo '<p class="sectionText">Written by ' . $record['author'] . ' on ' . CMS::styleDate($record['date_added']) .' </p>';
            echo '</footer>';
        }
        ?>

    I would start off with straight HTML then add the PHP to the page. I personally like using echo as I can easily modify certain HTML elements easier, but that is just probably me. 😀

  4. Like already stated you don't store an array in a database table, but you can store the individual values as long as the correct key names (index names) in an array matching the tables columns.

    Here's an example:

     

    function insertData(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: (Normally not needed if it is NEW data)
                $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;
    }

     

  5. What I mean is the id field (Auto Increment) start at 1 and I have existing records that have an id of 130 lets say. I wrote new questions/answers and it started back at 1. So if I add more questions that get up to say 130 will the exist questioning be OVER WRITTEN 🙄If I get another rude reply I am going to delete this account and use other forums. You would think a person who didn't understand what I was writing would say could you clarify it and to top it all it's an administrator that made the reply.

  6. I have updated a online trivia game and used an old database table that has existing questions.  I was wondering if the new questions would overwrite existing questions because questions have been deleted in the past with this database table?

    Thanks in Advance,

          John

  7. 5 minutes ago, eaglehopes said:

    Thanks requinix for suggestion, but I read lots of comparisons between fetch vs. XMLHttpRequest pages, such as  https://blog.openreplay.com/ajax-battle-xmlhttprequest-vs-the-fetch-api. Implementing "timeout" and "readyState " and some other features that are "not easy" in fecth.  XMLHttpRequest suits better for my purposes and easier(while loading... etc.) to handle.

     found another page after your link requinix, about POST data using form data : https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects in my search.

     Then, I added fastly a hidden form into my html code and send formdata object and worked. My code to solve problem was : 

    <form name="hiddenForm"></form>
    <button type="button" id="buttonT1" onclick="getContent()">Get content</button>
    <div id="contentDiv" ></div>
    <script>
    async function loadPage(url,elementIdToInsert,postVarName, postVarValue) {
        var xhttp = new XMLHttpRequest();
      	xhttp.onreadystatechange = function() {
        switch(this.readyState ) {
          case 4 :
          if(this.status == 200) {
            document.getElementById(elementIdToInsert).innerHTML = this.responseText; // this here refers to xhttp object
            console.log("ok");
          } else { console.log("not ok! : "+this.status ); }
          break;
        } 
      };  // end of onreadystatechange 
      xhttp.open("POST", url, true); // open the file
      let formData = new FormData(document.forms.hiddenForm);
      formData.append(postVarName,postVarValue);
      xhttp.send( formData );  
    }
    
    function getContent() {
    	loadPage("./path/to/phpfile/scripts.php","contentDiv","foo","bar");
    }
    </script>

    and send data correctly to php script and I got it from $_POST['foo'].

    Thanks.

     

    Totally disagree as FETCH is very easy to implement and is very elegant in my opinion - However, every coder has a different style. 😉

        /* Handle General Errors in Fetch */
        const handleErrors = function (response) {
            if (!response.ok) {
                throw (response.status + ' : ' + response.statusText);
            }
            return response.json();
        };
    
    /* Success function utilizing FETCH */
        const quizUISuccess = (parsedData) => {
            console.log('trivia data', parsedData);
            mainGame.style.display = 'grid';
            d.getElementById('content').scrollIntoView();
    
            //gameData = parsedData;
    
    
            gameData = parsedData.sort(() => Math.random() - .5); // randomize questions:
            totalQuestions = parseInt(gameData.length);
            createQuiz(gameData[gameIndex]);
    
        };
    
        /* If Database Table fails to load then answer a few hard coded Q&A */
        const quizUIError = (error) => {
            /*
             * If game database table fails to load then give a few questions
             * and answers, so that the game will still work properly.
             */
            failed = true;
            mainGame.style.display = 'grid';
            d.getElementById('content').scrollIntoView();
            console.log("Database Table did not load", error);
            gameData = [{
                "id": 1,
                "user_id": 1,
                "hidden": "no",
                "question": "[Blank] is the length of time when the film or digital sensor inside the camera is exposed to light, also when a camera's shutter is open when taking a photograph. The amount of light that reaches the film or image sensor is proportional to the [Blank].",
                "category": "photography",
                "answers": [
                    "Shutter Speed or Exposure Time",
                    "ISO",
                    "",
                    ""
                ]
            },
                {
                    "id": 2,
                    "user_id": 1,
                    "hidden": "no",
                    "question": "[Blank] was one of the earliest photographers in American history, best known for his scenes of the Civil War. He studied under inventor Samuel F. B. Morse, who pioneered the daguerreotype technique in America. [Blank] opened his own studio in New York in 1844, and photographed Andrew Jackson, John Quincy Adams, and Abraham Lincoln, among other public figures.",
                    "category": "photography",
                    "answers": [
                        "Robert Capa",
                        "Steve McCurry",
                        "Ansel Adams",
                        "Matthew Brady"
                    ]
                }
            ]
            totalQuestions = gameData.length;
            //console.log(gameData[gameIndex]);
            createQuiz(gameData[gameIndex]);
        };
    
        /* create FETCH request */
        const createRequest = (url, succeed, fail) => {
            fetch(url)
                .then((response) => handleErrors(response))
                .then((data) => succeed(data))
                .catch((error) => fail(error));
        };

     

  8. People put too much into printing web pages.

    I created a simple blood pressure reading page (I'm trying to keep my blood pressure under control) and use simple CSS to print out the readings -

    A sample of the CSS:

    // Avoid page breaks straight after a heading.
    h1, h2, h3, h4, h5, h6
    {
      page-break-after: avoid;
    }
    
    
    /* Avoid page breaks inside paragraphs, blockquotes, lists, and preformatted
       text. */
    p, blockquote, ul, ol, dl, pre
    {
      page-break-inside: avoid;
    }
    
    @media print {
      header, footer {
        display: none;
      }
    }

    Here's the link to the page - https://www.phototechguru.com/print_bp.php

  9. I did an online tutorial and the following is the basically setup for promises for me as it explains it clearly for me.

    
        /* Create High Score Data using fetch */
        const createHSTable = (retrieveUrl, succeed, fail) => {
    
            let max = 5; // Maximum Records to Be Displayed
            let maximum = {};
            maximum.max_limit = max;
    
            fetch(retrieveUrl, {
                method: 'POST', // or 'PUT'
                body: JSON.stringify(maximum)
            })
                .then((response) => handleErrors(response))
                .then((data) => succeed(data))
                .catch((error) => fail(error));
        };
    
        createHSTable('retrieveHighScore.php', retrieveHSTableUISuccess, retrieveHSTableUIError);

    First it handles any errors

        /* Handle General Errors in Fetch */
        const handleErrors = function (response) {
            if (!response.ok) {
                throw (response.status + ' : ' + response.statusText);
            }
            return response.json();
        };

    Second it handles success

        /* retrieve User Data from hs_table */
        const retrieveHSTableUISuccess = function (info) {
            displayHSTable(info);
        };

    Lastly it handles failure 😔

        /* If Database Table fails to save data in mysql table */
        const retrieveHSTableUIError = function (error) {
            console.log("Database Table did not load", error);
        };

    A nice thing about failure is that you can have it where it doesn't actually fail (example database table not loading):

    Here's an example what I'm trying to say:

    
        /* If Database Table fails to load then answer a few hard coded Q&A */
        const quizUIError = (error) => {
            /*
             * If game database table fails to load then give a few questions
             * and answers, so that the game will still work properly.
             */
            failed = true;
            mainGame.style.display = 'grid';
            d.getElementById('content').scrollIntoView();
            console.log("Database Table did not load", error);
            gameData = [{
                "id": 1,
                "user_id": 1,
                "hidden": "no",
                "question": "[Blank] is the length of time when the film or digital sensor inside the camera is exposed to light, also when a camera's shutter is open when taking a photograph. The amount of light that reaches the film or image sensor is proportional to the [Blank].",
                "category": "photography",
                "answers": [
                    "Shutter Speed or Exposure Time",
                    "ISO",
                    "",
                    ""
                ]
            },
                {
                    "id": 2,
                    "user_id": 1,
                    "hidden": "no",
                    "question": "[Blank] was one of the earliest photographers in American history, best known for his scenes of the Civil War. He studied under inventor Samuel F. B. Morse, who pioneered the daguerreotype technique in America. [Blank] opened his own studio in New York in 1844, and photographed Andrew Jackson, John Quincy Adams, and Abraham Lincoln, among other public figures.",
                    "category": "photography",
                    "answers": [
                        "Robert Capa",
                        "Steve McCurry",
                        "Ansel Adams",
                        "Matthew Brady"
                    ]
                }
            ]
            totalQuestions = gameData.length;
            //console.log(gameData[gameIndex]);
            createQuiz(gameData[gameIndex]);
        };

     

    That's just my way of handling promises and there could be more promises (or less) it's just depends in what you're doing. I find commenting functions makes it easier when you have to look at the code in the future.


  10. I would also suggest keeping HTML and PHP separated as much as possible.

    Here's an example - have the HTML in the body of the page (Obviously)

    <formid="formData"class="checkStyle"action="create.php"method="post"enctype="multipart/form-data"><inputtype="hidden"name="cms[user_id]"value="3">
        <input type="hidden" name="cms[author]" value="<?=Login::full_name()?>">
        <inputtype="hidden"name="action"value="upload"><divclass="file-style"><inputid="file"class="file-input-style"type="file"name="image"><labelfor="file">Select file</label></div><label><selectclass="select-css"name="cms><optionvalue="index"selected>Home</option><optionvalue="blog">Blog</option><optionvalue="about">About</option></select></label><divclass="heading-style"><labelclass="heading_label_style"for="heading">Heading</label><inputclass="enter_input_style"id="heading"type="text"name="cms[heading]"value=""tabindex="1"requiredautofocus></div><divclass="content-style"><labelclass="text_label_style"for="content">Content</label><textareaclass="text_input_style"id="content"name="cms[content]"tabindex="2"></textarea></div><divclass="submit-button"><buttonclass="form-button"type="submit"name="submit"value="enter">submit</button></div></form>

    <?php
    require_once "../assets/config/config.php";
    require_once "../vendor/autoload.php";usePhotoTech\Login;usePhotoTech\CMS;Login::is_login($_SESSION['last_login']);Login::securityCheck();
    
    $save_result =false;if($_SERVER['REQUEST_METHOD']==='POST'){
        $data = $_POST['cms'];try{
            $today = $todayDate =newDateTime('today',newDateTimeZone("America/Detroit"));}catch(Exception $e){}
        $data['date_updated']= $data['date_added']= $today->format("Y-m-d H:i:s");
    
        $cms =new CMS($data);
        $result = $cms->create();if($result){
            header("Location: gallery.php");exit();}}?><!doctype html><htmllang="en">

    PHP at the top of the page (file)

  11. Heck I even learn something new reading these threads.

    Here's my Database Connection:

    <?php
    
    
    namespace PhotoTech;
    
    use mysql_xdevapi\Exception;
    use PDO;
    use PDOException;
    
    class Database {
    
        private PDO $_connection;
        // Store the single instance.
        private static ?Database $_instance = null; // Don't initialize before it is called:
    
        // Get an instance of the Database.
        // @return Database:
        protected static function getInstance(): Database
        {
            if (!self::$_instance) {
                self::$_instance = new self();
            }
            return self::$_instance;
        }
    
        public static function pdo(): PDO
        {
            $db = static::getInstance();
            return $db->getConnection();
        }
    
        // Constructor - Build the PDO Connection:
        private function __construct() {
            try {
            $db_options = [
                /* important! use actual prepared statements (default: emulate prepared statements) */
                PDO::ATTR_EMULATE_PREPARES => false
                /* throw exceptions on errors (default: stay silent) */
            , PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
                /* fetch associative arrays (default: mixed arrays)    */
            , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
            ];
            $this->_connection = new PDO('mysql:host=' . DATABASE_HOST . ';dbname=' . DATABASE_NAME . ';charset=utf8', DATABASE_USERNAME, DATABASE_PASSWORD, $db_options);
            } catch (PDOException $e) {
                //echo $e;
                //echo "<pre>" . print_r($e->errorInfo, 1) . "</pre>";
                if ($e->errorInfo[1] === 1045) {
                    echo "Can't Connect to Database " . $e->errorInfo[1] . "<br>";
                    return false;
                }
    
                throw $e; // If PDO Exception error can't handle it throw it to Exception:
    
            } catch (Exception $e) {
                echo 'Caught exception: ', $e->getMessage(), "\n"; // Not for a production server:
            }
            return true;
        }
    
        // Empty clone magic method to prevent duplication: *Probably Not Even Needed Now*
        private function __clone() {
    
        }
    
        // Get the PDO connection:
        protected function getConnection(): PDO
        {
            return $this->_connection;
        }
    
    }

    I think (not totally sure) that before the constructor had to be public and that is why the Empty Clone Magic had to be used?

     

    Just something extra to use this class all one has to do is

    $stmt = Database::pdo()->prepare($sql); // Prepare the query:

     

  12. Another way of doing pagination is to figure out the offset of the table meaning where you are at actually in the database table:

    $offset = $per_page * ($current_page - 1);
    $sql = 'SELECT * FROM myTable WHERE category =:category ORDER BY id DESC, date_added DESC LIMIT :perPage OFFSET :offset'; // Offset of the table
            $stmt = Database::pdo()->prepare($sql); // Prepare the query:
            $stmt->execute(['perPage' => $per_page, 'category' => $category, 'offset' => $offset]); // Execute the query with the supplied data:
            return $stmt->fetchAll(PDO::FETCH_ASSOC);

    total pages in this case would be the number of records in the category

    $total_pages = ceil($this->total_count / $this->per_page);

     

  13. 4 hours ago, benanamen said:

    @Strider64, you have been posting that insertData function in various forums for some time now. It doesn't work the way you think it does. HINT: Try passing in an array that has "id". 🙂

    You're right that shouldn't even be in there in the first place. That was part of the update function.  I just copy that part over to the insert function when I wrote that code as I never really tested it out as insert should never have an id it in the first place. Me bad. 🙄

  14. Thanks to the help here, I think I am on the right path with my pagination and selecting categories.  While I'm not done coding I believe this is a much better way of doing it than using sessions thanks to requinix.

    This is what I have here so far for the vanilla JavaScript:

    'use strict';
    (function () {
        let d = document;
        let category = d.querySelector('#category');
        let container = d.querySelector('.container');
        let sidebar = d.querySelector('.sidebar');
        let url = 'galleryImagesGet.php';
        let current_page = 1, per_page =6, offset = 0;
        let database_data = {'category':'general', 'current_page': current_page, 'per_page': per_page, 'total_count': 0, 'offset': offset };
        let pages = [{}];
        let total_pages = 0;
    
        const links = d.createElement('div');
        links.className = 'links';
        links.textContent = 'SIDEBAR';
        sidebar.appendChild(links);
    
        /* Handle General Errors in Fetch */
        const handleErrors = function (response) {
            if (!response.ok) {
                throw (response.status + ' : ' + response.statusText);
            }
            return response.json();
        };
    
        /*
         * FETCH for New Category
         */
        const categoryUISuccess = (parsedData) => {
            /* Remove Image For Screen (cleanup) */
            while (container.firstChild) {
                container.removeChild(container.firstChild)
            }
            console.log('parsed_data ', parsedData);
            console.log('pages', pages);
    
            let count = 0; // For different class names for size boxes in CSS
    
            parsedData.forEach(slide => {
                /* Main Image Slide Block */
                let displayDiv = d.createElement('div');
                /* Array of different size class names for CSS */
                let displayFormat = ["gallery-container w-4 h-2", 'gallery-container w-3 h-2', 'gallery-container w-4 h-2', 'gallery-container w-3 h-2', 'gallery-container w-3 h-2', 'gallery-container w-2 h-2', 'gallery-container h-2', 'gallery-container h-2', 'gallery-container w-2 h-2', 'gallery-container h-2', 'gallery-container w-2 h-2', 'gallery-container w-4 h-2',
                    "gallery-container w-4 h-2", 'gallery-container w-3 h-2', 'gallery-container w-4 h-2', 'gallery-container w-3 h-2', 'gallery-container w-3 h-2', 'gallery-container w-2 h-2', 'gallery-container h-2', 'gallery-container h-2', 'gallery-container w-2 h-2', 'gallery-container h-2', 'gallery-container w-2 h-2', 'gallery-container w-4 h-2'];
                displayDiv.className = `${displayFormat[count]}`; //Assign Class Names to Div:
                container.appendChild(displayDiv); //Append Child to Parent Div:
    
                /*
                 * Create div for indiviual images
                 */
                let galleryItem = d.createElement('div');
                galleryItem.classList.add('gallery-item');
                displayDiv.appendChild(galleryItem);
                /*
                 * Image div element
                 */
                let images = d.createElement('div');
                images.classList.add('images');
                galleryItem.appendChild(images);
                /*
                 * Image itself
                 */
                let galleryImage = d.createElement('img')
                //console.log(slide.image_path);
                galleryImage.src = slide.image_path;
                galleryImage.setAttribute('alt', slide.content); // Description of what image is about:
                /* Set EXIF info to data-exif attribute */
                galleryImage.setAttribute('data-exif', slide.Model + ' ' + slide.ExposureTime + ' ' + slide.Aperture + ' '
                    + slide.ISO + ' ' + slide.FocalLength);
                images.appendChild(galleryImage); // Append image to Image div element:
                /*
                 * Hidden Paragraph
                 */
                let paragraph = d.createElement('p');
                paragraph.classList.add('hideContent');
                paragraph.textContent = slide.content;
                images.appendChild(paragraph);
                /*
                 * Title Block
                 */
                let title = d.createElement('div');
                title.classList.add('title');
                galleryItem.appendChild(title);
                /*
                 * Heading 1
                 */
                let heading1 = d.createElement('h1');
                heading1.classList.add('pictureHeading');
                heading1.textContent = `${slide.heading[0].toUpperCase()}${slide.heading.slice(1)}`;
                title.appendChild(heading1);
                let titleSpan = d.createElement('span');
                titleSpan.classList.add('exifInfo');
                titleSpan.textContent = slide.Model;
                title.appendChild(titleSpan);
    
                count += 1;
            })
    
            /*
             * Create Lightbox for Large Image Display
             */
            const lightbox = document.createElement('div')
            lightbox.classList.add('lightbox');
    
            document.body.appendChild(lightbox);
            const images = document.querySelectorAll('img')
            console.log('images', images);
    
            images.forEach(image => {
                /* Add Event Listener to Images and setting css class to active */
                image.addEventListener('click', () => {
                    lightbox.classList.add('active');
                    document.querySelector('.content').style.display = 'none';
                    //document.querySelector('.pagination').style.display = 'none';
    
                    /*
                     * Create Image portion of LightBox
                     */
                    let galleryImage = document.createElement('img');
                    galleryImage.classList.add('galleryImage');
                    galleryImage.width = 800;
                    galleryImage.height = 534;
                    galleryImage.src = image.src // image path
                    //console.log(image.src);
    
                    /*
                     * Create EXIF portion of LightBox
                     */
                    let galleryExif = document.createElement('p');
                    galleryExif.classList.add('galleryExif');
                    galleryExif.textContent = image.getAttribute('data-exif');
    
                    /*
                     * Create Text portion of Lightbox
                     */
                    let nextSibling = image.nextElementSibling; // Grab the next sibling:
                    let galleryText = document.createElement('p');
                    galleryText.classList.add('galleryText');
                    //console.log(nextSibling.textContent);
                    //galleryText.textContent = nextSibling.textContent;
    
    
                    /* Remove Image For Screen (cleanup) */
                    while (lightbox.firstChild) {
                        lightbox.removeChild(lightbox.firstChild)
                    }
    
                    /* Add Image to Screen */
                    lightbox.appendChild(galleryImage);
    
                    /* Add EXIF to Screen */
                    lightbox.appendChild(galleryExif);
    
                    /* Add Content to Screen */
                    //lightbox.appendChild(galleryText);
    
    
                })
    
            })
    
            lightbox.addEventListener('click', () => {
                if (lightbox.hasChildNodes()) {
                    lightbox.classList.remove('active'); // Exit Lightbox by removing active css class
                    lightbox.classList.add('lightbox');
                    document.querySelector('.content').style.display = 'grid';
                    //document.querySelector('.pagination').style.display = 'flex';
                }
            })
        };
    
        const categoryUIError = (error) => {
            console.log("Database Table did not load", error);
        }
    
        const paginationUISuccess = (parsedData) => {
            console.log('parseData', parsedData);
            pages = [{}];
    
            database_data.total_count = parsedData.total_count;
            database_data.offset = parsedData.offset;
            total_pages = Math.ceil(database_data.total_count/database_data.per_page);
    
            console.log('Total Pages =', total_pages);
            for (let x = 0; x < total_pages; x++) {
                //pages[x].page = x+1;
                pages[x] = {page: x+1};
            }
            pages.forEach(link_page => {
                console.log('page', link_page);
                console.log('link', link_page.page);
    
            })
    
            createRequest('galleryImagesGet.php', categoryUISuccess, categoryUIError);
    
        };
    
        const paginationUIError = (error) => {
            console.log("Database Table did not load", error);
        }
        /* create FETCH request */
        const createRequest = (url, succeed, fail) => {
    
            //console.log(category.value);
            //console.log('database_data', database_data);
            fetch(url, {
                method: 'POST', // or 'PUT'
                body: JSON.stringify(database_data)
            })
                .then((response) => handleErrors(response))
                //.then(res => res.text())          // convert to plain text
                //.then(text => console.log(text))
                .then((data) => succeed(data))
                .catch((error) => fail(error));
        };
    
        category.addEventListener('change', () => {
            database_data.category = category.value;
            createRequest('galleryPagination.php', paginationUISuccess, paginationUIError);
    
        }, false);
    
       createRequest('galleryPagination.php', paginationUISuccess, paginationUIError);
    
    
    })();

    I like using post instead of get as I don't have to deal with pretty url's as I personally find them a pain. Now all I have to do is finish the links.

    Thanks again for the help

  15. 8 minutes ago, requinix said:

    "Session variables" isn't a language. The choice is not "session variables instead of PHP" or "session variables instead of Javascript". The choice isn't even "PHP or Javascript".

    The choice is "session variables or data in the request". As in you can decide to put page information into the session or you can put page information into the URL. And the latter is better.

    That what I was trying to get at when I said preloading the images (like Flicker, Facebook and other websites do) just didn't know the terminology. I am a photographer that I want to share my best photographs on my own website, but even then I will still have a lot of images. I know sessions isn't going to cut it, so putting it in the URL is better though I will need a way not to load all my images onto the website hence the pagination. I will figure it out, probably combing the both. The URL for the images and the data for the sessions? I know I can use REACT or other Frameworks/Libraries, but I like doing it from scratch. I like the challenge for the most part and I like coding when I'm not taking photographs.

  16. 21 minutes ago, requinix said:

    Is it me or are you doing pagination using session variables?

    Well, I originally had pagination done in PHP, but I am in the process of converting it over to JavaScript. I'm more of a PHP person, but I like the fact Vanilla JavaScript doesn't reload the page. I was thinking of doing the links still in PHP, but I'm going to get around to doing it JavaScript. I was was thinking of just using sessions variables as a temporary fix, but if it cause this much of headache I probably just do it in Vanilla JS. Though I  hate the thoughts of doing the links in JavaScript. 🤔🤣 I know there is way of preloading a certain amount of images  in JavaScript which would be an idea solution, but I don't know how to go about to do it?

  17. 1 hour ago, Barand said:

    That above section of code is totally FUBAR

    • You test the value of $cat['category'] and afterwards decide to see if it is set!
    • Then having found it isn't set, you allocate this non-existant variable value to $_SESSION['category'].

    Yes, It is after monkeying around with it for almost a day I simplified things and came up with this - I still think it can be better.

    $data = [];
    /*
     * The below must be used in order for the json to be decoded properly.
     */
    try {
        $data = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
    } catch (JsonException $e) {
    }
    
    //echo "<pre>" . print_r($data['category'], 1) . "</pre>";
    //die();
    
    if (isset($_SESSION['category']) && $data['category'] === $_SESSION['category']) {
        $_SESSION['current_page'] += 1;
    }  else {
        unset($_SESSION['category']); // This probably isn't even needed? 
        $_SESSION['category'] = $data['category'];
        $_SESSION['current_page'] = 1;
    }

    I will find out when I have more images or have less per page and have my links working in JavaScript (Which I probably should break this down even further?).

     

    Thanks John

  18. 40 minutes ago, requinix said:

    The error message is telling you that the first character in the "JSON" is a less-than. You know, like the kind used by HTML?

    Doesn't that make you wonder what the "JSON" you expected to see, actually was?

    I am definitely going crazy as I know can't get it the database to load whereas before I could. Before this latest fiasco of mine I did what they said to do.

        /* create FETCH request */
        const createRequest = (url, succeed, fail) => {
            let cat = {category: category.value}
            cat.category = category.value;
            console.log(category.value);
            console.log('cat',cat);
            fetch(url, {
                method: 'POST', // or 'PUT'
                body: JSON.stringify(cat)
            })
                //.then((response) => handleErrors(response))
                .then(res => res.text())          // convert to plain text
                .then(text => console.log(text))
                .then((data) => succeed(data))
                .catch((error) => fail(error));
        };

    Now I get this gobbly  gook on all browsers

    <br />
    <b>Warning</b>:  Undefined array key "category" in <b>/homepages/11/d329291176/htdocs/phototech/galleryImagesGet.php</b> on line <b>19</b><br />
    [{"id":171,"user_id":2,"author":"John Pepp","page":"blog","category":"general","image_path":"assets\/uploads\/img-gallery-

    It's obvious that it's the first two lines of the mess. But how would I fix it? It used to work with it on Firefox, but I restarted my computer and now it say is doesn't load. Even though I did do a re-hard set time when I made modifications in Firefox, but at least Chrome is still giving me that error. So at least I am just semi-crazy.

     

    BTW - Thanks for helping

  19. I normally don't ask for help but this problem is driving me crazy.

    I'm using plain Vanilla JS and use FETCH to retrieve a bunch of information for my photo gallery . https://phototechguru.com/gallery.php

    It works fine in Firefox, but not Chrome or Safari. In the later two browsers I am getting this error message.

    Database Table did not load SyntaxError: Unexpected token < in JSON at position 0

    I will try to give the code I think that is important - here's some of the vanilla javascript

        /* create FETCH request */
        const createRequest = (url, succeed, fail) => {
            let cat = {}
            cat.category = category.value;
            console.log(category.value);
            console.log('cat',cat);
            fetch(url, {
                method: 'POST', // or 'PUT'
                body: JSON.stringify(cat)
            })
                .then((response) => handleErrors(response))
                .then((data) => succeed(data))
                .catch((error) => fail(error));
        };
    
        function selection(category) {
            /* Remove Image For Screen (cleanup) */
            while (container.firstChild) {
                container.removeChild(container.firstChild)
            }
    
    
            let url = 'galleryImagesGet.php';
            //let url =  urlRequest +  "category=" + category;
    
            createRequest(url, categoryUISuccess, categoryUIError);
        }
        category.addEventListener('change', () => { selection(category.value) } , false);
        category.value = 'general';
        createRequest('galleryImagesGet.php' , categoryUISuccess, categoryUIError);
    })();

    the galleryImagesGet.php

    <?php
    
    require_once 'assets/config/config.php';
    require_once "vendor/autoload.php";
    
    use PhotoTech\CMS;
    use PhotoTech\Pagination_New as Pagination;
    $cat = [];
    /* Makes it so we don't have to decode the json coming from javascript */
    header('Content-type: application/json');
    /*
     * The below must be used in order for the json to be decoded properly.
     */
    try {
        $cat = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
    } catch (JsonException $e) {
    }
    
    if ($cat['category'] === $_SESSION['category'] && isset($_SESSION['category'])) {
        $_SESSION['current_page'] + 1;
    } elseif (!isset($cat['category'])) {
        $_SESSION['category'] = $cat['category'];
        $_SESSION['current_page'] = 1;
    } else {
        $_SESSION['category'] = $cat['category'];
        $_SESSION['current_page'] = 1;
    }
    
    
    $per_page = 12; // Total number of records to be displayed:
    $total_count = CMS::countAllPage('blog', $_SESSION['category']); // Total Records in the db table:
    
    /* Send the 3 variables to the Pagination class to be processed */
    $pagination = new Pagination($_SESSION['current_page'], $per_page, $total_count);
    
    /* Grab the offset (page) location from using the offset method */
    $offset = $pagination->offset();
    
    /*
     * Grab the data from the CMS class method *static*
     * and put the data into an array variable.
     */
    $cms = CMS::page($per_page, $offset, 'blog', $_SESSION['category']);
    output($cms);
    
    function output($output): void
    {
        http_response_code(200);
        try {
            echo json_encode($output, JSON_THROW_ON_ERROR);
        } catch (JsonException) {
        }
    
    }

    I have tried Googling to find the solution and tried some of them, but I'm not to familiar with some of the terminology and I haven't gone too in-depth with the console for debugging. I can show more code if needed.  What's really puzzling is why will work in Firefox and not other browsers? 🤔 I don't know if this what put in the right forum category?

  20. /*
     * As long as you have the correct field names as the key and
     * the correct values in the corresponding keys the following
     * procedural function should work with no problem.
     *
     */
    
    
    function insertData(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) {
    
            /*
             *
             * getCode() is the sqlstate
             *
             * echo "unique index" . $e->errorInfo[1] . "<br>";
             *
             * An error has occurred if the error number is for something that
             * this code is designed to handle, i.e. a duplicate index, handle it
             * by telling the user what was wrong with the data they submitted
             * failure due to a specific error number that can be recovered
             * from by the visitor submitting a different value
             *
             * return false;
             *
             * else the error is for something else, either due to a
             * programming mistake or not validating input data properly,
             * that the visitor cannot do anything about or needs to know about
             *
             * throw $e;
             *
             * re-throw the exception and let the next higher exception
             * handler, php in this case, catch and handle it
             */
    
            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;
    }

    Here's a detailed explanation of catching a duplicate username. Someone explained to me a long time ago that this was the proper way to catch duplicates especially if your website has a lot of traffic on it. You could do the following to check if a username already exists, BUT it doesn't prevent duplicates as two people could be entering the exact username at the same time.  Sorry it's part of a Class, but this is just use as a courtesy to whoever is registering as the odds entering at the same username at the same time is not that great. 

     

    
        public static function usernameCheck($username): array
        {
    
    
            if (isset(static::$table)) {
                $query = "SELECT username FROM " . static::$table ." WHERE username = :username";
            }
            $stmt = Database::pdo()->prepare($query);
            $stmt->bindParam(':username', $username);
            $stmt->execute();
            if ($stmt->fetch(PDO::FETCH_ASSOC)) {
                $data['check'] = true;
                return $data;
            }
    
            $data['check'] = false;
            return $data;
    
    
        }

     

  21. 57 minutes ago, kicken said:

    If you catch the error then whatever value you return from the .catch method will be passed to your .then method as response.  Since you're not returning anything, response is undefined.

    You can either check that response has a value (like I did in the example) or return a mock response object with .ok set to false.

    function requests(url) {
       return fetch(url).catch(function(error) {
         console.log("caught error: "+error);
         return {ok: false};
       })
       .then(function(response) {
          if (!response.ok) {
            throw new Error(`Request failed with status ${response.status}`);
          }         
          return response.json();
       });
    }

     

    but if you handle errors first

        /* Handle General Errors in Fetch */
        const handleErrors = function (response) {
            if (!response.ok) {
                throw (response.status + ' : ' + response.statusText);
            }
            return response.json();
        };

    and do this

       /* create FETCH request */
        const createRequest = (url, succeed, fail) => {
            fetch(url)
                .then((response) => handleErrors(response)) // Check for errors
                .then((data) => succeed(data))
                .catch((error) => fail(error)); // Catch the errors
        };

    aren't you do the same thing with promises ?  Fetch to me can be confusing.

  22. Why not catch the "error"?

        /* Handle General Errors in Fetch */
        const handleErrors = function (response) {
            if (!response.ok) {
                throw (response.status + ' : ' + response.statusText);
            }
            return response.json();
        };
    
        /* Success function utilizing FETCH */
        const UISuccess = function (parsedData) {
            /* Successfully Load & No Errors */
        };
    
        /* If Database Table fails to load then hard code */
        const UIError = function (error) {
    
            console.log("Database Table did not load", error);
            
            /* Do Something like even run more code? */
    
        };
    
       /* create FETCH request */
        const createRequest = (url, succeed, fail) => {
            fetch(url)
                .then((response) => handleErrors(response))
                .then((data) => succeed(data))
                .catch((error) => fail(error));
        };
    
    	createRequest(url, UISuccess, UIError);

     

×
×
  • 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.