Jump to content

Strider64

Members
  • Posts

    480
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by Strider64

  1. Another thing is PHP OOP is great with inheritance where a lot of that code to put it nicely could be streamline and some of the methods wouldn't even have to be used. Something to look into?
  2. Warning Do not use extract() on untrusted data, like user input (e.g. $_GET, $_FILES). This coming from https://www.php.net/manual/en/function.extract.php
  3. A good thing to have is a good IDE that will point out the common syntax errors and find good resources/tutorials online to help with the logic flow. As for Database Tables I like using PDO and I still go to the following online resource when I get stump or have a brain fart. https://phpdelusions.net/pdo 🤣 I go here and other forums to see if someone before me has had the same problem and if not I will attempt to ask a question while showing my work. I learn over the years not to show too little or way too much code. I find commenting code help not only me but the people helping me trying to solve my problem(s).
  4. From what I am see is that you are doing too much inside methods and even the classes. Keep methods simple as possible such as the following example: public static function page($perPage, $offset, $loc = 'index'): array { $sql = 'SELECT * FROM ' . static::$table . ' WHERE page=:page ORDER BY date_updated DESC LIMIT :perPage OFFSET :blogOffset'; $stmt = Database::pdo()->prepare($sql); // Prepare the query: $stmt->execute(['perPage' => $perPage, 'blogOffset' => $offset, 'page' => $loc]); // Execute the query with the supplied data: return $stmt->fetchAll(PDO::FETCH_ASSOC); } Classes can be inherited from a parent class or even another child class (However, I wouldn't go too deep) There are other ways of doing inheritance as well and some people frown on doing the way I do, but from what I do is small compared to larger development places. class CMS extends DatabaseObject { protected static string $table = "cms"; // Table Name: static protected array $db_columns = ['id', 'user_id', 'thumb_path', 'image_path', 'Model', 'ExposureTime', 'Aperture', 'ISO', 'FocalLength', 'author', 'heading', 'content', 'data_updated', 'date_added']; public $id; public $user_id; public $page; public $thumb_path; public $image_path; public $Model; public $ExposureTime; public $Aperture; public $ISO; public $FocalLength; public $author; public $heading; public $content; public $date_updated; public $date_added; /* * Create a short description of content and place a link button that I call 'more' at the end of the * shorten content. */ #[Pure] public static function intro($content = "", $count = 100): string { return substr($content, 0, $count) . "..."; } I do that with my PDO Database Connection that I call the Grandparent (called Database and I utilize it by doing Database::pdo() ). I go by the the K.I.S.S. (Keep It Simple Stupid) model as I find out that I write less code and can be used over and over again. I find myself (as I sure others do to) when I try to get fancy and write a bunch of code it leads to write more code with the class end up being longer than they should. Granted having a long class is sometimes unavoidable, but even them after you gain more knowledge of PHP can be streamline. I learn something new everyday in PHP coding (and other languages) and sometimes I slap myself why didn't I think of that. 🤣
  5. Actually using Fetch in Vanilla JavaScript is pretty easy to do: (Here's an example) /* 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"; //messageSuccess.style.display = "block"; 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)); }; though jQuery has jQuery.get() I believe which is the same thing as Fetch in Vanilla JavasScript which might be worth looking into? In my opinion it easier and coding is more logical. I like that you don't have to worry about parsing the data and handling errors is easy to do. In your case you could make a fallback option or tell the other player that the other person is no longer online.
  6. Why don't you just extend the child class? Does it work in the parent class? If it doesn't then there is something wrong with self::$conn You might be initializing the database connection before it is called?
  7. I would suggest using namespaces and an autoloader using composer. A good link in my opinion is this one - https://phpenthusiast.com/blog/how-to-autoload-with-composer and it really help me understand on how to do it. Then you simply can do this : <?php require_once 'assets/config/config.php'; // You still need your trusty configuration file require_once "vendor/autoload.php"; // Autoloader using composer use PhotoTech\CMS; use PhotoTech\Pagination; Here's my Database Class: <?php namespace PhotoTech; use PDO; 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: public function __construct() { $db_options = array( /* 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); } // Empty clone magic method to prevent duplication: private function __clone() { } // Get the PDO connection: protected function getConnection(): PDO { return $this->_connection; } } I have been using it for sometime without any problems and to use it I simply do the following class DatabaseObject // Extended by the children class: { static protected string $table = ""; // Overridden by the calling class: static protected array $db_columns = []; // Overridden by the calling class: static protected array $objects = []; static protected array $params = []; static protected $searchItem; static protected $searchValue; /* * There is NO read() method this fetch_all method * basically does the same thing. The query ($sql) * is done in the class the calls this method. */ public static function fetch_by_column_name($sql) { $stmt = Database::pdo()->prepare($sql); // Database::pdo() is the PDO Connection $stmt->execute([ static::$searchItem => static::$searchValue ]); return $stmt->fetch(PDO::FETCH_ASSOC); } // More coding... I should mention I am using PHP 8, so there might be some adjustment that might be needed? I also make comments that are sometime mental notes to me in order to know what I was doing. 😉
  8. Where static really shines is when you using an Active Record Design Pattern (I would assume other patterns are the same way, but this is the only pattern that I have used so far), for example: The Data Object Class class DatabaseObject // Extended by the children class: { static protected string $table = ""; // Overridden by the calling class: static protected array $db_columns = []; // Overridden by the calling class: static protected array $objects = []; static protected array $params = []; static protected $searchItem; static protected $searchValue; // More code.... A Children Class example class CMS extends DatabaseObject { protected static string $table = "cms"; // Table Name: static protected array $db_columns = ['id', 'user_id', 'thumb_path', 'image_path', 'Model', 'ExposureTime', 'Aperture', 'ISO', 'FocalLength', 'author', 'heading', 'content', 'data_updated', 'date_added']; // More Code....
  9. This deals with auto loading classes in php, but it should help you -> https://phpenthusiast.com/blog/how-to-autoload-with-composer or this which is probably more what you are looking for https://phpenthusiast.com/blog/how-to-use-packagist-and-composer A great resource for composer - https://getcomposer.org/ Composer has been around for awhile.
  10. /* if(isset($_GET['page'])) { $page = $_GET['page']; } else { $page = 1; } */ if ( isset($_GET['page']) ) { $current_page = $_GET['page']; } else { $current_page = 1; } $per_page = 20; // $num_per_page = 20; $offset = $per_page * ($current_page - 1) //$sql = "SELECT * FROM people ORDER BY id ASC LIMIT $start_from, $num_per_page"; $sql = 'SELECT * FROM people ORDER BY id ASC LIMIT ' . $per_page . ' OFFSET ' . $offset . '; I think this will work, but I'm just taking an educated guess. You are going to need know the total number of records, so that you don't go pass the total records in your database table using your previous and next links. HTH Helps? Though I do have pagination working on my own website - https://www.phototechguru.com/
  11. I would suggest to find a recent good online PHP tutorial or a recent PHP How-to-code book to get familiar with programming in that language.
  12. The best way to do that is to have a login to the secure area. Here's an example from my website - <?php require_once "../assets/config/config.php"; require_once "../vendor/autoload.php"; use PhotoTech\Resize; use PhotoTech\CMS; use PhotoTech\Login; Login::is_login($_SESSION['last_login']); Login::securityCheck(); and the class that check it: public function __construct($args = []) { static::$searchItem = 'username'; static::$searchValue = htmlspecialchars($args['username']); $this->password = htmlspecialchars($args['hashed_password']); } public static function username() { static::$searchItem = 'id'; static::$searchValue = $_SESSION['id']; $sql = "SELECT username FROM " . static::$table . " WHERE id = :id LIMIT 1"; $user = static::fetch_by_column_name($sql); return $user['username']; } public static function full_name(): string { static::$searchItem = 'id'; static::$searchValue = $_SESSION['id']; $sql = "SELECT first_name, last_name FROM " . static::$table . " WHERE id =:id LIMIT 1"; $user = static::fetch_by_column_name($sql); return $user['first_name'] . " " . $user['last_name']; } public static function securityCheck() { static::$searchItem = "id"; static::$searchValue = $_SESSION['id']; $sql = "SELECT security FROM " . static::$table . " WHERE id=:id LIMIT 1"; $result = static::fetch_by_column_name($sql); /* * Only Sysop privileges are allowed. */ if ($result['security'] !== 'sysop') { header("Location: ../game.php"); exit(); } } // more code..... It's my own personal website and I'm no security "expert", but I feel it pretty secure in what I do. Something like that will keep people from accessing those pages.
  13. $file_name = $_FILES['gambar']['name']; // Original File Name: $file_size = $_FILES['gambar']['size']; $file_tmp = $_FILES['gambar']['tmp_name']; // Temporary file for the directory: $file_type = $_FILES['gambar']['type']; $file_ext = strtolower(pathinfo($_FILES['gambar']['name'], PATHINFO_EXTENSION)); /* * Set the path to the correct folder */ $dir_path = 'folder/pda-semakan/gambar/'; /* * Create unique name for file. */ $new_file_name = $dir_path . 'file-example-' . time() . '.' . $file_ext; move_uploaded_file($file_tmp, $new_file_name); I didn't test this out, but you would do something like the above. Note $new_file_name would also store the path in the database table, so if you just want the just file then just out the $dir_path after saving the file to the directory.
  14. You can resolve a lot of those issues by using an autoloader (I use composer's autoloader) and namespaces. That way you can ensure there are no conflicts amongst your classes 99 percent of the time. Here's an example in what I'm talking about. <?php /** @noinspection ALL */ namespace PhotoTech; use Exception; use JetBrains\PhpStorm\Pure; use DateTime; use DateTimeZone; class CMS extends DatabaseObject { protected static string $table = "cms"; // Table Name: static protected array $db_columns = ['id', 'user_id', 'thumb_path', 'image_path', 'Model', 'ExposureTime', 'Aperture', 'ISO', 'FocalLength', 'author', 'heading', 'content', 'data_updated', 'date_added']; public $id; public $user_id; public $page; public $thumb_path; public $image_path; public $Model; public $ExposureTime; public $Aperture; public $ISO; public $FocalLength; public $author; public $heading; public $content; public $date_updated; public $date_added; <?php require_once 'assets/config/config.php'; require_once "vendor/autoload.php"; use PhotoTech\CMS; use PhotoTech\Pagination; /* * Using pagination in order to have a nice looking * website page. */ $current_page = $_GET['page'] ?? 1; $per_page = 2; // Total number of records to be displayed: $total_count = CMS::countAllPage('blog'); // Total Records in the db table: /* Send the 3 variables to the Pagination class to be processed */ $pagination = new Pagination($current_page, $per_page, $total_count); I'm not saying that's the issue, but it will save you a lot of headaches trying in having to rule out conflicts.
  15. Yeah I know, but wouldn't the file name have to be known if it is a hidden attribute?
  16. if ($_FILES['image']['size'] >= 44040192) { $errors[] = 'File size must be less than or equal to 42 MB'; } Simply check the file size and throw and throw an error if it is too big. I would also on the HTML page state the maximum file size allowed to upload. You could also try to compress the file, but that gets more involved.
  17. SwiftMailer is also another good one, I use it and it's very simple to use and has good community support: Just a small section of a small script /* create message */ $message = (new Swift_Message('A email from ' . $data['name'])) ->setFrom([$data['email'] => $data['name']]) ->setTo(['[email protected]']) ->setCc([$data['email'] => $data['name']]) ->setBody($data['message'], 'text/html') ->attach(entity: Swift_Attachment::fromPath('https://www.example.com/assets/images/img-logo-003.jpg'));
  18. Well, the path won't be "hidden" even if you get it to work properly as anyone can get the path by looking at the HTML once the image is displayed. That is if I am understanding you properly?
  19. require 'initializations.php'; if(isset($_POST['add_cat'])) { $cat_obj->add_category($_POST['cat_title']); header("Location: admin/category.php"); exit; } To me there should be some kind of check to see if the add_category method/function to see if it actually did what it say. The way it's written now it blind faith that it worked and the reason for the header redirect? This is what I'm talking about require 'initializations.php'; if(isset($_POST['add_cat'])) { $result = $cat_obj->add_category($_POST['cat_title']); if ($result) { header("Location: admin/category.php"); exit; else { echo "Oops, something went wrong"; } } of course something in return true or something like that needs to be in the add_category. If require "header.php" is causing the problem then maybe the above needs to be in a configuration file or sessions needs to be used? As the above then isn't at the level at should be at.
  20. That's also true for grid elements as well.
  21. Well, if you just update the $_SESSION on page1 directly, but go straight to page 2 then how is it going to update? It will update if you go to page 1 first then page 2. I hope I'm making sense? You need to update it in a configuration file of some sort or it as a set option where you can't go to any other pages if you update ppp?
  22. Hmm? I didn't not know that as I'm a iPhone user. I find it strange that android devices would do that. I think a work around would to check the email.value to see if it's empty?
  23. Well, I would if the errormessage is the trigger then just wipe out the input value (email.value = "";) for the email, have it required and show the error message. HTML5 won't allow a user to proceed. Maybe? if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)) { errorMessage = 'Email contains invalid character/s'; email.value = ""; } Though it really isn't checking totally for invalid characters just the proper format. (That's what I'm concerned about) I think most people are pretty careful in typing their email address.
  24. const emailIsValid = (email) => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }; email.addEventListener('change', () => { let status = emailIsValid(email.value); console.log('Email Address', email.value, 'Status', status); if (!status) { email.value = ""; email.placeholder = "Email Address is Invalid!"; email.style.borderColor = "red"; email.focus(); } else { email.style.borderColor = myBorder; sendEmail.email = email.value; sendStatus.email = true; } }); It's still best to check it server side and HTML5 make it required.
  25. I for one have found using Grids and Flex to reduce the CSS file size a lot as you really don't use that much CSS when using Grids/Flex, plus it's very easy change the layout of the website. It's well worth redoing the CSS using grids/flex and it's a tad bit better than doing it from the ground up, but not by much. Here's a small example of my css (Actually it's SCSS, but it's just a processor version of CSS) - Though looking at this example it looks like just plain CSS in this portion. /* Approximately the size of an iPad Pro 12.9in 1024px */ @supports (grid-area: auto) { @media screen and (min-width: 64em) { .site { display: grid; grid-template-columns: 1fr minmax(19.2em, 44.80em); grid-template-areas: "header header" "nav nav" "sidebar main" "footer footer"; justify-content: center; } .masthead { background-image: url(../images/img-header-001-1024.jpg); } .registerStyle { display: grid; grid-template-columns: 1fr 1fr; grid-template-areas: "email email" "first last" "screenName telephone" "password1 password2" "birthday submitForm"; justify-content: center; } .first { grid-area: first; margin: 0 0.625em; } .last { grid-area: last; margin: 0 0.625em; } .screenName { grid-area: screenName; margin: 0 0.625em; } .telephone { grid-area: telephone; margin: 0 0.625em; } .emailStyle { grid-area: email; margin: 0 0.625em; } .password1 { grid-area: password1; margin: 0.3125em 0.625em; } .password2 { grid-area: password2; margin: 0.3125em 0.625em; } .birthday { grid-area: birthday; text-transform: capitalize; margin: 0.3125em 0.625em; } .submitForm { grid-area: submitForm; button { float: right; } } } } Another thing that will bog down the CSS is having LARGE image files and having redundant CSS. I also would stylize for smartphones first and work yourself up from there when it comes to CSS responsive web design.
×
×
  • 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.