Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Strider64

  1. I would look into using Grids and/or Flexbox. I personally like grids and once you learn it then you find out how simple it can be in my opinion.
  2. You need three things for pagination to work : Current Page being displayed Total Count of Records The number of pages to be displayed Then you have to figure out the offset public function offset(): float|int { return $this->per_page * ($this->current_page - 1); } Sorry, that's as far as I can go as that looks like WordPress and that is something that I don't do, but I'm sure WP has some built-in features for pagination. Maybe someone else will be able to help you better?
  3. Personally, I just write functions that I try to do one thing and send it back to the main program. Here's an example of what I'm talking about $query = "SELECT username FROM " . static::$table ." WHERE username = :username"; $stmt = Database::pdo()->prepare($query); $stmt->execute(['username' => $username]); if ($stmt->fetch(PDO::FETCH_ASSOC)) { $data['check'] = true; return $data; } $data['check'] = false; return $data; I check the username against the database table then send and array back. Yes, I know it only has one index in the array, but then I can use that for other code like a validation array for example? This might help or it might not? I just find it easier not to have too many things going on at once.
  4. My suggestion is to find a good PHP tutorial and have error reporting turned on (which should be part of the tutorial). As for what you are trying to do try to keep it simple. TRY to keep most of the PHP on top and the HTML on the bottom of each page. Here's an example of what I mean and try to comment your coding as it will make sense later on when you go modify or help you out when you go work on it later on. Top /* * Set the class to of the record (data) to be display * to the class then fetch the data to the $record * ARRAY do be displayed on the website. If an * update has been done then update database * table otherwise just fetch the record * by id. */ if (isset($_POST['submit'])) { $cms = new CMS($_POST['cms']); $result = $cms->update(); $id = $_POST['cms']['id']; } elseif ($id && is_int($id)) { $record = CMS::fetch_by_id($id); $cms = new CMS($record); } else { header("Location: index.php"); exit(); } Bottom <form id="formData" class="form_classes" action="edit.php" method="post" enctype="multipart/form-data"> <input type="hidden" name="cms[id]" value="<?= $id ?>"> <input type="hidden" name="cms[user_id]" value="<?= $_SESSION['id'] ?>"> <input type="hidden" name="cms[author]" value="<?= Login::full_name() ?>"> <input type="hidden" name="cms[date_updated]" value="<?= $date_updated ?>"> <input type="hidden" name="action" value="upload"> <input class="form_image_upload_style" type="file" name="image"> <br><br> <label class="heading_label_style" for="heading">Heading</label> <input class="enter_input_style" id="heading" type="text" name="cms[heading]" value="<?= $cms->heading ?>" tabindex="1" required autofocus> <label class="text_label_style" for="content">Content</label> <textarea class="text_input_style" id="content" name="cms[content]" tabindex="2"><?= $cms->content ?></textarea> <button class="form_button" formaction="delete.php?id=<?= $id ?>" onclick="return confirm('Are you sure you want to delete this item?');">Delete</button> <button class="form_button" type="submit" name="submit" value="enter">submit</button> </form> Just my helpful addition to the conversation (I hope).
  5. Object-oriented Programming does add better security as you can make the code protected or private, but any code is hack-able. The biggest security threat is between the user and the website as you don't what the user might try. It can be like playing whack-a-mole with them at times. My best advice is never trying to write your own security code, by that I mean like not writing your own password algorithm. Let that be done by PHP internal security functions/methods or a TRUSTED 3rd-party source. Just my .02 cents.
  6. Another pattern you might want to look into is Active Record Design Pattern. That is what I use as it's database data driven and once the you get the insert, update and delete working it's basically just sending the right query or sql to the database. The view is usually another class. It's nice for a small website, but I wouldn't want to use it on a big project though it does lend itself to modifications more easily in my opinion and being a little more haphazard for people who like that aspect of coding. 😃 Though MVC does lend itself to better to structure than ARD and some people consider Active Record Design Pattern an anti-pattern. Though I disagree with that as if it was the case then you might as well stick to procedural coding in my opinion. Some more info -> https://en.wikipedia.org/wiki/Active_record_pattern
  7. Strider64

    New CMS

    I personally design the CMS first by that I mean I do a mock-up of what I visualize what the CMS is going to look like by creating a static HTML page with CSS. That way I know how it's going to look like and the setup of the PHP. Here's a visual description on what I'm trying to get at: (Obviously this is after the PHP being added) <?php foreach ($cms as $record) { ?> <article class="cms" itemscope itemtype="http://schema.org/Article"> <header itemprop="articleBody"> <div class="byline" itemprop="author publisher" itemscope itemtype="http://schema.org/Organization"> <img itemprop="image logo" class="logo" src="assets/images/img-logo-004.png" alt="website logo"> <h2 itemprop="headline" class="title"><?= $record['heading'] ?></h2> <span itemprop="name" class="author_style">Created by <?= $record['author'] ?> on <time itemprop="dateCreated datePublished" datetime="<?= htmlspecialchars(CMS::styleTime($record['date_added'])) ?>"><?= htmlspecialchars(CMS::styleDate($record['date_added'])) ?></time></span> </div> <img itemprop="image" class="article_image" src="<?php echo htmlspecialchars($record['image_path']); ?>" <?= getimagesize($record['image_path'])[3] ?> alt="article image"> </header> <p><?= nl2br($record['content']) ?></p> </article> <?php } ?> The main thing to take away from all of this is the naming of the variables as they are consistent to the database table: create table cms ( id int auto_increment primary key, user_id int null, author varchar(160) null, page varchar(255) default 'index' null, thumb_path varchar(255) null, image_path varchar(255) null, Model varchar(255) null, ExposureTime varchar(255) null, Aperture varchar(255) null, ISO varchar(255) null, FocalLength varchar(255) null, heading varchar(60) null, content text collate utf8_unicode_ci null, date_updated datetime null, date_added datetime null ); I would start off using procedural PHP when creating the first CMS and it still can be very robust. A lot of planning beforehand can save a lot of headaches later on. Didn't realize this was an old thread as I'm still waking up. 😁
  8. Yes sir. I did give this serious thought. I was able to make everything work by simply serializing $_POST data, and retrieving it when the $_GET request is made. But then I read about all the dangers and pitfalls of serializing $_POST (not to mention, doing so would be uncultured and uncivil). I made a list of pros and cons: mySQL Cons I am not very good at mySQL (writing the simplest prepared statement requires about 3 hours debugging afterwards) It's pretty easy writing PHP to access the MySQL database table. It just takes practice and actually writing the code. I have to worry that one day a visitor will decide to Post too much inventory data and my varchar(255) columns would be too small. (If I used "text" or "blob" I would be worried my table is taking too much unnecessary pace, greenhouse gases, etc.) Unless you are the size of Facebook, I don't think you have anything to worry about taking up space in a db table. If I knew mySQL as well as you do I'd have given full mySQL a shot. ...but I know my place. Find a good tutorial, practice coding and actually write the code. I didn't start off right away knowing how to code in PHP and everyone here has started off as a newbie. I didn't learn PHP until I was in my 50s and now I am not only able to access MySQL using PHP PDO, but can do the following: /* * This is the update that method that I came up with and * it does use named place holders. I have always found * updating was easier that creating/adding a record for * some strange reason? */ public function update(): bool { /* Initialize an array */ $attribute_pairs = []; /* Create the prepared statement string */ foreach (static::$params as $key => $value) { if($key === 'id') { continue; } // Don't include the id: $attribute_pairs[] = "{$key}=:{$key}"; // Assign it to an array: } /* * The query/sql implodes the prepared statement array in the proper format. */ $sql = 'UPDATE ' . static::$table . ' SET '; $sql .= implode(", ", $attribute_pairs) . ', date_updated=NOW() WHERE id =:id'; /* Normally in two lines, but you can daisy chain pdo method calls */ Database::pdo()->prepare($sql)->execute(static::$params); return true; } Commenting your code also help reinforcing what you have learned.
  9. The following simplifies this for me to understand.
  10. I personally like using the Fetch API as it's pretty straight forward and pretty darn easy to use (once you get the hang of coding it): Here's an example from my contact page: /* Success function utilizing FETCH */ const sendUISuccess = function (result) { //console.log('Result', result); if (result) { d.querySelector('#recaptcha').style.display = "none"; submit.style.display = "none"; notice.style.display = "grid"; notice.textContent = "Email Successfully Sent!"; notice.style.color = "green"; message.style.display = "grid"; d.querySelectorAll('form > *').forEach(function (a) { a.disabled = true; }); } }; /* If Database Table fails to update data in mysql table */ const sendUIError = function (error) { console.log("Database Table did not load", error); }; const handleSaveErrors = function (response) { if (!response.ok) { throw (response.status + ' : ' + response.statusText); } return response.json(); }; const saveRequest = (sendUrl, succeed, fail) => { fetch(sendUrl, { method: 'POST', // or 'PUT' body: JSON.stringify(sendEmail) }) .then((response) => handleSaveErrors(response)) .then((data) => succeed(data)) .catch((error) => fail(error)); };
  11. Do a echo "<pre>" . print_r($result, 1) . "</pre>"; die(); to see if you are getting any results.
  12. $pwd = password_hash($data['password'], PASSWORD_DEFAULT); unset($data['password']); try { $query = 'INSERT INTO users (fullName, username, status, password, security, email, date_added) VALUES (:fullName, :username, :status, :password, :security, :email, Now())'; $stmt = Database::pdo()->prepare($query); $result = $stmt->execute([':fullName' => $data['fullName'], ':username' => $data['username'], ':status' => $data['status'], ':password' => $this->pwd, ':security' => 'newuser', ':email' => $data['email']]); } catch (PDOException $e) { /* * 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: } If you really want to make sure there can be no duplicates then create an unique index for the username and throw an PDO exception if a duplicate is found. Though I think this would only be useful for a busy busy website.
  13. There's is a way check the "inside" of an image file $contents = file_get_contents($file['tmp_name']); $position = strpos($contents, '<?php'); return $position !== false; HOWEVER, it's a memory hog and doesn't work very good for large image files as you would need something more robust than the strpos() function. I personally don't allow image uploading other than myself who I trust. 😄
  14. To me that would be more ideal for a client side web app (like JavaScript) than a server-side app (PHP). They wouldn't have to use the back button at all and you could even use JavaScript, Ajax and PHP if you want to use a MySQL table. To give you an idea here is an example of a trivia game that I wrote for my website - https://www.miniaturephotographer.com/game.php I'm still developing it, but it works pretty darn good and you can do all sorts of things to it.
  15. You're not echoing out the content <h4><?php the_title(); ?> </h4> should be <h4><?php echo the_title(); ?> </h4> /* or this */ <h4><?= the_title() ?> </h4>
  16. e.preventDefault() will stop the HTML button from firing: submit.addEventListener('click', (e) => { e.preventDefault(); sendEmail.phone = phone.value; sendEmail.website = website.value; sendEmail.response = submit.getAttribute('data-response'); if (sendStatus.name && sendStatus.email && sendStatus.comments) { saveRequest(sendUrl, sendUISuccess, sendUIError); } else { notice.style.display = "block"; notice.textContent = "Name, Email, and Message Required!"; } }, false);
  17. If the code doesn't work, but the only solution is to use arrays then learning about arrays is probably only option? There's a reason why the code stopped working and that is you added extra conditions to the script. Instead of single images there are now multiple images? (I'm assuming and you know what they say about assuming. 😃) Learning arrays isn't that tough. It is one of the first things that is taught in any coding language.
  18. Well, it's not actually cropping, but resizing function that I wrote and I have been testing it out on my website. So far it's been working like I expect it to. Though I imagine you could modify the script to do cropping? <?php function imageResize($imageSrc, $imageWidth, $imageHeight, $newImageWidth, $newImageHeight): GdImage|bool { $newImageLayer = imagecreatetruecolor($newImageWidth, $newImageHeight); imagecopyresampled($newImageLayer, $imageSrc, 0, 0, 0, 0, $newImageWidth, $newImageHeight, $imageWidth, $imageHeight); return $newImageLayer; } function resize($file_temp, $new_file_name, $thumb = false): bool { $sourceProperties = getimagesize($file_temp); // Get image sizes: /* * Determine if it's a thumbnail or large image then * resize the images accordingly. */ $old_width = $sourceProperties[0]; $old_height = $sourceProperties[1]; $new_height = null; if ($thumb) { $new_width = 300; $newImageHeight = ($new_width * $old_height) / $old_width; $newImageWidth = $new_width; } else { $new_width = 1200; $newImageHeight = ($new_width * $old_height) / $old_width; $newImageWidth = $new_width; } $temp = '../' . $new_file_name; // folder is nested one down from root: $imageType = $sourceProperties[2];// Determine what type of image (png, jpg or gif): /* * Use Switch statement to resize the image and save it to the correct folders */ switch ($imageType) { case IMAGETYPE_PNG: $imageSrc = imagecreatefrompng($file_temp); $tmp = imageResize($imageSrc, $sourceProperties[0], $sourceProperties[1], $newImageWidth, $newImageHeight); imagepng($tmp, $temp); break; case IMAGETYPE_JPEG: $imageSrc = imagecreatefromjpeg($file_temp); $tmp = imageResize($imageSrc, $sourceProperties[0], $sourceProperties[1], $newImageWidth, $newImageHeight); imagejpeg($tmp, $temp); break; case IMAGETYPE_GIF: $imageSrc = imagecreatefromgif($file_temp); $tmp = imageResize($imageSrc, $sourceProperties[0], $sourceProperties[1], $newImageWidth, $newImageHeight); imagegif($tmp, $temp); break; default: echo "Invalid Image type."; exit; } return true; // Return true to signal that image was resized: }
  19. or you could simply have a small function of some kind to use a full name: function fullname($user) { return $user['firstname'] . " " . $user['lastname']; }
  20. If you are not using Fetch then you need to parse the data: var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var myObj = JSON.parse(this.responseText); document.getElementById("demo").innerHTML = myObj.name; } }; xmlhttp.open("GET", "json_demo.txt", true); xmlhttp.send();
  21. The methods/functions in the DbBox class to me is redundant unless you are going to override them, but like requinix stated "really, really, really vague question" to help with. I use the Active Record Design Pattern and those two classes would just be silly to me.
  22. Ooops read it wrong ..... please delete 😃
  23. 🤔 Hmm? Something tells me that isn't true. 🤥😔
  24. I have been updating my website to include the Active Response Design pattern using PHP pdo. I have most to the pdo done with a few minor refinements and improvements. If you want to get some ideas or inspiration check out my GitHub repository : https://github.com/Strider64/Miniature01282021 I know there's better out there, but it' not to bad for a person who is 56 that has only been programming in PHP the last 6-7 years (though I have previous coding experience in other languages).
  25. I would personally just do it silently with an unique constraint in MySQL and not advertising it too much to users. The more you broadcast it or let it be known that an username exists the more like they will attack your website. I'm not saying NOT to do it, but simply say "username can't be used at this time", "Choose a different username" or something more vague than that after the user attempts to registers. It's usually not that big of deal having to come up with a different username as you can save all the other registration info (except password) back on the HTML form as a convenience to the user. That's what I do.
  • 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.