Jump to content

Psycho

Moderators
  • Content Count

    11,957
  • Joined

  • Last visited

  • Days Won

    114

Psycho last won the day on August 14

Psycho had the most liked content!

Community Reputation

556 Excellent

About Psycho

  • Rank
    Move along, nothing to see here

Profile Information

  • Gender
    Not Telling
  • Location
    Canada

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Unfortunately, there is no perfect answer. Every "spam" system can have different things it looks for to determine what is spam. If there was a simple list of things to do, then every spammer would do those things so their email would not wind up in spam. You will want to do some research, but here a a few things to consider: 1. The server sending the email should be an "authorized" sender for the domain in the from address. In this case you are using Gmail to send an email on behalf of 'bidsoliciationapp.com'. There are ways to change the MX records (similar to DNS records) to authorize a server for a particular domain. But, I think that would require reaction from Google as well if you want to use your current configuration. You may need to use a Google from address or use a dedicated emailing service that can help with the right configuration. Of course, that would cost money. I only understand these things tertiarily, so some of my 'facts' may be slightly off. 2. The name of the domain could be problematic with words such as "bids", "solicitation" could raise a red flag. 3. Content: I would not start with a "Hello Bob, please click <here> . . . " It just seems like something I would see in a Spam email. I don't know if that is part of the problem or not. What you can do: Set up an account with a few different email providers and send some samples of your current emails to them to see if any are flagged as spam. If so, then change the content to something completely innocuous. Does that go through w/o being detected as Spam? If yes, then you know it is the content causing the detection. If not, then it is likely something to do with the configuration/meta data.
  2. Then get rid of all the nested loops! That is what is sucking up all your memory. It would also help if you read the documentation. The documentation for the spreadsheet code you are using mentioins there is a memory problem and how to resolve it. Based on their recommendations, I would follow Barand's earlier advise to put the data into an array first. <?php //Run ONE Query to get the data for ALL the salespeople $sql="SELECT x, y, z . . "; //run the query $result =odbc_exec($connect,$sql); if(!$result){ exit("Error in SQL"); } //Create array to hold the data $salesData = array(); //Iterate through the data and populate a structured array while ($row = odbc_fetch_array($result)) { $salesData[$row['salespersonID']][] = $row; } //Iterate over the structured array to create the spreadsheets foreach($salesData as $salesPersonID => $salesPersonData) { //make a new spreadsheet object $spreadsheetObj = new Spreadsheet(); //Add all the standard setting and content (e.g. headers) //Iterate over the records for the current salesperson and all to the spreadsheet foreach($salesPersonData as $salesData) { //Refernece the records using the $salesData array } //I assume there would be a step here to write the current sheet to disk ########################### ## Disconnect and unset the spreadsheet object ########################### $spreadsheet->disconnectWorksheets(); unset($spreadsheet); }
  3. I am curious as well. Why not just create each spreadsheet when requested by a user. I.e. User selects to see the data for Salesperson X - create the spreadsheet for Salesperson X only at that time. In any event, you have a lot of loops going on with many "expensive" operations being repeated in those loops. For example, you're still running individual queries for each salesperson. Run ONE query to get all the data - THEN create your output for each spreadsheet from that query. You're also recreating the $spreadsheet object for each salesperson. Not sure, but that may not release any memory for the previous object. You shoudl create the object ONCE then create multiple spreadsheets using that object.
  4. I'm not going to bother even reading through your code. You need to STOP, take a breath, and come up with a logical, repeatable process for form validations. Here is an example of the start of a process you could follow: <?php //Create arrays of valid values for fields using a 'list' (e.g. select, radio group, etc.) // - the array index represents the value // - the array value represents the label // This could be created from a DB query if the lookups are stored there. // Use this for BOTH the validation AND for creating the select list, radio group, etc. // FYI: You can't assume the value passed for a select list is one you provided!!! $field4Values = array( 1 => "Blue", 2 => "Green", 3 => "Red", 4 => "Yellow" ); //Create array to hold the errors $errors = array(); //Check if form was submitted // I usually have form pages submit to themselves so I can repopulate fields // if there are errors. So, should only do validations if the form was submitted if($_SERVER['REQUEST_METHOD']=='POST') { //Trim all the post values // You have to determine if this is appropriate (can some legitimate value have // beginning/ending whitespace?). Also, can't use array_map like this if the // post fields contain multi-dimensional arrays array_map('trim', $_POST); //Validate the fields //Field is required if($_POST['field1']$_POST['field1']=='') { $errors['field1'] = "Field 1 is required"; } //Field is NOT required, but must be a number if($_POST['field2']!='' && ) { $errors['field1'] = "Field 2 must be a number"; } //Field IS required, and must be a number if($_POST['field3']=='') { $errors['field3'] = "Field 3 is required"; } elseif(!ctype_digit($_POST['field3'])) { $errors['field3'] = "Field 3 must be a number"; } //Field must contain a values in a predetermined list if(!array_key_exists($errors['field4'], $field4Values)) { $errors['field3'] = "Field 4 is not a valid color"; } // And so on, and so on //Create 'helper' functions for more complicated validations: //Validation process complete - see if there were errors if(empty($errors)) { //Add logic to process the form data - e.g. database insert/update //Redirect to another page: e.g. update successful, listing, etc. //Read up on PRG - (Post, Redirect, Get) for form processing header('http://mydomain.com/formsuccess.php'); exit(); } //If there were errors, code continues to form display logic } //Include the code to display the form //This should display the errors if any exist //and populate any fields with previously POSTed values include('formpage.php'); ?>
  5. You don't mention anything about HOW you want to change it, so there is no way we can provide much guidance. Your script is calling a function "PT_LoadPage". That function takes two parameters. The first appears to be a description of the "type" of output: e.g. a list or content. The second is the array. I would assume those two "types" of output expect an array in the exact configuration as you are passing them now. So, you will need to find the function and modify that. However, if all you want to do is substitute a value in the current array with something else you can either change the process that runs the query to generate the data to create an array with the same structure (but different values) or add some process to change va;lues in the array. But, since you've not provided any description of what/how you want to change the output - I don't know what to say.
  6. Yes, you should combine them - never run queries in loops. I would suggest modifying the names of your fields in those two tables. Both tables have fields called "name" and "message". It is possible to run a JOINed query on those two tables, but you will need to create aliases - otherwise it is ambiguous when trying to reference "name" in the result set. E.g. in the SELECT condition you could do this to add aliases SELECT m.message_ID, m.name as messageName, m.subject, m.message, r.reply_ID, r.name as replyName, r.reply_day, r.message as reply But, why go to the trouble of using aliases when it would make more sense to rename those fields to be unique? Using "message_ID" in both tables makes sense since is a primary/foreign key relationship. Anyway, here is how you could combine those queries. SELECT m.message_ID, m.name as messageName, m.subject, m.message, r.reply_ID, r.name as replyName, r.reply_day, r.message as reply FROM `messages` m JOIN `replies` r ON m.message_ID = r.message_ID ORDER BY `message_ID` ASC, `reply_ID` DESC LIMIT 0,200
  7. Agree. Although I would say there is a case where "protecting a form field" is directly related to "outputting user-supplied data". When populating a form field value (e.g. when editing a record) it would be appropriate to escape the content in the value parameter. Not sure if that is what the OP is asking about since what is being asked doesn't exactly make sense.
  8. I would be interested to know WHY you are wanting to do this. What are these "duplicate" records for and if their data is the same as the 'parent' why do you need to refer to the parent for the data? Also, since each element doesn't have a defined index I'm not sure how you want to make the reference. Do you just want to store the first element value (e.g. '10') in the child element? This would be a lot easier to work with if the elements also had named indexes. Anyway, here is a possible solution. Note, once you run this IF you change one of the referenced values in a parent element it WILL be reflected in the child elements. function mapArrayReferences(&$inputArray) { //Create array to map unique value sets $mappingAry = array(); foreach($inputArray as $elementKey => $element) { //Remove the first element off the array array_shift($element); //Create a hash of the remaining array $hash = md5(implode("|", $element)); //Check if the hash already exists in the mapping array $parentKey = array_search($hash, $mappingAry); if($parentKey !== false) { //Change the current element values to refer to parent $inputArray[$elementKey][1] = &$inputArray[$parentKey][1]; $inputArray[$elementKey][2] = &$inputArray[$parentKey][2]; $inputArray[$elementKey][3] = &$inputArray[$parentKey][3]; $inputArray[$elementKey][4] = &$inputArray[$parentKey][4]; } else { //Add new parent to mapping array $mappingAry[$elementKey] = $hash; } } return; } Usage $dataAry = array( array("10", 25, 31, "Yes", "No"), array("20", 21, 18, "No", "No"), array("30", 11, 47, "No", "No"), array("40", 14, 60, "No", "No"), array("Ten", 25, 31, "Yes", "No"), array("dix", 25, 31, "Yes", "No"), array("twenty", 21, 18, "No", "No") ); //Map child elements to parent element values mapArrayReferences($dataAry); //Change a parent element value $dataAry[0][2] = 99; print_r($dataAry); Output
  9. That is NOT what Barand suggested. You don't create some arbitrary array of salespeople. You use your query results to dynamically create the array BEFORE you start creating your output. You should really break up your functionality into distinct functions/files/etc. It will make things so much easier. Try adding better organization to your code and you know exactly where the problem is based on the error. Anyway, I did my best to rewrite the code using Barand's suggestion and adding a better structure. Obviously I can't test it as I don't have your DB, but hopefully thi swill work or you can fix whatever minor errors I may have introduced <?php //call the autoload require 'vendor/autoload.php'; //load phpspreadsheet class using namespaces use PhpOffice\PhpSpreadsheet\Spreadsheet; //call iofactory instead of xlsx writer use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Style\Fill; ############### Begin styling arrays ############### //table head style $tableHead = [ 'font'=>[ 'color'=>['rgb'=>'FFFFFF'], 'bold'=>true, 'size'=>11 ], 'fill'=>[ 'fillType' => Fill::FILL_SOLID, 'startColor' => [ 'rgb' => '538ED5' ] ] ]; //even row $evenRow = [ 'fill'=>[ 'fillType' => Fill::FILL_SOLID, 'startColor' => [ 'rgb' => 'F2F2F2' ] ] ]; //odd row $oddRow = [ 'fill'=>[ 'fillType' => Fill::FILL_SOLID, 'startColor' => [ 'rgb' => 'FFFFFF' ] ] ]; ############### End styling arrays ############### ############### Begin Data Abstraction ############### // Create DB connection $connect =odbc_connect(removed); if(!$connect) { exit("Connection Failed: " . $connect); } //the sql query $sql="SELECT ARPINVOICEDATE ,ARJSALESEMPLOYEEID ,ARPARINVOICEID ,UARPSALESORDERNUMBER ,ompCreatedDate ,ARPCUSTOMERORGANIZATIONID ,CMONAME ,CMOCUSTOMERGROUPID ,cmoState ,ARLINVOICEQUANTITY ,ARLPARTID ,ARLUNITOFMEASURE ,ARLPARTGROUPID ,ARLFULLEXTENDEDPRICEBASE ,ARLEXTENDEDDISCOUNTBASE ,ARLEXTENDEDPRICEBASE ,ARLSALESORDERID ,case when arlPartGroupID = 'PROMO' then 4.00 when arlPartGroupID = 'DC' then 2.00 when cmocustomergroupid = 'LIST' then 5.00 when cmocustomergroupid = 'VOL' then 4.00 when cmocustomergroupid = 'VOL2' then 4.00 when cmocustomergroupid = 'VOL2' then 5.00 else 5.00 end as comission_percent FROM M1_KF.dbo.ARInvoices INNER JOIN M1_KF.dbo.ARInvoiceLines ON arpARInvoiceID = arlARInvoiceID LEFT OUTER JOIN M1_KF.dbo.organizations ON ARPCUSTOMERORGANIZATIONID = cmoorganizationid LEFT OUTER JOIN M1_KF.dbo.arinvoicesalespeople ON arparinvoiceid = arjarinvoiceid left outer join M1_KF.dbo.SalesOrders on ompSalesOrderID=UARPSALESORDERNUMBER where arlsalesorderid !='' and arpPostedDate >='05-01-2019'and arpPostedDate <'06-01-2019' and arlPartGroupID not in('FRT') ORDER BY ARJSALESEMPLOYEEID,arpARInvoiceID"; //run the query $result =odbc_exec($connect,$sql); if(!$result){ exit("Error in SQL"); } //Process the data into an array $salesData = array(); while ($row = odbc_fetch_array($result)) { //loop through the data $salesData[$row['ARJSALESEMPLOYEEID']][$row['arpARInvoiceID'] = $row; } //Close connection odbc_close($connect); ############### End Data Abstraction ############### ############### Begin Create Spreadsheet ############### //make a new spreadsheet object $spreadsheet = new Spreadsheet(); //get current active sheet (first sheet) //set default font $spreadsheet->getDefaultStyle() ->getFont() ->setName('Arial') ->setSize(10); //Loop through records for each sales data $lastSalesID = false; foreach($salesData as $salesId => $salesData) { //Check if this is a different sales id than the last if($salesId !== $lastSalesID || ) { //If not the first salesID, create a new worksheet if($lastSalesID !== false) { $spreadsheet->createSheet(); } //Set new last sales ID $lastSalesID = $salesId; //Create the worksheet header data //heading $spreadsheet->getActiveSheet()->setCellValue('A1',"Comission"); //merge heading $spreadsheet->getActiveSheet()->mergeCells("A1:P1"); // set font style $spreadsheet->getActiveSheet()->getStyle('A1')->getFont()->setSize(20); // set cell alignment $spreadsheet->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER); //setting column width $spreadsheet->getActiveSheet()->getColumnDimension('A')->setWidth(25); $spreadsheet->getActiveSheet()->getColumnDimension('B')->setWidth(20); $spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth(20); $spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(30); $spreadsheet->getActiveSheet()->getColumnDimension('E')->setWidth(25); $spreadsheet->getActiveSheet()->getColumnDimension('F')->setWidth(25); $spreadsheet->getActiveSheet()->getColumnDimension('G')->setWidth(25); $spreadsheet->getActiveSheet()->getColumnDimension('H')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('I')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('J')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('K')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('L')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('M')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('N')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('O')->setWidth(10); $spreadsheet->getActiveSheet()->getColumnDimension('P')->setWidth(10); //header text//current row $spreadsheet->getActiveSheet() ->setCellValue('A2',"INVOICE DATE") ->setCellValue('B2',"SALESPERSON") ->setCellValue('C2',"INVOICE ID") ->setCellValue('D2',"ORDER ID") ->setCellValue('E2',"ORDER DATE") ->setCellValue('F2',"CUSTOMER ID") ->setCellValue('G2',"NAME") ->setCellValue('H2',"GROUP ID") ->setCellValue('I2',"STATE") ->setCellValue('J2',"QTY") ->setCellValue('K2',"PART") ->setCellValue('L2',"UOM") ->setCellValue('M2',"GROUP") ->setCellValue('N2',"GROSS") ->setCellValue('O2',"DISCOUNT") ->setCellValue('P2',"NET"); //set font style and background color $spreadsheet->getActiveSheet()->getStyle('A2:P2')->applyFromArray($tableHead); //Output invoice records $lastInvID = false; $exrow = 3; //Set starting row for current sheet foreach($salesData as $invId => $invData) { $spreadsheet->getActiveSheet() ->setCellValue('A'.$exrow ,$data['ARPINVOICEDATE']) ->setCellValue('B'.$exrow ,$data['ARJSALESEMPLOYEEID']) ->setCellValue('C'.$exrow ,$data['ARPARINVOICEID']) ->setCellValue('D'.$exrow ,$data['UARPSALESORDERNUMBER']) ->setCellValue('E'.$exrow ,$data['ompCreatedDate']) ->setCellValue('F'.$exrow ,$data['ARPCUSTOMERORGANIZATIONID']) ->setCellValue('G'.$exrow ,$data['CMONAME']) ->setCellValue('H'.$exrow ,$data['CMOCUSTOMERGROUPID']) ->setCellValue('I'.$exrow ,$data['cmoState']) ->setCellValue('J'.$exrow ,$data['ARLINVOICEQUANTITY']) ->setCellValue('K'.$exrow ,$data['ARLPARTID']) ->setCellValue('L'.$exrow ,$data['ARLUNITOFMEASURE']) ->setCellValue('M'.$exrow ,$data['ARLPARTGROUPID']) ->setCellValue('N'.$exrow ,$data['ARLFULLEXTENDEDPRICEBASE']) ->setCellValue('O'.$exrow ,$data['ARLEXTENDEDDISCOUNTBASE']) ->setCellValue('P'.$exrow ,$data['ARLEXTENDEDPRICEBASE']); //set row style $rowStyle = ( $exrow % 2 == 0 ) ? $evenRow : $oddRow; $spreadsheet->getActiveSheet()->getStyle('A'.$exrow.':P'.$exrow)->applyFromArray($rowStyle); //increment row $exrow++; } //Create filter for current sheet //define first row and last row $firstRow=2; $lastRow=$exrow-1; //set the autofilter $spreadsheet->getActiveSheet()->setAutoFilter("A".$firstRow.":P".$lastRow); } } ######## OUTPUT THE FILE ################ //set the header first, so the result will be treated as an xlsx file. header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); //make it an attachment so we can define filename header('Content-Disposition: attachment;filename="result.xlsx"'); //create IOFactory object $writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); //save into php output $writer->save('php://output');
  10. Also, you need to look into how to make your capturing conditions "greedy" or "non greedy". By default, matches will be greedy. So a condition such as "A(.*)B" with the string "A1B A2B A3B" would find one match "1B A2B A3" - everything form the first "A" to the last "B". If you wanted to find all the values between each set of A/B, then you need make the match non-greedy - "A(.*?)B"
  11. This is not a use case where you should be using RegEx. A better solution is to use a DOM parser such as Simple HTML Dom. You can easily find elements by searching by multiple parameters - such as tag and class. Using the above content you could get every DOM object for every Div with the class "previewSegment" - which would appear to hold all the contents for each title. Then use the DOM parser to get the text within the "previewTitle" div and the "previewLabel" (which is the runtime). That is how you should be doing this. But, it can be done via RegEx, I just wouldn't advise it. $regEx = "#<div class=\".*?previewLabel[^\"]*\">(.*?)</div>.*?<div class=\"previewTitle\">(.*?)</div>#is"; preg_match_all($regEx, $content, $matches, PREG_SET_ORDER); $titles = array(); foreach($matches as $match) { $titles[] = array( 'title' => $match[2], 'duration' => $match[1] ); } echo "<pre>".print_r($titles, 1)."</pre>"; Example output:
  12. array_rand only returns the key (or keys) of the randomly selected items. So, that line would only return a 0 or 1 - which is not helpful without the original array to get the value from. It makes more sense to create an array as a variable first, the use array rand to get the value like so: $values = ['orange', 'apple']; $randomValue = $values[array_rand($values)];
  13. However, I would strongly suggest putting the error condition first as Barand did in his examples. The reason is that it makes it easier to "see" the condition that creates the error. Plus, if your error condition does a redirect, you don't even need to enclose the main code in an else clause. This makes the code easier to read/maintain. if($foo == 'bar) { include('some_error_page.php'); exit; } //Continue with the main logic w/o else clause Also as Barand's stated, there is no reason to create a variable when you have a perfectly good condition. But, if you do need to create a flag based on a condition, do not do it this way if($numberoflabels > 4) { $too-many-labels = TRUE; } Instead do this: $too-many-labels = ($numberoflabels > 4);
  14. So, now you are going to post the REAL code? How nice of wasting people's time. You still haven't done what has been suggested multiple times - output your variables so you can SEE what they are. Instead of putting your query string directly in the prepare() statement, create it as a variable. Also, the full query that you are now showing us could be the problem. Even if there is matching data an error in the JOIN criteria could prevent any results. Replace this for the relevant section in your code and look at the results to see if the query and param values are what you think they are. // // FINDTOTAL RECORDS IN SEARCH RESULTS // $placeholderStr = join(",", $placeholders); $query = "SELECT COUNT(*) as tot FROM ( SELECT id FROM ( SELECT v.id , v.title , GROUP_CONCAT(tag SEPARATOR ' ') as alltags FROM product v JOIN product_tag t ON v.id = t.product_id GROUP BY v.id ) v JOIN product_tag t ON v.id = t.product_id WHERE tag IN ({$placeholderStr}) GROUP BY id HAVING COUNT(t.tag) = ? ) found;"; echo "<b>Query:</b><pre>{$query}</pre><br>\n"; echo "<b>Params:</b><pre>".print_r($params, true)."</pre><br>\n"; $res = $db->prepare($query); $res->execute($params);
  15. First, I would strongly suggest that you first use more appropriately named variables. Don't create a generic variable and then try and reuse it. What does "$params" represent? Parameters obviously, but parameters for "what"? In this case $params is an array that keeps getting additional values appended to it - and those values are logically different "types" of values. Also, a prepared query will expect an array with the same number of parameters as placeholder in the query. Second, output your variables to the page to "see" what they contain. $params does not contain what you think it does when you are using it.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.