-
Posts
5,450 -
Joined
-
Days Won
175
Everything posted by mac_gyver
-
is there an actual question in this?
-
DOM ids should start with a letter (though browsers will probably let you use ones that start/are just a number.) the parameter in the function call is a string and must be surrounded by quotes. the onclick='...' attribute must also be quoted. the two quote types must be different. the id attribute in the <div ...> must also be set to be the same value as the parameter in the function call. i recommend that you slow down and reread the linked to example.
-
DOM ids must be unique. you basically have the same problem (and solution) as in this recent thread - https://forums.phpfreaks.com/topic/315508-php-and-javascript-with-mysql-copy-button/
-
the msyqli extension does have a fetch_all() function/method, which they finally fixed so that it doesn't depend on the mysqlnd driver, but it is still messed up in that the default fetch mode is numeric, which is different from the default fetch mode for every other general fetch - both/assoc/numeric statement, because the nimrods that programmed this didn't understand that the fetch mode applies to the rows of data, not the all-array holding those rows.
-
yes. if you were using the PDO database extension, it has a fetch mode that will directly produce an array of the SELECTed column values.
-
$sku = array( '1234', '5678', '4444', '2222', '9393', '1111', '8689' ); foreach(array_chunk($sku,5) as $chunk) { $qs = '&SKU=' . implode('&SKU=',$chunk); // examine the result echo $qs . '<br>'; }
-
i would use array_chunk() to break the starting array into chunks of 5 elements, with the last chunk containing the remainder. you can then simply use a foreach(){} loop to loop over the chunks. rather than concatenating to build the query string, just implode each chunk array.
-
the main point of using a prepared query, e.g. with place-holders in the sql statement where the data values are to be acted upon, then supply the actual data values when the query is executed, is to prevent any sql special characters in a data value from being able to break the sql query syntax, which is how sql injection is accomplished, by separating the parsing of the sql query syntax from the evaluation of the data values. a secondary point is they provide a performance gain (~5%) in the rare cases when you execute the same query within one instance of your script with different data values, since the sql query statement is only sent to the database server once, where it is parsed and its execution is planned only once.
-
the simplest, straightforward solution would be to query on each page request to get the current user's status. even though you are not performing any of the actions i listed, you are forcing the user to become logged out. in the current code you should have login check logic on each protected page, that starts the session and tests if $_SESSION['unique_id'] is or is not set. you would change it to the following to cause a status value of "Offline now" to log the user out and redirect to the logintool.php page - <?php // this sets the lifetime to zero and the rest of the values to null session_set_cookie_params(0); session_start(); // login check code if(!isset($_SESSION['unique_id'])) { // if not logged in, go elsewhere header("location: https://www.peredy1.com/adminchat/logintool.php"); die; } // at this point there's a logged in user, get the user's current status // note: use 'require' for things your code must have for it to work require "config.php"; $sql = "SELECT status from users WHERE unique_id = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param('i', $_SESSION['unique_id']); $stmt->execute(); $stmt->bind_result($user_status); $stmt->fetch(); if($user_status === "Offline now") { // force a log-out // note: you should only unset() $_SESSION['unique_id'] since a session can contain other pieces of data session_unset(); session_destroy(); header("location: https://www.peredy1.com/adminchat/logintool.php"); die; } // at this point the user is logged in and can access the rest of the code on the protected page
-
no. the session data files are managed by php.
-
session_save_path() returns the path of the current directory used to save session data.
-
it's in the posted code, by deleting the session data.
-
you would have to find out where the session data files are stored and unlink() them. it would be much better to query on each page request to get the user's current status, so that you can individually implement things like promoting, demoting, suspending, or banning a user.
-
the code wasn't designed to let you do this, because it isn't querying on each page request to get the user's current status, which would let the login check code force a log-out based on a value stored in the database table. you can either rewrite the code to do this, or you could delete all the session data files, which would also log-out the admin performing this action, unless you want to scan through the session data files to find the one for the admin and not delete it too. btw - not only should the logout be a post method form, but using mysqli_real_escape_string() on a value that isn't being used in a string context in a query doesn't provide any sql injection protection, which still can occur for trusted users if cross site scripting is possible, since any value submitted to your code can be changed by cross site scripting to be anything and cannot be trusted. the only fool-proof way of preventing sql injection is to use a prepared query.
-
in general, functions should accept input data as call-time parameter(s), so that they can be reused with different input values. start by dynamically building the id attribute, incorporating the $row['id'] value (note: you can put php variables directly into an overall double-quoted string without all the extra quotes and concatenation dots) - id='c_{$row['id']}' dynamically build the function call with the same value as its call-time parameter - <button onclick=\"myFunction('c_{$row['id']}')\">Copy</button> modify the function definition to use the call-time parameter as the id of the element to reference - function myFunction(id) { // Get the text field var copyText = document.getElementById(id); .. the rest of the function code is the same
-
the variable in question contains a string, because that's what you wrote a line of code to cause that variable to contain. that line of code was not in the most recent previous code. why are you making random changes for no reason? why are you even changing the name of the database connection variable, which should be named as to what type of database connection it contains, so that you can easily see or search which code is using a connection type that's different from what you were previously using in your code? the example code I posted some time ago was error free, secure in both an sql and html context (the htmlentities() call was in the proper location, where a dynamic value was being output as a form field value), provided a good User eXperience (UX), was as SIMPLE and straightforward as possible, without a bunch of unnecessary typing, variables, and logic, and through the suggested php error related settings, validation logic, and error handling, would have either worked or told you when and why it didn't work. now you have a bunch of assembly line repetitive typing crap that took over a month to come up with and still doesn't work.
-
looking for an easy way to implement pagination
mac_gyver replied to alexandre's topic in PHP Coding Help
the number of concurrent database connections is only limited by your database server/hosting, and is typically several 100. your script could (but shouldn't) make a dozen connections using both mysqli and PDO at the same time. the PDO extension is better designed, simpler, and more consistent than the mysqli extension. as an added benefit, works with 12 different database types, so you are not learning a new set of php statements for each database type. if you had some problem using the PDO extension, you would need to find out why and fix it. the following is typical PDO connection code - $DB_HOST = ''; // database host name or ip address $DB_USER = ''; // database username $DB_PASS = ''; // database password $DB_NAME = ''; // database name $DB_ENCODING = 'utf8mb4'; // db character encoding. set to match your database table's character set. note: utf8 is an alias of utf8mb3/utf8mb4 $options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // set the error mode to exceptions PDO::ATTR_EMULATE_PREPARES => false, // run real prepared queries PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // set default fetch mode to assoc ]; $pdo = new pdo("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=$DB_ENCODING",$DB_USER,$DB_PASS,$options); -
looking for an easy way to implement pagination
mac_gyver replied to alexandre's topic in PHP Coding Help
this is the same as what the example code is doing, just with a variation of the LIMIT/OFFSET term. it's not. this is only the data retrieval query part of the process. you still need all the other functionality that was shown in the example code. -
looking for an easy way to implement pagination
mac_gyver replied to alexandre's topic in PHP Coding Help
here's an example showing the points that have been made - <?php // initialization // this example uses the much simpler PDO database extension require 'pdo_connection.php'; // number of results per logic page $num_results_on_page = 25; // number of +/- pagination links around the current page number $range = 3; // post method form processing - none in this example // get method business logic - get/produce data needed to display the page // build the common part of the queries $common_sql = 'FROM random_donation_clash'; // get the total number of matching rows $sql = "SELECT COUNT(*) $common_sql"; $stmt = $pdo->query($sql); $total_rows = $stmt->fetchColumn(); // calculate total number of pages $total_pages = ceil($total_rows / $num_results_on_page); // get/condition the current page number, default to page 1 $page = intval($_GET['page'] ?? 1); // limit page to be between 1 and $total_pages $page = max(1,min($total_pages,$page)); // get a logical page of data $offset = ($page - 1) * $num_results_on_page; // note: a person's age is not a fixed number, unless they are dead. store the date of birth and calculate the age when needed. $sql = "SELECT name, age, joined $common_sql ORDER BY name LIMIT ?,?"; $stmt = $pdo->prepare($sql); $stmt->execute([ $offset, $num_results_on_page ]); $page_data = $stmt->fetchAll(); // build pagination links: prev, 1, range around current page, total_pages, next $pagination_links = ''; if($total_pages > 1) { // produce array of pagination numbers: 1, range around current page, total_pages, without duplicates, between 1 and total_pages $links = array_filter(array_unique(array_merge([1],range($page-$range, $page+$range),[$total_pages])), function ($val) use ($total_pages) { return $val >= 1 && $val <= $total_pages; }); // get a copy of any existing get parameters $get = $_GET; // produce previous $get['page'] = $page - 1; $qs = http_build_query($get,'', '&'); $pagination_links .= $page == 1 ? 'prev ' : "<a href='?$qs'>prev</a> "; // produce numerical links foreach($links as $link) { $get['page'] = $link; $qs = http_build_query($get,'', '&'); $pagination_links .= $link == $page ? "$link " : "<a href='?$qs'>$link</a> "; } // produce next $get['page'] = $page + 1; $qs = http_build_query($get,'', '&'); $pagination_links .= $page == $total_pages ? 'next' : "<a href='?$qs'>next</a>"; } // html document ?> <!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8"> <title>Pagination Example</title> </head> <body> <?php if(!$page_data): ?> <p>There is no data to display</p> <?php else: ?> <table> <tr> <th>Name</th> <th>Age</th> <th>Join Date</th> </tr> <?php foreach($page_data as $row): ?> <tr> <td><?=$row['name']?></td> <td><?=$row['age']?></td> <td><?=$row['joined']?></td> </tr> <?php endforeach; ?> </table> <?php endif; ?> <p><?=$pagination_links?></p> </body> </html> -
looking for an easy way to implement pagination
mac_gyver replied to alexandre's topic in PHP Coding Help
here's an additional list of points for this code, most of which will clean up, organizing, and simplify the code - put any error related settings in the php.ini on your system. build any sql query in a php variable. this makes debugging easier and helps prevent typo mistakes. pagination involves two queries. the common part of the query, from the FROM term through to any HAVING term should be built in a php variable, with a corresponding array of any prepared query input parameters, so that these common parts can be used in both queries. don't select all the columns and all the rows to find the total number of matching rows. use a SELECT COUNT(*) AS total... query, then fetch and use the total value. use the much simpler PDO database extension. as already mentioned, calculate the total number of pages, once, and store it in a correctly named php variable. the total number of pages is needed to validate/limit the submitted page number and in the pagination link code. use exceptions for database statement errors and only handle the exception/error in your code for user recoverable errors, of which a select query isn't, i.e. don't put any error handing logic in your code for a select query. put any query to get/produce the data needed to display the page above the start of the html document, fetch all the data from the query into an appropriately named php variable, then test/loop over this variable at the appropriate location in the html document. you should list out the columns you are selecting in a query. if the data retrieval query doesn't match any rows of data, test and output a message stating so, rather than to output nothing at that point in the html document. put any code to get/product the pagination links above the start of the html document, build the output in an appropriately named php variable, then echo this variable at the appropriate location(s) in the html document. when building pagination links, you should start with a copy of any existing $_GET parameters, set the current 'page' parameter value for the current link, then build the query string part of the current URL by using php's http_build_query(). there's generally no need to close prepared statements, free result sets, or close database connections in your code since php will destroy these things when your script ends. -
ids must be unique throughout the html document. since each section has the same id, the popup code always displays the first section. you need to use a different selector in the javascript, either to operate on the current element, find the nearest element, or use unique and valid ids in the markup. posting all the code needed to reproduce the problem would allow someone here to help arrive at the simplest result.
-
the spelling in the PDO DSN connection string is mysql, not msql
-
if the last snippet of code, with the foreach() loop using $this->productType, was an attempt at 'fixing' the last error, that's not it. there was nothing wrong with the code i posted. it was in fact tested code. there is however, something that needs to be changed about the __construct() code in that class, which i wrote a reply stating. at this point, i don't think you understand what your OOP code is doing, so, wont be able to modify it or troubleshoot it when any errors occur. whatever learning resource you are using, isn't teaching you the meaning of what you are doing.
-
i'm going to guess that you didn't write the OOP post class or if you did, you copied something you saw and didn't actually learn the meaning of what you were doing? in your existing OOP post class definition, there's a __construct() method that looks like - public function __construct($db) { $this->conn = $db; } you need to add the $table and $fields input parameters and class property assignments.
-
I've written at least twice that the ->create() method must return a success or failure value that you test in the calling code. the database specific code in the ->create() method is where that information is known at. here's what your create.php should look like (without the multiple column duplicate determination code) - <?php // when using ajax, the only thing this code will do is handle the post method form processing // you can save resources on non-post requests by putting all the code inside the request method test // initialization //Headers header('Access-Control-Allow-Origin: *'); header('Content-Type: application/x-www-form-urlencoded'); header('Access-Control-Allow-Methods: POST'); header('Access-Control-Allow-Headers: Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods, Authorization, X-Requested-With'); // use 'require' for things your code must have for it to work require '../../config/database.php'; require '../../models/post.php'; //Instantiate db $database = new Database(); $db = $database->connect(); // define the $table and $fields for the Create operation $table = 'skandi'; $fields = []; $fields['sku'] = ['label'=>'SKU','validation'=>['required']]; // add other field definitions here... //Instantiate post for the Create operation $product = new Post($db,$table,$fields); $post = []; // array to hold a trimmed working copy of the form data $errors = []; // array to hold user/validation errors // post method form processing if($_SERVER["REQUEST_METHOD"]==="POST") { //Get raw data $json = json_decode(file_get_contents("php://input"),true); // trim all the input data at once $post = array_map('trim',$json); // if any input is an array, use a recursive trim call-back function here instead of php's trim // validate all inputs foreach($fields as $field=>$arr) { if(isset($arr['validation']) && is_array($arr['validation'])) { foreach($arr['validation'] as $rule) { switch ($rule) { case 'required' : if($post[$field] === '') { $errors[$field] = "{$arr['label']} is required"; } break; // add code for other validation rules here... } } } } // if no errors, use the input data if(empty($errors)) { //Create if(!$product->create($post)) { // initially, just setup a canned message for the sku column $errors['sku'] = "SKU is already in use"; // the code to detect which of multiple columns contain duplicates would replace the above line of code } } // if no errors, success if(empty($errors)) { $response = [ 'message' => "Created Successfully" ]; } else { $response = [ 'message' => implode('<br>',$errors) ]; } echo json_encode($response); } the corresponding ->create() method would be - public function create($data) { // build the sql query $set_terms = []; $params = []; foreach(array_keys($this->fields) as $field) { $set_terms[] = "`$field`=?"; $params[] = $data[$field]; } $sql = "INSERT INTO `$this->table` SET " . implode(',',$set_terms); $stmt = $this->conn->prepare($sql); try { // a 'local' try/catch to handle a specific error type $stmt->execute($params); // if you are at this point, the query executed successfully return true; } catch (PDOException $e) { if($e->errorInfo[1] == 1062) // duplicate key error number { return false; } throw $e; // re-throw the pdoexception if not handled by this logic } } as to the server-side validation logic, you should validate each input separately and setup a unique and helpful message for each validation error. the code posted in this reply shows how to use a data-driven design to dynamically validate the data and build the sql query. however, it just occurred to me that the product characteristics (size, weight, height, length, and width) change depending on the selected productType, so the data-driven definition would need entries for each productType value (you should also have a separate product characteristic table, rather than columns in this main table for these characteristic values, where you would only insert rows for each characteristic that exists for each defined product.) for debugging, just temporarily output (echo/print_r/var_dump) things in the php code, and send everything to the console log in the javascript - success: function (data) { console.log(data); alert("successfully posted"); },