-
Posts
5,450 -
Joined
-
Days Won
175
Everything posted by mac_gyver
-
does the activation link contain a run-once unique token? this would let you know if something is just submitting email addresses or actually has access to the content in the emails.
-
if a business rule of the application is that that booking/busy times start/end on 30 minute intervals, you would need to provide a method of picking values that follow that rule and you would need to validate submitted data to insure that it meets that rule. if you have existing data that doesn't follow that rule, you can normalize the values, either where they are stored or when pre-processing the array of data, to round start times down to the previous interval time and round end times up to the next interval time.
-
here's an outline of what the logic would look like - $interval = 30; // booking/busy interval in minutes // based on conditional logic in the code, 0 = mon through 6 = sun define('MON',0); // use defined constants to make code/data self-documenting // working hours $hours = []; $hours[MON] = ["morning_from" => "closed", "morning_to" => "closed", "afternoon_from" => "13:00", "afternoon_to" => "19:00"]; // note: if you define the above array as an array of arrays, with the from/to values, a label (Morning/Afternoon), and a 'closed' or time entry, you can just loop over this to produce the output without needing to have specific code for each possible segment in a day // busy times - the example data is for a monday $busy = []; $busy[] = ["title"=> "Test", "start_date" => "2019-11-25 13:00:00", "end_date" => "2019-11-25 14:00:00"]; // pre-process the booked/busy data $data = []; foreach($busy as $arr) { $date = $arr['start_date']; $end_date = $arr['end_date']; while (strtotime($date) <= strtotime($end_date)) { $data[$date] = $arr['title']; $date = date("Y-m-d H:i:s", strtotime("$date +$interval min")); } } // examine the pre-processed booked/busy data echo '<pre>'; print_r($data); $current_date = '2019-11-25'; // determine the current date being displayed using whatever logic the code has now $book_day_int = date('N') - 1; // get the integer day of week number - 1 $current_day = $hours[$book_day_int]; // get the from/to data for the current day // morning output (see the note above by the $hours array to simplify and make the code general-purpose) $start = $current_day['morning_from']; $end = $current_day['morning_to']; if( $start != 'closed') { echo 'Morning<br>'; $start = "$current_date $start:00"; $end = "$current_date $end:00"; $date = $start; $end_date = $end; while (strtotime($date) <= strtotime($end_date)) { echo $date; // test if this date-time is busy if(isset($data[$date])) { echo ' ' . $data[$date]; } echo '<br>'; $date = date("Y-m-d H:i:s", strtotime("$date +$interval min")); } } // afternoon output $start = $current_day['afternoon_from']; $end = $current_day['afternoon_to']; if( $start != 'closed') { echo 'Afternoon<br>'; $start = "$current_date $start:00"; $end = "$current_date $end:00"; $date = $start; $end_date = $end; while (strtotime($date) <= strtotime($end_date)) { echo $date; // test if this date-time is busy if(isset($data[$date])) { echo ' ' . $data[$date]; } echo '<br>'; $date = date("Y-m-d H:i:s", strtotime("$date +$interval min")); } }
-
here’s how you should do this - pre-process/expand the booked/busy array of data so that it has entries for each 30 minute interval of the appointment, using the date-time value Y-m-d H:i:s as the array index. for the example data, you would end up with three entries - 2019-11-25 13:00:00, 2019-11-25 13:30:00, and 2019-11-25 14:00:00, all with the same title as the array value (if the data for each appointment is actually more than this, store it as a sub-array under each index.) get the day of week number from the current date you are displaying, then get the morning/afternoon start and end times for that day, loop over the 30 minute intervals, from the start time to the end time, produce the date-time value for each interval - Y-m-d H:i:s, then test (isset() will work) if there’s an entry in the pre-processed booked/busy data array for the current interval.
-
chrisj, what is the overall reason you have been beating on this script (and the previous phpmotion script) for so long? is this for a collage course assignment? is this for self-learning? do you think that having a video sharing script will help you to make money? some other reason? the main reason i ask is, most of your posts seem like you just want someone else to think/write code for you, and your only involvement is to be a 'proxy typist' pushing keys on a keyboard. this is not how programming help works, doesn't result in any learning, and doesn't result in much progress. you need to be able to define for yourself what the code/data should do, then through learning enough php/sql/html/css/javascript, be able to design, write, test, and debug the code needed to produce an application or make changes to an existing application. you need to sit down with paper/pencil or an open text document, and list out the top-level work-flow (steps) that need to occur, from the point where someone first visits your site through to the point where they watch a purchased video. you would then define what the user interface (UI) looks like for each step. you would then define what input data, what processing, and what result or output is needed to accomplish each step. the part of the process where you are at in this thread is when the user has hit the submit button during the 'checkout' step. regardless of this being for physical or digital items or using real money or credits, the processing is the same/similar. you would store/convert the cart items in to a 'pending' (unpaid) order. when payment is confirmed, you would update the order status to 'paid' and either trigger the shipment of physical items or make digital items available for downloading/viewing. since you are using credits that are being managed on your site, as far as the order status, you would determine if the user has enough credits in their account, update the order status to 'paid', deduct the amount from the user's account, add the earned amount to the video owner's account, and add the reminder to the system's account. all the database queries that modify data as part of this step, must be part of the same database transaction, so that if any of them fail, they all fail and roll-back. to manage the amounts, each video (which can have its own price, resulting in a different earned amount, and a different remainder for the system) that's purchased should have a separate set of records inserted into the account table. here is the starting definition for the account table - since the time when i wrote that, i think it would be a good idea to add the video purchase id (auto-increment integer primary index from the paid_videos table) so that the account records are related to the video purchase record they correspond to. so, what would be inserted into the account table foreach(){} video that is purchased - a row with the purchaser's id (id_user), the negative of the video purchase price, a transaction type id (for a purchase), the last insert id from the row that was inserted into the paid_videos table, and the current datetime. a row with the video owner's id (user_id_uploaded), the positive earned amount for the video, a transaction type id (for an earned amount from a purchase), the last insert id from the row that was inserted into the paid_videos table, and the current datetime. a row with the system's id, the positive remainder between the video purchase price and the earned amount, a transaction type id (for a system share of a purchase), the last insert id from the row that was inserted into the paid_videos table, and the current datetime. the transaction_type_id in the above means that you need a 'transaction type' table, with an id column and a name column. to get the account total for any user id, you would just SUM() the total column, and group by the user_id column, for any single, list, or all users (depending on the WHERE clause used.) to get the account total for any/each transaction type, you would additionally group by the transaction type id column.
-
what output do you get and if it's a blank page, what does the 'view source' of the page in your browser show? either the output is hidden in the 'view source' or the code isn't being executed. since you apparently are getting the data inserted, it's possible you are 'seeing' the result of a double page request, especially since you are using a get request to do this rather than a post method form.
-
What's the proper way to do "SORT BY" selection options?
mac_gyver replied to imgrooot's topic in PHP Coding Help
to do this, you need to produce an array that defines the permitted choices and also contains entries that control which tables/columns to use in the query. you would then dynamically produce the base query by having general-purpose code that makes use of the data in the array. short-answer: you are trying to produce a data driven design, rather than to hard-code logic for every possible choice. some comments about the existing code - use domain relative urls, this will eliminate the need for the $page_url value. trimming input data after you have tested if the data is empty is backwards. use http_build_query() to produce links in your code from any existing get parameters and any new values. this will eliminate the need for the preg_repalce() statement near the start of the code. put the 'get method' business logic before the start of your html document. the base query, with any table, join, where, and having clauses must be the same for both the COUNT(*) query and the data retrieval query. build this part of the query and any bound input parameters, in this part of the query, in dedicated php variables, then use these variables when building and executing the two queries. put literal, constant values directly into queries, such as the publish = 1 value. use implicate binding, by supplying an array of the input values to the execute call. don't copy variables to other variables without a good reason. just use the original variables. -
Converting custom website from PHP 5.6 to 7.2
mac_gyver replied to dc2000's topic in PHP Coding Help
how much total code/files is/are there? if you post your code (less any database/api credentials) somewhere (in the forum or on github) you would get more specific help about what you do need to change. since your code works under php5.6, you don't have to deal with register_globals, and the only things to update would be those that have been removed, are backward incompatible, or are deprecated (to future-proof) in going from 5.6 to 7.x. -
Converting custom website from PHP 5.6 to 7.2
mac_gyver replied to dc2000's topic in PHP Coding Help
if your code is not making any shell/system/passthru calls, it doesn't matter what operating system you use for a development system. all that matters is you have the same set of extensions and php.ini settings between the development system and the live server. you can use one of the all-in-one development packages. the mysql extension became deprecated as of PHP 5.5 (released in 2013) and would have been throwing errors in your code if not for the @ error suppressors. don't ever use @ error suppressors in any code. on a live/public server, your php error related settings should be set to log all errors. if you are faced with updating old code that uses the mysql extension, do yourself a favor and 1) jump directly to use the very simple and future-proof PDO extension, 2) use prepared queries when supplying external/unknown data to an sql query statement (this actually simplifies the sql query syntax), 3) using implicate binding (supply an array of values to the execute call) for prepared queries, and 4) use exceptions for errors and in most cases let php catch and handle the exception where it will use its error related settings to control what happens with the actual error information (database errors will 'automatically' get displayed/logged the same as php errors.) doing these four things greatly simplifies the implantation of your database specific code, which will let you eliminate, rather than convert code, shortening the task. -
if you use exceptions for database statement errors and in most cases let php catch and handle the exception, php will use its error related settings to control what happens with the actual error information (database errors will 'automatically' get displayed/logged the same as php errors.) you will be able eliminate the existing error handling, rather than to convert it. to enable exceptions for errors for the mysqli extension, add the following line of code before the point where you make the database connection - mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); now the bad news, it is not enough to just update statements in old code, as one of the things that was removed in php5.4, magic_quotes, eliminated some protection that php provided against sql special characters in external string data from breaking the sql query syntax (which is how sql injection is accomplished.) if your code does not have specific protection for all external/unknown data, and for all the different data types, being put into sql queries, you will need to add it. the simplest, universal way of doing this is to use prepared queries, provided that you switch to use the simpler PDO extension. the prepared query interface for the mysqli extension is overly complicated and inconsistent
-
See if something submitted (best practices 2019)
mac_gyver replied to StevenOliver's topic in PHP Coding Help
detect that a post method form was submitted. trim all input data at once, so that you can detect if all white-space characters were entered (this is the only alteration you should make to the input data.) if more more than one form will submit to the same page, add logic, using your favorite method, to detect a unique field/value from the form, to control which form processing code to execute. validate all input data, storing unique and helpful validation error messages in an array. this array is also an error flag. if the array is empty, there are no errors. if the array is not empty, there are errors. if there are no validation errors, use the submitted form data. afaik, the form name is not submitted, as the form tag is not an input field. the submit button may or may not be set, depending on how the form gets submitted and/or which browser is being used, so, don't bother testing it. if you need to distinguish between multiple forms on one page, add a unique key/value as a hidden form field, and detect this in your code. except for un-checked check boxes and radio buttons, once the form has been submitted, all other form field types will be set, even if they are empty, so there's no point in cluttering up code with isset() statements for these types of fields. you would want to see (during development)/log (on a live/public server) php errors if expected-set form fields are not set, as this indicates either a programming mistake or someone/something submitting their own set of fields. as an advanced programming subject, dynamically validate and process the submitted form data, by defining an array, with the field names as the array indexes, and an array of elements under each index controlling the validation steps and the type of processing for each field. none of this has anything to do with security. security is achieved by using data properly in whatever context it is being used in. if used in an sql context, use a prepared query. if used in a html context, apply htmlentities() to the data. if uploading files, store them in a location that is not directly accessible through a http request. -
this is due to floating point conversion errors. see this link on how to do this math using binary coded decimal numbers, i.e. like a hand-held calculator does - https://www.php.net/manual/en/book.bc.php
-
Null session array condition not met until page is refreshed
mac_gyver replied to makamo66's topic in PHP Coding Help
since the code is un-setting the variable and will always output 'else test', if you are not seeing the output, ether - your code is redirecting all over or using ajax to display content and you are not actually 'on' the page where this code is at, but the refresh does 'goto' the page where this code is at. you have some conditional logic that is preventing the posted code from being executed, either explicate logic or an exit/die statement, which the refresh doesn't trigger, and so the posted code gets executed. some html is being conditionally output prior to the posted code and the output from the posted code is hidden in the 'view source' of the page, but, again, the refresh doesn't trigger the prior output, and so you see the output from the posted code. since you have repeated the unset() statement with the variations of the code, i/we assume that is actually part of this code. do you understand what the unset() statement does and what affect it will have on the conditional logic test(s) you have posted? as stated on one of the other help forums, all you are showing/describing are snippets of code and symptoms. if you just post all the relevant code for the page(s) involved with this problem, someone can probably solve this in a couple of minutes. -
the example you have shown implies you have sets of same meaning data stored in a single row in the database table. this is a bad design, resulting in more code/queries to manage the data. research database normalization to find out how to properly store data. each set of data should be stored in a separate row in the database table, with an auto increment id column. this will establish a unique identifier that you can use when dynamically building the edit links. the id from the link would be used in the edit.php code to retrieve the correct row of data to populate the form fields with. the id would be passed in a hidden field in the form. the process.php code would detect that a post method form has been submitted, enforce any user 'edit' or ownership permissions, validate the input data, then use the input data when executing the update query.
-
wherever you read that, it (should have) included the information - 'when using emulated prepared queries and supplying the values via an array to the ->execute() method call'. since you are not using emulated prepared queries, you can use place-holders for the limit values.
-
store them in a session array variable as stated in your previous thread. all what code? the submitted form data will be in $_POST. the only thing submitted when someone adds an item to the cart is the item id (sku) and the quantity (which could be an implied 1.) the form processing code needs to add new items to the session cart array variable with the submitted quantity or implied quantity of 1 or add the submitted quantity to the existing quantity if the item is already in the cart. you can have code to handle other operations, such as removing an item from the cart, clearing the entire cart, or updating the entire cart. if there's a lot of code/variables to do this, somethings wrong with the existing code. the server-side code to perform the 'add' to cart operation is probably about 20 lines of code. anything occurring in the client-side javascript are for display purposes and don't affect what's in the server-side cart. when you process the contents of the server-side cart (item ids and quantities), you calculate any amounts on the server (accepting prices/amounts from the client-side code allows someone to purchase things for the price they want, not the price you have set.) if you want specific help with any existing code you will need to post it.
-
Safe to use two forms and hidden inputs?
mac_gyver replied to StevenOliver's topic in PHP Coding Help
yes to storing the data in a session variable, no to just concatenating it to a single element. the 'cart' session variable needs to be an array, with the array index being the item id and the value stored in the array being the quantity. this will result in the simplest code when referencing or manipulating the data. for example, how do you detect and deal with adding the same item to the cart more than once? with an array, you can just use isset() to detect if the item id is already in the cart. with concatenation, you must search though the string to find a match. -
i'm guessing the answer is 42?
-
Safe to use two forms and hidden inputs?
mac_gyver replied to StevenOliver's topic in PHP Coding Help
external data can be anything and cannot be trusted. you have to validate all external data before using it, so, you should submit/pass a minimum of information through a form. by using a hidden field, you will have to validate the original data and then re-validate all the hidden field data before using it. when items are selected, the item id (sku) and quantity should be the only information that gets submitted and should be stored in a 'cart' on the server, either in a session array variable or in a database table. you would use or display the server-side cart information as needed. when an order is finalized/finished, you need to persistently store the items making up that order, in a database table. to display or print a packing slip, you would query for and retrieve the item information for the correct order number. -
forget about the mysqli extension when updating old code, especially when there's external/unknown data being put into the sql query statement. use the much simpler and more consistent php PDO extension instead. after you make the connection using the PDO extension, in $pdo, the following are some usage examples - a query that doesn't have any external/unknown data being put into it // form the sql query statement $sql = "your sql query statement here..."; // execute the query $stmt = $pdo->query($sql); // for SELECT queries, fetch the data into an appropiately named php variable // for a query that will match at most one row $some_descriptive_var = $stmt->fetch(); // for a query that will match a set of zero or more row(s) $some_descriptive_var = $stmt->fetchAll(); // use the variable holding the data at the appropiate place in your html document. if the query didn't match any data, the variable will be a boolean false/empty() value. for a query that does have external/unknown data being put into it, you need to use a prepared query, with a ? place-holder in the sql query statement for each data value, then supply the data when you execute the query. // form the sql query statement $sql = "your sql query statement here..."; // prepare and execute the query $stmt = $pdo->prepare($sql); $stmt->execute(supply an array of the variable(s) holding the data values here...); // the code dealing with the result from a SELECT query is the same as above when converting an old query that has variable(s) in the sql query statement, you would remove the variable, any single-quotes, {}, and concatenation dots associated with the variable from the sql query statement, and replace each variable with just a ? place-holder. the variable(s) that were removed would be supplied as an array to the ->execute(...) method call. you would also remove, rather than convert, any ..._escape_string() functions in old code. when you make the connection, set emulated prepared queries to false (you want to run TRUE prepared queries when possible), error mode to exceptions, and set the default fetch mode to assoc (so that you don't have to specify it in every fetch statement, but can override it when necessary.) here is some typical connection code - $DB_HOST = ''; // db hostname or ip address $DB_USER = ''; // db username $DB_PASS = ''; // db password $DB_NAME = ''; // database name $DB_ENCODING = 'utf8'; // db character encoding. set to match the character encoding of your db tables $pdo = new pdo("mysql:host=$DB_HOST;dbname=$DB_NAME;charset=$DB_ENCODING",$DB_USER,$DB_PASS); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // set the error mode to exceptions $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); // run real prepared queries $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); // set default fetch mode to assoc by using exceptions to handle database statement errors (the connection always uses an exception for an error, the above setting applies to query, prepare, and execute statements), you can eliminate any existing error handling logic, rather than to convert it. in most cases you should just let php catch any exception, where it will use its error_reporting, display_errors, and log_errors settings to control what happens with the actual error information. the only time you would need to have a try/catch block in your code to catch and handle a database exception is when inserting/updating duplicate data. this is a recoverable error. your catch logic would detect if a duplicate key error occurred (requires setting the database table column(s) as a unique index, if they are not already), and setup a user error message indicating what was wrong with the data that was submitted. if the error is not for a duplicate key, you would re-throw the exception and let php catch and handle it.
-
here's a list of things i saw in the posted code - 1. don't put php variables inside of double-quotes if they are the only thing in the string. 2, don't use or die() for error handling. use exceptions and in most cases let php catch the exception. note: your use of mysqli_error(...) in the connection code won't work because there's no connection to use. 3. don't unconditionally output database errors onto a web page (this will go away when you get rid of the or die() logic.) 4. don't run queries inside of loops. learn to do JOIN queries. 5. if your code is tabbed that far over because it is located inside your html document, you need to put the php code that's responsible for getting/producing data before the start of your html document, fetch the data into appropriately named php variable(s), then use those variable(s) in the html document. 6. handling the negative/failure case is usually shorter then the positive/successful case. if you invert the logic tests and handle the negative/failure condition first, your code will be clearer. you won't have logic for the negative/failure case 10's/100's of lines later in the code. 7. don't use loops to fetch what will be at most one row of data. just directly fetch the single row of data. 8. don't put static calculations inside of loops. the various date values shouldn't change during one report (where they are at now, they will if the request spans midnight.) put them before the start of the loop. 9. don't put quotes around numbers. 10. don't selected things that are not used and don't create variables that are not used (given the amount of code, the cases i saw of this may not be accurate.) 11. if you are looping to do something (should go away with JOINed queries), don't evaluate count() statements in the loop. determine the loop count, once, before the start of the loop. 12. doing some of these things will simplify variable naming. you won't have to think up unique names for variables because you will only have one instance in the code. 13. the $AffID is probably from external/unknown data. you should NOT put eternal/unknown data directly into an sql query statement. use a prepared query, with a place-holder for each data value, then supply the data when the query gets executed. switching to the much simpler php PDO extension will make using prepared queries easy compared to the php mysqli extension.
-
yes, but you are trying to upload 12M bytes. your form processing code, after detecting that a post method form was submitted, first needs to detect and handle the condition in item #3 in my list above. you should detect that the $_FILES array is empty and set up an appropriate user error message, than skip trying to process any $_FILES or $_POST data since there isn't any. you should use an array to hold the validation errors (this is not the same as your array holding the defined error messages.) as you test and validate the submitted data, store the errors into an array variable. this variable then also serves as an error flag. if the array is empty, there are no errors and you can use the submitted data. if the array is not empty, there are errors. to display the errors, you would output the content of this array at the appropriate point in your html document.
-
if you are still getting the first error you listed - ... POST Content-Length of 12263648 bytes exceeds the limit of 8388608 bytes..., and you tried to set the post_max_size setting to be more than 8M Bytes, something prevented the change from working. either the php.ini that you changed isn't the one that php is using, there's a setting that's overriding the one you change (a local php.ini), there's a syntax error in the php.ini above the point you changed that's preventing the file from being fully parsed, the line you changed is in some commented out code or is using a value that isn't valid. add a phpinfo(); statement to the top of your .php file and check what the - Loaded Configuration File value is and what both the local and master post_max_size setting is. also, check if the file_uploads setting is ON. for reference, here are the things that can cause the $_FILES array to be empty - 1. One of several possible problems with the html form - not a post method form, missing the enctype attribute, missing a type='file' field, the form field isn't inside the form, a misnaming between the form field and the php code, broken html markup, ... 2. Uploads are not enabled on the server. 3. The total size of the submitted post data exceeds the post_max_size setting. In this case, both the $_POST and $_FILES arrays will be empty. 4. The $_FILES array is being referenced without first detecting that a post method form was submitted.
-
Submit large form created with select statement
mac_gyver replied to Adamhumbug's topic in PHP Coding Help
you only need one form field per item. use a meaningful name for the field, such as qty, and use the item id as the field's array index value - name='qty[item id goes here]'. in the form processing code, use a foreach() loop. this will give you the item id and the submitted quantity for the id. to remove empty items use array_filter() with no call back function (empty strings and zeros are false and will be removed.) lastly, you need to insert a separate row in your table for each item and you need to use a prepared query, with place-holders in the sql query statement for each value, then supply the values when you execute the query. you would prepare the query once, before starting to loop over the data, then only get each set of values and execute the query inside of the loop.