Jump to content

kicken

Gurus
  • Posts

    4,695
  • Joined

  • Last visited

  • Days Won

    177

Everything posted by kicken

  1. That should not have been changed. Change it back to the original $row = $data[$record];
  2. @slotegraafd then perhaps you have an additional problem or did not make the correct changes. Provide the updated code after you've made the changes. I copied your function from the original post and tested it with the sample data and changes and it works just fine for me.
  3. Your data array only contains 2 rows, but your function is written to expect a minimum of ROWS_PER_PAGE rows. Once the loop passes the end of your data array, $row = $data[$record]; Will result in $row being NULL because the index it's trying to access doesn't exist. What you need to do is change your function to only loop until the end of the array if there are not enough rows available. So you want the end of your loop to be either $firstRecord + ROWS_PER_PAGE or $rows which ever is smallest. This can be easily determined by using the min() function. So change your for loop to $lastRecord = min($firstRecord + ROWS_PER_PAGE, $rows); for($record = $firstRecord; $record < $lastRecord; $record++){ Additionally, the function currently generates invalid HTML due to various errors in the HTML strings. You'll want to address those as well.
  4. What do client_select_all() and client_count() return? Move them out of the function call and assign them to a variable, then var_dump that variable. $data = client_select_all(); var_dump($data); $rows = client_count(); var_dump($rows); display_table( array( "id" => "Id", "emailaddress" => "Email", "firstname" => "First Name", "lastname" => "Last Name", "salesperson" => "Salesperson", "phonenumber" => "Phone Number", "extension" => "Extension", "type" => "Type" ), $data, $rows, 1 ); They probably are not returning what you're expecting them too.
  5. Because you're not quoting your label properly. You're going to be generating a function call that looks like myfunction(8, The world's best cider); That's invalid Javascript, your label needs to be inserted as a valid string literal so that you'd end up with a call that looks like: myfunction(8, 'The world\'s best cider'); Such a thing can be done, but it's pain to do and this whole approach is the wrong way to accomplish this anyway so you shouldn't bother trying to figure out how to quote your string. There are varying way's to do this more correctly, but the way that would closest resemble your current approach would be to create your div node and then attach a click handler to it using javascript. It appears you're using jQuery which makes this fairly easy to do. Based on your usage of record[ i ] I assume this code is inside a simple for loop that is iterating over your records array. Given that, you'd end up with something like this as a replacement: var div = $(document.createElement('div')); div.text(records[i].label); div.click(function(record){ return function(){ myfunction(record.id, record.label); }; }(records[i])); list.append(div); If you've never seen the type of function declaration being used in the .click() method, that's what's known as an Immediately Invoked Function Expression (IIFE). It basically creates a new anonymous function which is then immediately executed and it's return value (another function) is then used as the parameter to the .click() method. This whole mess is necessary to make sure you're referencing the correct record when the item is clicked. If you just used record[ i ] directly it would not work as by the time you can click on the div i would point beyond the end of your list. This is because every iteration shares the same variable scope and thus modifications made to variables inside that scope. The IIFE generates a new isolated variable scope to work around that. You can read more about this scoping issue over on Stackoverflow if you're interested, they also go over various solutions to it from the most modern to the classics. What I prefer to do is make use of either jQuery's .each() function or Array's .forEach() function to loop over my array's instead of a simple for loop. This causes every iteration of the loop to run inside it's own unique variable scope so you can easily just reference the current item. records.forEach(function(record){ var div = $(document.createElement('div')); div.text(record.label); div.click(function(){ myfunction(record.id, record.label); }); list.append(div); });
  6. If you did $rows = $stmt->fetchAll(); print_r($rows); and just see Array() on the page that would indicate your query returned zero results. Make sure your query should return results if you manually run it with the same keyword value. If you continue having trouble, show us your updated code, including your attempt to fetch and display the results. Preferable as text and not a screenshot. Use the <> button on the editor toolbar and paste your code into the dialog that opens up.
  7. Apparently you need to add the Content-length header yourself, PHP won't add it for you when passing body content. The code I posted was just to get you on the right path, you'll have to troubleshoot/problem-solve yourself to get to a final working solution. Not necessarily. Since most API's are REST based these days, most places in my experience don't really bother with an SDK. At best, you get documentation of the end points and some example code. At worst you get the "common use case" documentation and have to figure everything else out yourself. The general idea is that anyone that is going to be trying to implement said API knows how HTTP works and knows how to make HTTP requests. If you're not well-versed on HTTP then you fall back to a library that can handle that part of it for you, which for PHP a popular choice these days is Guzzle. It's still up to you to know what request to make and what data to pass however. If they have explicitly advertised their API as being AJAX compatible then maybe it is. Maybe they just forgot to add the necessary CORS stuff. Since you mention it's a private API, potentially created just for you, then this is a real possibility. If it's not advertised as being AJAX compatible though then calling it from javascript probably isn't intended and the missing CORS stuff is likely intentional.
  8. It could look like many things, depending on what you need to accomplish. The simplest thing would just be something like: <?php $url = 'https://3rdpartywebsite.com/api'; $context = stream_context_create([ 'http' => [ 'method' => 'POST' , 'content' => file_get_contents('php://input') ] ]); echo file_get_contents($url, false, $context); Basically you just have PHP make the request to the API via whatever means (native streams, cURL, guzzle, etc) and return the result back.
  9. Instead of requesting the third-party API directly in your script you request a resource on your domain then you have your server forward that request to the third-party. So, for example, your XMLHttpRequest would be to the URL http://yourdomain.com/third-party/api Then on your server you could either make that point to a PHP script that runs the third-party request and returns the result, or configure your server to proxy the request with something like: ProxyPass /third-party/api "https://3rdpartywebsite.com/api" ProxyPassReverse /third-party/api "https://3rdpartywebsite.com/api"
  10. The functions you list all say they return false on an error such as a bad path, so check for that and log the details you need to determine which path is invalid so you can fix it. $result = $xpath->evaluate($path); if ($result === false){ trigger_error('Invalid XPath: '.$path, E_USER_WARNING); } If you want to prevent the built-in warning, then use libxml_use_internal_errors. libxml_use_internal_errors(true); $result = $xpath->evaluate($path); if ($result === false){ $errors = libxml_get_errors(); $errors = array_reduce($errors, function($carry, $error){ return sprintf("%s[%s:%d] %s\r\n", $carry, $error->file, $error->line, $error->message); }, ''); trigger_error(sprintf("Invalid XPath: %s\r\nErrors: %s", $path, $errors), E_USER_WARNING); } libxml_use_internal_errors(false);
  11. $myObject->result That is a simple array. The first element in a simple array is at index zero, so just display index zero if you want the first element. var_dump($myObject->result[0]);
  12. I'm not familiar with the ESP32 in particular but usually these micro-controller products are no where near capable of running an SQL database locally. For the ones that have networking capabilities, you can usually get some sort of TCP/IP connection going either via a minimal HTTP server or custom socket setup. It looks like that's what the whole MQTT thing is so that sounds like a good option. For the ones without networking capabilities you'd generally hook them up to a computer via a serial connection and connect to it that way. This is what I've usually done for my occasional Arduino based projects.
  13. This is just a matter of two separate levels of escape sequence processing that you need to wrap your mind around, which can be difficult at times. When you're setting a string in PHP first you have PHP's escape sequence processing. PCRE then has it's own level of processing that is done on the value that was passed to the function. For example, if you wanted to use \0 in a replacement literally rather than have it interpreted as a back reference you have to pass the string '\\0' as your replacement. If you're defining value in your PHP source as a string then you need to escape those slashes again for PHP's sake so you have $replacement = "\\\\0" If you get the value from a file or database you don't have to worry about the PHP level of escaping, but do still need to account for the PCRE level so you need your file to contain \\0 not just \0. It's not clear to me exactly what output you're expecting in your code sample. The addslashes call effectively mitigates PHP's escaping meaning $replacement is set to the literal value "<pre>\\\\</pre>". preg_replace will then see that and process it's own escaping which means the value it's working with is effectively "<pre>\\</pre>". That means your final replaced output would be "<div><pre>\\</pre></div>" If you have "<pre>\\\\</pre>" stored in your database and are pulling that value from there then you should get the same result, just don't run it through addslashes() as you don't have to deal with the PHP level of escaping things.
  14. Indeed, This is why you don't just load up the queue with a simple foreach loop. Instead you have your callback re-register itself as long as there is stuff to do. This works out because the queue will only run whatever callbacks were registered at the time it started running. Any newly added callbacks will be delayed until the next event loop cycle. If there are any callbacks in the future tick queue you can see that the event loop will set it's timeout to zero so that it won't block. It does still test for stream activity so it will still be able to dispatch and process incoming I/O as it needs it, it just won't wait around for it.
  15. Ideally you don't ever block if you have work to do. In general, as long as you can do work you should be doing work. It's when you cannot do any work that you want to yield control to the event loop. That's usually when you're waiting for I/O from somewhere. That said, if the work you can do is going to take along time without having any sort of natural blocking point (I/O) but you don't want to block your other tasks for that long then you need to start trying to find ways you can break up that task so you can yield control occasionally. That's generally known as cooperative multitasking. In the case of sending a bunch of emails, an obvious way to break that up would be to yield control after each email. If other tasks are pending in the queue then they will get a chance to do their work. If not, control will return back to your original task immediately. The only time the process should be blocked is when either there are no tasks at all or all tasks are waiting on I/O. I haven't done anything with react in a long time but as far as I can tell what you'd want to do is use the futureTick function to schedule more work and break up your task. For example: <?php class EmailQueue { private $loop; private $emailList; private $isTicking; public function __construct(LoopInterface $loop){ $this->loop = $loop; $this->index = 0; $this->emailList = new SplQueue(); $this->isTicking = false; } public function queueEmail(string $to, string $message){ $this->emailList->enqueue([$to, $message]); if (!$this->isTicking){ $this->tick(); } } private function tick(){ if ($this->emailList->isEmpty()){ $this->isTicking = false; } else { $this->isTicking = true; $this->loop->futureTick(function(){ $this->processMessage(); $this->tick(); }; } } private function processMessage(){ [$to, $message] = $this->emailList->dequeue(); //Send message. } } $loop = Factory::create(); $queue = new EmailQueue($loop); //load up the queue with a bunch of emails. $loop->run(); When you first queue up an email, it will call the tick() function. That function will check if there are any messages in the queue. If there are it registers a callback to be executed on the next cycle of the event loop. When that callback is executed it will dequeue one message and send it, then call tick() again which causes the cycle to repeat if necessary. As long as there is email in the queue this will constantly work through the queue while still allowing the loop to trigger other work items.
  16. var jsonObj = request.result; This sets jsonObj to undefined because XMLHttpRequest doesn't have a result property. You need to read and parse the responseText property. XMLHttpRequest is an older standard. You might also want to look at the more modern fetch() API instead.
  17. Your starting array is in a strange format. You have your outer array with 3 sub-array lists. Each element in that sub-list is then a single-item array with an index matching it's parent index. I'd probably see if that can be cleaned up and better organized first if possible. The code would end up cleaner and easier to understand if you could remove one or two of those levels. It seems like you could probably just form one single list instead of the nested setup you have now. For example: array ( 0 => array ( 'dataAula' => '2020-09-21', 'tempos' => '4', 'tempos2' => 'Segunda', 'total' => 4, ), 1 => array ( 'dataAula' => '2020-09-22', 'tempos' => '4', 'tempos2' => 'Terça', 'total' => 8, ), //... ); At the vary least it should be possible to remove the third level of the array you currently have. That said, what you want to do is possible with your setup. You need another loop though as you need to loop over the outer array first. Each item of that loop is another array you need to loop over. Each item of that inner loop is another single-element array that you need to "unwrap" so to speak to get access to the data. $result = []; //Loop over list $array, each item of which is another list. foreach ($array as $level1){ //Loop over the sub-list. foreach ($level1 as $level2){ //$level2 is a single-element array with the same index as it's parent. Extract that single element. $level2 = current($level2); $date = $level2['dataAula']; if (isset($result[$date])){ $result[$date]['tempos'] .= '+' . $level2['tempos']; } else { $result[$date] = $level2; } } }
  18. Yes, I did this year ago also just like you. As I said though, this is something that has never been officially supported in any way, nor has it ever been reliable. I understand what you want. You want your loading gif to appear immediately and then your script continue and outputting updates as it goes. Whether that will work or not depends on a lot of things outside of PHP's control so it's not something you can rely on. The proper way to do something like that is to load a simple page first, then use javascript to update it over time. This will probably require re-working your script to run over multiple requests and do the work in the background some way. Either that or just put a notice up that it might take a while and do without any kind of progress indication. If you have some prior page that links to your script, you can have it display the loading indicator prior to making the request. The browser should leave it up until the request is complete.
  19. You're attempting to do something that's always been a fundamentally flawed idea. That fact that it may have worked before comes down mostly to luck/implementation details and not because if was ever an officially supported feature. ob_flush/flush does still make PHP send it's output. The problem (then and now) is that there might be other buffers in the chain that PHP has no way to control such as you web-server's buffer, a caching proxy server buffer, the browser's buffer, etc. If you want some kind of a loading animation for your page, you need to output a page that's just your loading animation and then use Javascript to fill in the content after by loading it in the background using ajax / fetch().
  20. The delimiters don't matter really, though by using # you could skip escaping the / in the expression. Normally I'd probably use something other than / as well in a situation like this just to avoid that escape, but I was to lazy to change them on the website. You need the start and end of string anchors though if you want to enforce the value strictly. Without them it just looks for the pattern somewhere in the string, not that the string is exactly that pattern. So your regex would also match if: $_POST['ay'] = 'I want to attend in the (2020/21) academic year';
  21. If you want the entire string to be in that format, you need to use the start (^) and end ($) anchors and put your pattern in between. Your regex currently also only looks for digits and /, but they can be in any order. If you want to enforce that strict format you need to look 4 digits followed by a slash followed by 2 more digits. Given the above, you end up with a regex such as /^\(\d{4}\/\d{2}\)$/
  22. When you're trying to re-create a flow, the best thing to do generally is to use either the browsers developer tools or something like fiddler to monitor what exactly the requests being made are, then figure out how to re-create those requests. Sometimes it's as simple as loading a URL, other times it's more complicated and involves parsing the previous pages source for various details. The process is something you general have to figure out on a case-by-case basis so it'll be difficult for anyone to really guide you without at lot of details.
×
×
  • 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.