-
Posts
476 -
Joined
-
Last visited
-
Days Won
13
Everything posted by Strider64
-
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.
-
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?
-
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. 😉
-
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....
- 6 replies
-
- oop
- static-properties
-
(and 1 more)
Tagged with:
-
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.
-
/* 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/
-
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.
-
Taking away URL access to secured area of site
Strider64 replied to TechnoDiver's topic in PHP Coding Help
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. -
$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.
-
Seemingly unconnected file causing header mash up
Strider64 replied to TechnoDiver's topic in PHP Coding Help
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. -
Yeah I know, but wouldn't the file name have to be known if it is a hidden attribute?
-
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.
-
php Mail Contact Form - File Attachment - Not sending file
Strider64 replied to cocolembo's topic in PHP Coding Help
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')); -
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?
-
Confused about non working header redirect
Strider64 replied to TechnoDiver's topic in PHP Coding Help
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. -
That's also true for grid elements as well.
-
Problem transferring data between pages using PHP session
Strider64 replied to dunno's topic in PHP Coding Help
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? -
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?
-
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.
-
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.
-
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.
-
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.
-
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?
-
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.
-
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).