Psycho
Moderators-
Posts
12,157 -
Joined
-
Last visited
-
Days Won
129
Everything posted by Psycho
-
Programming, like any skills, is a matter of Crawl, Walk, Run. You learn by doing the very simple things, then build on that to learn intermediate skills, then (after a sufficient amount of time) you can learn to do more complex things. But, here's the thing. If you already know how to run a query against the database, you should already know how to work with an array and to build an output from it. Plus, the fact that you state you've been working with this language for two years and don't know these fairly easy tasks is incomprehensible to me. In fact, I am leaning towards the fact that you are a troll and just trying to get people mad based on your "not" understanding these things. I've even considered locking the thread.
-
@forum It appears you are of the expectation that when retrieving the results of a Database query, that you should be able to just do an "echo" of the results and have it written to the page in some way. That's not how this works (with PHP/MySQL or any similar languages as far as I know). If you think about this logically, you would understand that would not be very useful for the majority of use cases. Here are just a couple of reasons; How should the results be formatted? What works for one scenario would not work for the other 9,999 scenarios. Not all DB queries would be output to the page without other "post-processing". E.g. maybe the results should include sub-totals for different categories, or some records should be displayed differently (e.g. a negative amount in red. It would be extremely difficult if the results were returned in an "echo" ready format to do anything with the data. A database returns DATA in a logical data type that a programming language or other resource can work with. It is up to the receiving application to determine what to do with the data. If you want to run a query and have it output to the page in some standard format. Then just create a simple function and you can call that function every time you call a query. That is the beauty of programming, you can write a little bit of code to do something repetitive and reuse that code whenever and wherever you choose. You only have to figure out how to do it one. Also, there is a VERY easy way to output a multi-dimensional array in a readable format (albeit not in a table). I do this all the time to be able to debug output from a query. $query=$db->query("SELECT * FROM msg"); echo "<pre>" . print_r($query, TRUE) . "</pre>";
-
Please Review my code and highlight my mistake
Psycho replied to Ehsan_Nawaz's topic in PHP Coding Help
@mac_gyver is correct about the proper way to prevent duplicates. However, when it comes to account creation you should never inform the user that there are existing values for user IDs or email addresses. Malicious users use such "errors" to data-mine a site to find out what are valid usernames. They can then do all sorts of nefarious activities from trying to brute force passwords, sending users fishing emails purporting to be from the company of the site, etc. Best practice is that when a user registers for a site (assuming the data they entered was valid) is to provide a message to them stating something along the lines of "Thank you for registering, an email has been sent to you with instructions to complete your registration". If the username & email are not duplicates, then send an email with a link to complete the registration. If the email is an existing one (whether or not the username is the same), then send an email with a statement that a registration was attempted with the email address, but one already exists (and probably include a link with instruction on how to reset their password as they may have forgotten they registered previously). If it was a malicious attempt the user will know that someone else tried to register with their email address. What I remember was based on the email address being the User ID. So, I'm not certain what you would want to do if only the User ID is a duplicate. But, you don't want to allow a malicious user to harvest your application for valid User IDs. -
To add some context to @Barand's response. The code you provided is not "complete". I would expect that line is contained within an echo statement that uses double quotes. Within a string defined with double quotes the brace {} characters have special meaning - they allow you to include a PHP variable directly within the quoted string. But, you cannot manipulate the variable within the braces - only include the value of it. So, similar to what Barand showed, you need to find where that string starts and before the declaration of the string you will want to define a new variable which is the view count +1000. Then replace the view count variable within the quoted string with the new variable that you have defined.
-
OK, I just realized that the prior code I posted has a problem - not a "technical" problem as it should do what it was intended to do. But, in retrospect, it allows for an attack vector. Ideally, you should not "leak" data about existing accounts. In the sample code I provided, a malicious user could identify if a particular email address was already used and then iterate through various usernames to see which one was used for that account (or vise versa). Instead, I would suggest that the account signup page always present the user will a message along the lines of "Your account request has been received, please check your email for more info". Of course, if there were data validation errors (e.g. not a valid email format, username blank or too short) you can present the user with those problems on screen. Going back to the "valid" submission and the potential duplicate errors, here is what I would do. Both the email and username or unique: Create a temp account and send an email with a link to confirm the account. Do not allow the user to "use" the account until it is confirmed. This prevents a malicious users from creating an account under someone else's email The email address is a duplicate (the username may or may not be a duplicate): Send an email to the existing user for that account with a message telling them that you are notifying them that a request was made to create a new account for their email address, but an account already exists The username is a duplicate, but the email address is not: This is a tough one. If the email is the user ID then it is covered in #2 above. But, in this situation it is quite possible that two people might want to use the same username, but you don't want to tell a malicious user about existing usernames. The best option I can think of is to send the sign-up user an email to the email address provided telling them the username is not unique. It still leaks data, but it would be harder to automate/brute force because they also have to check the email - although that can be automated as well.
-
The query that Barand provided to create a table shows how to create a table in the database with a unique constrain on a field. His earlier response where he linked to an old post of mine showed how you would execute an INSERT query against a table with a unique constraint. So, let's restate all this another way: You need to configure your table such that the username and email fields have a unique constraint. That will prevent the DB from accepting any INSERT\UPDATE requests that would generate duplicate values in either of those fields. But, in doing so, any such queries would fail and you need to execute your logic a little differently. Step 1 is to set up those fields in the DB to be unique. The query Barand provided would create a new table from scratch. You could also create an update query for the table to modify its structure for those unique constraints (e.g. "ALTER TABLE `table_name` ADD UNIQUE(`field_name`);"). Or, if you are like me, I just use PHP Admin's console to modify tables. Open the Table in PHP MyAdmin and select the "Structure" tab. In the list of fields, there is a column on the right where the label UNIQUE is shown. Just click that label to make that field unique in the table. Step 2. Now that those fields are unique IF someone was to try and create a new profile with a username or email address that already exists in the table, the query will fail. So, you need to approach the INSERT logic differently. The code Barand linked to previously provides an example. Basically, you want to wrap the INSERT (or an UPDATE) query within a try{} block. Then, if it fails, you will have a catch{} block to determine IF the failure was due to a duplicate constraint or not. Now, your case is a little unique since there will be two potential unique constraints and you will want to advise the user "which" of the fields (or both) are a duplicate, so you need more logic than the example provided. Here is some sample code. Note that I have not tested it and expect I may have made some typos, but the point is about showing what the logic would look like $pdo = new PDO("mysql:host=$hostname;dbname=$databasename;charset=utf8", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Enables exception mode try { //Attempt to execute the INSERT query $query ="INSERT INTO user2(username, email, password1, date) values(:username, :email, :password1, :date)"; $stmt = $pdo->prepare($query); $stmt->execute($arr); } catch (PDOException $e) { //Insert failed, check if it was due to duplicate constraint if ($e->getCode() == 1062) { // Duplicate username and/or email address - figure out which one(s) $query = "SELECT SUM(username=:username) as dupe_username, SUM(email=:email) as dupe_email FROM `photos`" $stmt = $pdo->prepare($query); $stmt->execute($inputArr); //This arr should only have the username & email values $result = $stmt->fetchAll(PDO::FETCH_ASSOC); $errors = ""; if($result['dupe_username']) { $errors .= "Username must be unique"; } if($result['dupe_email']) { $errors .= "Email address must be unique"; } } else { //Some other error occured throw $e;// in case it's any other error } }
-
In addition to echoing out the query, you would want to check any variables in that part of the code. The construction of the ternary operator line looks odd. Typically I would put the conditions (especially when there are multiple) within parens. Although, that does seem to work in my install. I see that the $upwalle value is being put into quote marks in the query, which is not proper for a numerical value - same with the id value. Also, you are ALWAYS running the query even if you are not intending to change the value. You should only run the query if you are intending to make a change. Here is some very verbose debugging. I also made some minor tweaks to the code. What are your results when running this: echo "Get user for id: {$video->user_id}<br>"; $up_user = $db->where('id', $video->user_id)->getOne(T_USERS); echo "Get wallet amount for user: "; $uploader_wallet = $up_user->$user->wallet; echo "{$uploader_wallet}<br>"; echo "Calculate change to wallet: "; $upwallet = ($sell_video == 0 && $uploader_wallet >= 1) ? .5 : 0; echo "{$upwallet}<br>"; echo "Check if upwallet value is not zero: "; if($upwallet > 0) { echo "True - run update query<br>"; echo "Construct query: "; $query = "UPDATE ".T_USERS." SET `wallet` = (`wallet` - {$upwallet}) WHERE `id` = {$video->user_id}"; echo "{$query}<br>"; echo "Run query: "; $db->rawQuery($query); echo "Complete"; } else { echo "False - do not run update query<br>"; }
-
How to convert text string into associative array using delimiters?
Psycho replied to Darkwoods's topic in PHP Coding Help
Here is how I would do that: function parseDataString($inputStr) { $outputAry = array(); foreach(explode("|", $inputStr) as $catAry) { list($catName, $catValuesStr) = explode("=", $catAry); $outputAry[$catName]= explode(",", $catValuesStr); } return $outputAry; } $text = 'cat1=hello,world|cat2=one,two|cat3=value1,value2'; $result = parseDataString($inputStr); print_r($result); -
Let me add to Barand's response. The typical process I take with forms is as follows: Form pages will POST to themselves When a form page loads it will first determine if a submission was made. If no submission is made, proceed to creating the form If a submission was made, then I will have the code go through form validation logic to ensure that all required data was submitted and that all submitted data is appropriate (e.g. a numeric field should have a numeric value, a date field should include a value that can be interpreted as a date, if something should match a DB id value, make sure that value exists, etc.) During the validation, for any errors that are encountered save appropriate error messages in an array/object, then proceed to creating the form. If no errors in validation, then execute the code to act on the submitted data - e.g. do a DB INSERT. Then redirect to a confirmation page. CREATE THE FORM: If there was no form submission or if there were errors in the data validation, create the form for user input. If there were errors, you can repopulate any valid data back into the appropriate fields so the user does not need to reenter. For errors, you can list them all at the top of the page (easy) or you can list them out above/below the individual fields where the errors occurred. You would just need to store the errors in the array/object in a way to correspond them to the input fields where they originated. I also like to create functions for building my various input fields. That way I can call the function with appropriate parameters so it can build the field either with the default/empty value or with a previously entered value. That way I don't have to write the same 6-10 lines of code to handle those two scenarios for every input field.
-
Loop through line items (Stripe) pulled from database
Psycho replied to tunnelboy's topic in PHP Coding Help
Unless there are additional fields in the query result set, you don't have all the corresponding fields shown in the example data. The example data has a "name" and "description". Your data has a description, but no name. You could use the SKU in place of the name. Also, I assume "unit_amount" is the price. Here is some (untested) code which should do what you need //Create the line items array $lineItems = array(); foreach ($resultID as $row) { $lineItems[] = array( "price_data" => array( "currency" =>"usd", "product_data" => array( "name"=> $row['sku'], "description" => $row['description'] ), "unit_amount" => $row['price'] ), "quantity" => $row['qty'] ) ); //Create full payment array $paymentArray = array( "success_url" => "https://www.domain.com/stripesuccess.php?sid={CHECKOUT_SESSION_ID}", "cancel_url" => "https://www.domain.com/cart.php", "mode" => 'payment', "line_items" => $lineItems ); //Set session for payment call $session = \Stripe\Checkout\Session::create($paymentArray); -
@Strider64 Maybe I am misreading your code, but I think I see a bug. In the block of code to consolidate the values into the array $attribute_pairs to perform the insert there is a condition that checks if the index is "id" - if so, it skips adding that value to the $attribute_pairs. But, there is no similar logic in the code block that dynamically creates the list of fields for the sql query. That code uses all the indexes in the $data array using array_keys($data). So, if the array $data did contain an index with the name "id" the query would fail because the number of fields for the insert would be one greater than the number of values. Either the "id" field needs to be excluded in the fields list OR the value if such a field exists can be set to NULL. Personally, I would leave such logic out since any code passing data to an INSERT function should only pass the relevant fields. Although, I could see the viability of including the ID if the function was doing an ON DUPLICATE KEY UPDATE. Or, I could be completely missing something and would appreciate pointing what that is.
-
I never saw any code that you posted. And, if you like your code, why are you asking? Checking to see if there is a duplicate BEFORE inserting the record creates the possibility for a race condition. Depending on the needs of your application this may not be a concern, but it is not the "right" way to do it. Here's an example of what can happen in a race condition. Two users submit the form for the same user ID that does not yet exist in the database. User #1's request hits the server first. The code checks to see if the username exists and see that it does not. Now, before the code can proceed to the insert, the request for User #2 reaches the server and does a Select statement to see if the value exists. Since User #1's request hasn't yet completed the insert statement, no duplicate will be found. User #1's request will be inserted, but since the validation for the duplicate check passed for User #2 is request will be inserted as well. But, of course, it will fail if there is a duplicate constrain - but then you'd have to add the same logic as you would need to check during the initial insert. Granted, a race condition requires two users to submit such records at almost the same instant. So, based on your application this may not even be a consideration. But, it is the right way to do it
-
If I understand your question correctly - yes. If there is an error because of a duplicate key constraint the entire record does not get added, even if other values were "OK". Here is some example code of how to use a try/catch for an INSERT with a duplicate check $pdo = new PDO("mysql:host=$hostname;dbname=$databasename;charset=utf8", $username, $password); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Enables exception mode try { $stmt = $pdo->prepare("INSERT INTO REGISTRY (uname, fname, lname) VALUES (:uname, :fname, :lname)"); $stmt->execute([$username, $firstname, $lastname]); } catch (PDOException $e) { if ($e->getCode() == 1062) { // Duplicate user } else { throw $e;// in case it's any other error } }
-
@LeonLatex We all have those moments where something obvious escapes us. I think the responses you have received have the tone that they do because the problem (as posed) shows a lack of discipline and it appears you were not even trying. Plus, you never provided the error messages you were getting. For example, how does one write all those lines of code and THEN discover all those syntax errors? I typically only write a "section" of code to do something specific, then run it to see that it is doing what I intend. Having typos is to be expected when writing code. What are you using as an editor? Most IDEs will highlight many basic typos.
-
Here is some very rough code on one way to approach validation logic. As I said before, with all the fields you need to validate, I would create functions or a class to do this. But, this will give you something to build on. Ideally, you would present the original input form and repopulate the valid values so the user doesn't have to re-enter everything again. You can show the errors at the top of the page or show them in-line with the input fields (or both). //Create an array to hold errors $errors = array(); //Get the learnign end date value $learning_actual_end_dateVal = isset($_POST['learning_actual_end_date']) ? trim($_POST['learning_actual_end_date']) : ''; //Check that not empty (i.e. required) if(empty($learning_actual_end_dateVal)) { $errors[] = "The learning end date is required"; } elseif (!strtotime($learning_actual_end_dateVal)) { $errors[] = "The learning end date must be a valid date value"; } //Get the participant complete course value $partcipant_complete_courseVal = isset($_POST['partcipant_complete_course']) ? trim($_POST['partcipant_complete_course']) : ''; if(empty($learning_actual_end_dateVal)) { $errors[] = "Participant complete course is required"; } // - - - Repease necessary validations for each field //Check if there were any validation errors if(count($errors)) { //There were validation errors $msg = "The following validation errors occured:<ol>"; foreach($errors as $error) { $msg .= "<li>{$error}</li>"; } $msg .= "</ol>"; } else { //There were no input validation errors // . . . attempt to process the data if(process_was_successful) { $msg = "The data was saved successfully"; } else { $msg = "There was a problem saving the data"; } } echo $msg;
-
OK, after looking at the code more closely, you need better validation logic than just checking all fields have "a" value. You should validate each field individually to make sure it has a value (if required) AND that the value is a valid value. E.g. a date should be a date, a number should be a number, etc. If only a few fields I would write the validation logic in-line. But, for this many fields, I would write separate functions for the validations based on the type of expected inputs. Those functions can be built to include parameters for such things as minimum/maximum inputs, required or not, etc.
-
What results ARE you getting? Are you getting a blank page or any output? EDIT: Looking at the logic flow there is an if() condition with a LONG list of conditions which will result in "$msg = '';" if the result is true. I am guessing that the condition is always true resulting in the message variable getting defined as an empty string. I also don't see that $msg is ever getting output regardless of what it is defined. Change the value for $msg on that one line to something and add a line at the end of the code to echo $msg to the page. Then you can see if it is hitting that branch of code, or the other branch where it is defined as "New Soft Skills Entry Added". IN any event that LONG list of conditions in the if() statement seem overly complicated.
-
That is generally how I would handle that logic as well. But, I would add a couple comments on that. Based on what I see in the OP's code it would seem that the 'dates' value should be unique. If only relying upon the id value being present or not, it could lead to duplicate records for the same 'dates' value. A unique constraint can be added to the column in the DB, but there will also need to be code to check for that condition. That can be done by doing a SELECT first to see if there is a record for that date (as is already being done), but that does allow for a race condition to allow duplicates. Depending on the needs of the application that may not be an issue. But, the proper way is to execute the INSERT statement and capture the error when it fails and check the error to see if it was due to a uniqueness issue. I'll be honest that I almost never do this:)
-
Unable to copy table data from one database to another
Psycho replied to wongle's topic in PHP Coding Help
Understand that the members here provide help out of good will and receive no compensation. When someone takes the time and energy to read through a person's post and provide a response - then the poster ignores the help that was provided it can certainly feel like the person helping was unappreciated or even disrespected. You posted 124 lines of code, of which almost 100 lines were unnecessary and add no value (those lines which simply populate object values into distinct variables). In fact, all those lines of code do nothing other than increase chances of bugs. Far too often I've seen people reassign the wrong value to a variable when doing such things. Instead of parsing the $_POST['array'] into an object, have it parsed into an array (look at the other attributes for json_decode). Then simply prepare your query with named placeholder and pass the array. Here is a quick rewrite that would accomplish the same thing with only about 25% of the code which is much more readable and maintainable. I may have made a typo or two, so itg may not work out of the box. There is a LOT more I would do to make this code better, but that's all the time I am willing to invest at this time try { $pdo = new PDO('mysql:host=' . db_host . ';dbname=' . db_name . ';charset=' . db_charset, db_user, db_pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //Read data into an array $data = json_decode($_POST['array'], TRUE); // Update the record //Create placeholders using a colon and the index names from the $data array //Ideally I would also list out the field names before the values $query = 'INSERT INTO contacts VALUES (null, :learner_id, :email, :phone, :title, :created, :status, :riskdv, :nin, :dob, :nextofkin, :address, :refname, :refagency, :refadd, :refemail, :refnum, :riskvoi, :riskar, :risksat, :riskpph, :rismpmh, :riskpos, :mentalhealth, :hisdrug, :exoff, :learndif, :hisalc, :fled, :rousl, :trave, :yplc, :psd, :hivadids, :hep, :phyneeds, :mentneeds, :meds, :subdose, :methmil, :alcdepend, :ivdrug, :onmeth, :compdetox, :drugdepend, :dip, :attcdp, :heroin, :canna, :meth, :coc, :crack, :solvents, :amph, :spice, :premed, :halluc, :subu, :alchevel, :otherinfo, :btype, :bamount, :bstartddate, :bnextpay, :padd1, :padd2, :preoff, :pendcase, :precon, :onprob, :ship, :cook, :money, :cleaning, :perh, :housing_benefit_claim_date, :housing_benefit_reference, :>housing_benefit_cancelled, :date_left_left, :number_of_times_at_reflections, :amount_of_service_charge_owed, :reason_for_leaving, :home_town, :town_moved_to, :imagesave, :datemovedin, :gpsurgery, :rflfull, :last_date_left, :med_cons, :addinfo, :compldetox, :complprog, :dietaryreq'); $stmt = $pdo->prepare($query); $result = $stmt->execute($data); var_dump($data); echo "Contact added at Kenobi"; } catch (PDOException $exception) { // If there is an error with the connection, stop the script and display the error. exit('Failed to connect to database!'); } -
Show title only if no featured image is present
Psycho replied to webyoda's topic in PHP Coding Help
Your question is not clear. When you say "I want to remove the placeholder image and show only the title if no featured image is present." are you saying that you just want the "text" part of the image above ("This is a draft post with a really long . . . ") to be displayed? If so, find that image on your server (i.e. image ID 272) and edit the image to remove the AT&T part of the image from the left side. However, if the "title" you are wanting to show is actual text, you can't do it within the code you shared. That code you showed determines an $featured_image_ID to use. Somewhere else in the code there is logic to use that image ID to display the appropriate image. What you could do is: 1. Make the else part of that code set $featured_image_ID to false 2. Find the part of the code that uses the $featured_image_ID and add a branch of code that will test if the value is false and, if so, shows the "title" text wherever it would get that from. -
I don't have any prior experience with mod_rewrite and am trying to create internal redirects to create a test harness for an application. I am using Apache on an XAMPP install. I have enabled mod_rewrite by modifying the conf file. I can get some rules to work that will modify the URL in the browser (i.e. external redirect), but I cannot get ones to work that do an internal redirect. For example, if I have two files: foo.html and bar.html If I use a Redirect in my .htaccess file RewriteEngine on Redirect "/foo.html" "/bar.html" Then attempting to load localhost:8080/foo.html is redirected in the browser address bar and in the loaded content. However, what I want to happen is to enter the URL for foo.html and only see the content for bar.html - i.e. the address in the browser should still display foo.html. Based on the examples, I've seen I need to use a RewriteRule. I have tried a couple different ways to do this (see below) based on info at apache.org. But when I do, I still get the content for foo.html. It's as if the RewriteRule is not doing anything. Here is the format I think I should be using so the url in the browser is not changed: RewriteEngine on RewriteRule "^/foo\.html$" "/bar.html" [PT] Here is another version using RewriteRule, that I think should work just like Redirect (which is working) RewriteEngine on RewriteRule "^/foo\.html$" "bar.html" [R] But, as stated above, neither of these work - I just get the content for foo.html (and the URL is unchanged). Any ideas? FWIW: Here is the actual logic I want to achieve using a RedirectMatch but, as stated above, I want to do with as an internal redirect which is hidden from the calling agent. RedirectMatch "/data/FAMStaticData/(.*).txt(.*)" "http://localhost:8080/index.php?file=$1"
-
And, for good measure, I will provide another option: array_chunk() $columns = 3; //Put results into an array $results = $pdo->fetchAll(); echo "<table>"; foreach(array_chunk($results, $columns) as $rowData) { echo "<tr>"; foreach($rowData as $record) { echo "<td>{$record['name']}</td>"; echo "</tr>"; } echo "</table>"; EDIT: Fixed inner TD tags
-
Appearance of user id when downloading to the file
Psycho replied to mikcsu120's topic in PHP Coding Help
Probably not what you really want, but it is what you asked for: $midPt = floor(strlen($content)/2); $file["content"] = substr($content, 0, $midPt) . $context['user']['id'] . substr($content, $midPt); -
Apparently the DateInterval class supports milliseconds, but the default method does not support it as an input value. You need to instead use the createFromDateString class of that method // convert your date to DateTime object $date = '10:00:00.500000'; $dt = new DateTime($date); // convert your period to $interval = '00:25:10.300000'; //Extract time parts list($hours, $minutes, $totalSeconds) = explode(':', $interval); list($wholeSeconds, $milliSeconds) = explode('.', $totalSeconds); //Create interval with milliseconds $intervalString = "{$hours} hours + {$minutes} minutes + {$wholeSeconds} seconds + {$milliSeconds} microseconds"; $interval = DateInterval::createFromDateString($intervalString); // Add interval to date $dt->add($interval);// Format date as you needecho $dt->format('H:i:s'); echo $dt->format('Y-m-d\TH:i:s.u'); //Output: 2021-11-12T10:25:10.800000
-
I assume you mean milliseconds. Can you describe what you are trying to accomplish? I.e. do you need\want to include milliseconds or is the problem that there is input data with milliseconds that is causing a failure? The solution to your problem could be very different based on what you are trying to accomplish. The manual shows that the DateTime class does support milliseconds. So, "where" in your code are you wanting to support milliseconds? Will it be the $date, will it be the defined interval, and/or do you need the milliseconds included in the output??? Need some more info.