Psycho
Moderators-
Posts
12,157 -
Joined
-
Last visited
-
Days Won
129
Everything posted by Psycho
-
Yeah, good catch. If that is the case, then I would propose the following. Keep the $header flag variable and make the initial value false. Then, in the loop, if $header = FALSE, set $header to the current row (i.e. the actual header row content). Then process all the other records as you normally do and put their values into $tempData. Then, after all the processing is complete, sort $tempData. Finally, when you write the data to the output file, first write $header then loop over $tempData writing all those rows.
-
How would you solve this engineering problem?
Psycho replied to yoursurrogategod's topic in Miscellaneous
I would say RFID as well, but I'd question the ability to "implant" them into the ball without affecting the properties of the ball or getting damaged from use. A barcode on the ball would not affect the ball at all, but it could get smeared or rubbed off. For a barcode, the ball could go through chamber where the ball is spun around until the barcode is read. -
Ah, here is the cause //Add record to temp array $tempData = $dataRow; That line is overwriting $tempData with the value of $dataRow (the current record). We want to add/append the current records to $tempData //Add record to temp array $tempData[] = $dataRow;
-
Did you verify the array contents before you do the sorting? FYI: You changed the sorting function I provided. what you changed wouldn't sort the array, but I don't think it would have removed the records. I gave you what should be a working solution for using usort() in this particular case.
-
Output the array before and after you modify it. I'm not following the logic you are using to try and sort the array. But, that is the problem. When you process the data you create an array of JUST the last names in the variable $ar. Then you use array_multisort() even though it is only a single dimensional array (sort() would have worked the same). But, THEN you do this foreach($ar as $value) { $tempData[$nameColumn] = $value; //putting back sorted names } Since the variable $nameColumn is not changing on each iteration of the loop, all that loop does is continually overwrite the index $nameColumn with each last name. So, when you are done the variable $tempData has all the records that were generated during the processing PLUS it has a new record which is not a sub array, but is only a single element of the very last last_name. So, when you try to use fputscsv() it is failing on that record. Don't use the $ar array at all or array_multuisort(). After processing the input, use usort() to sort the array. Check the manual on how to use it - but you will need to create a function I think this should work function sortMyArray($a, $b) { $nameColumn = 1; return strcmp($a[$nameColumn], $b[$nameColumn]); }
-
I'm not really sure what you are doing with that data, but I have a feeling the structure is all wrong - you definitely shouldn't need to store the username in all those tables. But, this *should* get you what you asked for. FYI: Your example result had the wrong days associated with the other data. SELECT p.username, p.startpoint, p.destination, GROUP_CONCAT(w.waypoint SEPARATOR ' -> ') AS waypoints, d.monday, d.tuesday, d.wednesday, d.thursday, d.friday, d.friday FROM postaride AS p JOIN waypoints AS w ON p.id = w.waypointid JOIN days AS d ON p.id = daysid WHERE p.username = '$session->username' GROUP BY p.id
-
Did you try the first one I provided?
-
<< Moving to MySQL Forum >> You need to do a JOIN from the patient table to the location table.This is the main purpose of using a "relational" database. Go out and do some research on using JOIN else you are not really using a database effectively. Also, the show and insurance columns have values of 1 and 2 - are those supposed to represent yes and no? If so, you should be using (0) false and (1) true. You can then use those values as logical Boolean values (TRUE/FALSE). Plus, you shuld rename the column pat_location to be location_id to match up with the related field name in the locations table. makes it much easier to associate your foreign keys I don't know what your DB query looks like right now, but this should get you going in the right direction: SELECT p.pat_id, p.pat_fname, p.pat_lname, o.office_name, p.pat_ins, pat_show FROM patients AS p JOIN offices AS o ON p.pat_location = o.office_id EDIT: If you change the show and insurance columns to 0/1 values and if you changes the pat_loc field to be named loc_id, you could simplify the query and you could get descriptive text ('Yes', 'No') returned for the two show and insurance fields. SELECT p.pat_id, p.pat_fname, p.pat_lname, o.office_name, IF(p.pat_ins, 'Yes', 'No'), IF(p.pat_show, 'Yes', 'No') FROM patients AS p JOIN offices AS o USING(office_id)
-
You need to look at those two functions and what they expect - you have the parameters messed up. date() takes a string as the first parameter to determine the format and an optional second parameter for a timestamp strtotime() takes a string representing a data and an optional second parameter of a timestamp. Your code has both of the parameters for those two function put into the strtotime() function. So,it is giving you that error because the second parameter you passed to strtotime() is not a timestamp. Try <?php echo date("d M Y", strtotime($order_row['od_date']));?>
-
Yep, I've done that too, but that seems more of a hack to me. Besides, making the resource file a .php (or other dynamically processed file) provides a great deal more flexibility. For example, with my previous problem above, the array of options could be dynamically generated from a DB query. So, there would be no need to create a new flat-file and put it out on the server - just create a new DB entry. In any event, there is no single correct solution. There are always different factors that make one solution preferable to others.
-
FYI: If you need a Boolean (i.e. 0 or 1) based upon a condition, there is no need to create an IF() condition that checks the condtition then sets a 0 or 1 value. Just use the condition as the value (it will return a 1 or 0). So instead of SELECT media.*, IF (ISNULL(ratings.ip), 0, 1) AS HasRated You could just use SELECT media.*, NOT ISNULL(ratings.ip) AS HasRated
-
Please go back and look at my instructions again. You should FIRST run a loop to process the data and make all the data transformations - putting the data into a temporary array. Then, AFTER THE LOOP IS DONE processing all the records, sort the data in the array as you need it. Lastly, iterate over the array to now write out the sorted. modified data to a new file. The code you have above doesn't really make sense. For one, it is trying to sort the records on each iteration of the loop - which is a waste of resources. Second, it is only sorting an array of the last names. You need the records sorted using the last name of the records. Use this as a framework and fill in the gaps <?php //Define the input/output files $inputFile = 'input.csv'; $outputFile = 'input.csv'; $nameColumn = 1; function formatName($name) { $nameArray = explode(' ', $name); //Extract the last name $lastName = array_pop($nameArray); //Format lanstname, rest of name and put back in string $name = $lastName . (count($nameArray) ? ', ' : '' ) . implode(' ', $nameArray); return $name } $dateColumn = 3; function formatDate($date) { //Add steps to transform the date // . . . // . . . // . . . return $date; } $inputHandle = fopen($inputfile, "r"); $outputHandle = fopen($outputFile, 'w'); if(!$inputHandle || !$outputHandle) { $errorMsg = ''; if(!$inputHandle) { $errorMsg .= "Error: nable to open input file.<br>"; } if(!$outputHandle) { $errorMsg .= "Error: Unable to open/create output file.<br>"; } die($errorMsg); } //Temporary array to hold processed data $tempData = array(); //Flag to not process the header data $headerRow = true; //Process the input data while (($dataRow = fgetcsv($inputHandle, 1024, ",")) !== FALSE) { //Do not process the first row of data if($headerRow) { //Set flag so additional rows will be processed $headerRow = false; //Modify the name $data[$nameColumn] = formatName($dataRow[$nameColumn]); //Modify the date $data[$dateColumn] = formatDate($dataRow[$dateColumn]); } //Add record to temp array $tempData = $dataRow; } //Records are processed. NOW add process to sort the tempData array // . . . // . . . // . . . //After records are storted, put into output file foreach ($lastnameArray as $dataRow) { fputcsv($outputHandle, $dataRow); } //Close the files fclose($inputHandle); fclose($outputHandle); ?>
-
Yeah, there might be a problem with html since the browser might try to parse it. However, I remembering having a problem years ago where an included .js file was used to define an array of values that were used to perform some dynamic actions based upon a select list. It worked fine until we needed to update that .js file. The browser was caching the file so changes were not being reflected for users who had previously accessed the page. By changing the file to .asp it resolved that problem.
-
I've learned a ton by visiting forums such as this one. Look at interesting problems people post (such as yours) then look at the solutions people provide. Then step through the solution line by line to understand what it is doing - and more importantly why. If you don't know what a function does, go look it up. Then, try and come up with your own solutions to peoples problems. Chances are others will respond before you have a chance to complete yours, but maybe you did some piece that was more efficient than what someone posts. You should NOT run another loop. You only need to run ONE loop. I already provided an explanation of how this could be accomplished Let me expand on this a bit: Have one loop to read the input file. When the loop runs do all of the data transformations you need to make, BUT do not write the data to the new file. Instead, after the transformations, copy the row into a new array. Then once the loop has processed all the line, run a function to sort the array. Lastly, run a foreach() loop on the array to write the data to the new file. To do the sorting, I would use usort() which allows you to create a custom function for the sorting logic.
-
PHP is only executed if the file is requested from the server as a PHP file. If the file is named .js, .html, .css then the server just picks up the file and sends it to the user. If the file is .php then the server will parse the file and execute the PHP code. Now, you can change the web server settings (assuming it is your dedicated server) to also process other file types for PHP code, but an easier alternative is to simply make the JavaScript include file a PHP file so it will be processed by the server before being sent to the user. JavaScript doesn't care about the file extension for files that are included. Heck you can even use PHP file for your stylesheets.
-
You never stated there was a header row! The reason why it works for the name column header is probably due to the line of code you asked me about previously to handle situations where there is only one "word" in a name to not add a comma/space. So, I assume the column header is a single word. If I had not put in that line, the name header would have been manipulated. The reason you are seeing the problem with the date header is because of this line $data[$BDColumn] = date('Ymd', strtotime($BD)); It is trying to convert the value to a timestamp and then into a formatted date string. The first part is failing since a date that cannot be interpreted as a date can be converted to a timestamp and is returning false. Then the date() function is using the value of FALST to try and create a formatted string and defaulting to something close to the EPOX date. I see two choices. 1) Skip the first row (or however many rows there are up to the header row). Just create a variable before the loop called $header and set to false. Then in the loop add something like this if(!$header) { $header = true; continue; } 2. Modify the code to not convert the string to a date. Start by first attempting to convert to a timestamp. If the value of that result is false do not change the value. $timestamp = stringtotime($BD); if($timestamp != false) { data[$BDColumn] = date('Ymd', $timestamp); }
-
I added that based on previous experience. Think about what would happen if you were to have a record that only had a single "word" for the name? For example: "Bono". The result would be "Bono, " with an extraneous comma and space after the name. In fact, if this was my project I would add a lot more such data handling (e.g. removing repetitive spaces). In plain English the logic works like this: 1. Explode the name into multiple words based upon spaces. 2. Remove the last word from the array 3. Create a new string starting with the last word that was extracted 4. IF there are additional words left in the array append a comma and space 5. Concatenate the remaining words with a space between them and append
-
mysql query on two tables , sum on one table and match with other table
Psycho replied to jkkenzie's topic in PHP Coding Help
Are there duplicates in table "b" with the same program, activity and year? If not, the query will be relatively simple: SELECT b.program, b.Activity, b.approved, SUM(a.expense) as TotalEpense, (b.approved-SUM(a.expense)) AS Difference, YEAR(b.approveDate) as YearOfApprovalAndUse FROM b JOIN a ON b.program = a.program AND b.Activity = a.Activity AND YEAR(a.transDate) = YEAR(b.approveDate) GROUP BY b.program, b.Activity, YearOfApprovalAndUse If not, the query is a little more complicated: SELECT a2.program, a2.Activity, SUM(b.approved) as approved, a2.TotalEpense, (SUM(b.approved)-a2.TotalEpense) as Difference, a2.YearOfApprovalAndUse FROM (SELECT a.program, a.Activity, SUM(a.expense) as TotalEpense, YEAR(a.transDate) as YearOfApprovalAndUse FROM a GROUP BY program, Activity, YearOfApprovalAndUse) as a2 JOIN b ON a2.program = b.program AND a2.Activity = b.Activity AND a2.YearOfApprovalAndUse = YEAR(b.approveDate) GROUP BY a2.program, a2.Activity, a2.YearOfApprovalAndUse -
The problem is how you are referencing the value of the select list. I don't think you can get it that way in all browsers. Assuming setSize() is called onchange of the select list, then you should call the function passing a reference to the select list. <input type="select" name="mySize" onchange="setSize(this);"> Yo can also greatly simplify the code: function setSize(selObj) { var sizeVal = selObj.options[selObj.selectedIndex].value; var hrefVal = '<?php echo $cart_url; ?>'; if (sizeVal > 0) { hrefVal = hrefVal + '&s=' + sizeVal; } document.getElementById('btnAddToCart').options.onClick = "window.location.href='" + hrefVal + "'" }
-
OK, here's one last improvement. If the input string does not have height/width tags, then they obviously can't be replaced. This will resolve that $width = 'width="540"'; $height = 'height="320"'; //Replace height/width tags with correct values $s = '<iframe src="http://www.youtube.com/embed/_LtZGQ65RNM" frameborder="5px" allowfullscreen></iframe>'; $s = preg_replace("#width=[\"']\d*[\"']#", $width, $s); $s = preg_replace("#height=[\"']\d*[\"']#", $height, $s); //If no height/width tags exist add them $firstSpace = strpos($s, ' '); if(!strpos($s, $width)) { $s = preg_replace("# #", " $width ", $s, 1); } if(!strpos($s, $height)) { $s = preg_replace("# #", " $height ", $s, 1); }
-
That won't work if the tags are not in the order you expect. This will work better. With this it doesn't matter where the height/width tags are located in the string and it won't matter if they use single or double quotes. $s = '<iframe width="640" height="420" src="http://www.youtube.com/embed/_LtZGQ65RNM" frameborder="5px" allowfullscreen></iframe>'; $s = preg_replace("#width=[\"']\d*[\"']#", 'width="540"', $s); $s = preg_replace("#height=[\"']\d*[\"']#", 'height="320"', $s);
-
The reason it is not working is how you are using str_repolace str_replace($s[1], "width='540'", $s[1]); str_replace() RETURNS a modified value. You aren't doing anything with the returned value. You should have assigned it to $s[1]. But, you don't even need to use str_replace() since you want to replace the whole value. Just do this if($s[1]!== ("width='540'")) { $s[1] = "width='540'"; } EDIT: Heck, you don't even need the if() statements - just set $s[1] and $s[2] to the requisite values $s = '<iframe width="640" height="420" src="http://www.youtube.com/embed/_LtZGQ65RNM" frameborder="5px" allowfullscreen></iframe>'; $s = str_replace('"', '\'', $s); $s = explode(' ', $s); $s[1] = "width='540'"; $s[2] = "height='320'"; $s = implode(' ', $s); But, I would probably implement a RexEx solution anyway since it won't matter where the height/width tags are in the string.
-
This will do what you need. The only thing you would need to do is define the correct column index for $nameColumn $inputfile = 'input.csv'; $outputFile = 'output.csv'; $inputHandle = fopen($inputfile, "r"); $outputHandle = fopen($outputFile, 'w'); if(!$inputHandle || !$outputHandle) { echo "Error: Unable to open file '{$csvfile}' or the ourput file '{$outputFile}'"; } else { $nameColumn = 1; while (($data = fgetcsv($inputHandle, 1000, ",")) !== FALSE) { //Retrieve the name $name = $data[$nameColumn]; //Explode the name $nameArray = explode(' ', $name); //Extract the last name $lastName = array_pop($nameArray); //Format lanstname, rest of name and put back in $data[$nameColumn] = $lastName . (count($nameArray) ? ', ' : '' ) . implode(' ', $nameArray); //Add record to new csv fputcsv($outputHandle, $data); } fclose($inputHandle); fclose($outputHandle); } EDIT: Based on your requirements you should probably read the data in, process it into an array, THEN after all processing is done, write to the new file. You'll need to do this to sort the results in the output file.
-
@Robert, Can you explain exactly what you are trying to achieve? What is the purpose of needing to change the name field, where is the data coming from, where is the file used after it is converted, etc. The reason I ask is that there may be better solutions than what you are asking.
-
Just because I was curious, I went ahead and created a regular expression that can take care of this in a single line: $text = preg_replace("#(^\|+)|(?<=\|)\|+|(\|+$)#", '', $text); Although, it's not really worth considering since it performs so fast, I tested this against my previous solution and found that the one which was faster was dependent upon the value to be replaced. The more occurrences of the delimiter used to split the string into an array caused the explode/implode method to be slower compared to regex. I also tried another method. trim() the delimiter, then create a recursive loop to remove repetitive instances of the delimiter. This was again faster/slower than the other methods based upon the number of delimiters (we are talking milliseconds here). This really has no real impact, I like to do these things to understand the more about the technology and thought I'd share. $text = trim($text, '|'); while(strpos($text, '||') !== false) { $text = str_replace('||', '|', $text); }