Jump to content

Phi11W

Members
  • Posts

    152
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by Phi11W

  1. This is almost always the wrong way to do things. You cannot guarantee that this update process will run every, single day. This is Technology - stuff happens. Updating every record is a lot of [unnecessary] work for your database to do and will, almost certainly, lock the entire table, causing other issues. Showing stuff to Users is not the database's job. You'll write an Application that the Users interact with and that will show them your "remaining time". I'm sorry, but why? Users these days want instant responses, not arbitrary and artificially-enforced delays. If you are interested in a particular date & time, then work out when that is and store that. You never need to change it, "in bulk" or at all, Your application can calculate how long it is until "Real Time" catches up with it and show that duration to the User, no matter what they do in the meantime (refreshing, logging off-and-on again, etc. ), and You can easily tell once you have reached it in a SQL query. Keep it Simple ... Regards, Phill W.
  2. I would go further and say you must not "select data in order to decide to insert or update it". That road leads to Race Conditions. Whist "on duplicate update" exists and works well, I would suggest making a conscious decision about which is the more likely condition to occur. In this case, I would say that updates are far more likely that inserts (with new pages only being added occasionally) so I would code the update first, and check to see whether zero rows were updated by it and, if so, insert the new row. Regards, Phill Ward.
  3. The path is relative to where it starts from. Without any qualification ("inc/header.php"), it starts from the current directory, i.e. where the file doing the including is. With a leading slash ("/inc/header.php"), it will start at the root of the site. You might also be able to navigate "upwards", e.g. "../inc/header.php", but that's actively barred in some systems and will drive you mad if you have to refactor the site significantly. Regards, Phill W.
  4. Hi Barand, If only for completeness, shouldn't you have a "group by Branch" in there? Regards, Phill Ward.
  5. Five of your queries use "SELECT *". Do not do this in Production code. Databases are intrinsically shared entities and table structures can be changed [by anyone] at any time. Retrieving more fields than you actually need leaves you open to expected slow-downs, not of your making. Your remaining four queries could be combined into two. Taking the first pair, you can retrieve both aggregated values in one query: SELECT date_format(Date,'%Y') as month, COUNT(*) COUNT FROM calibrationdata WHERE Branch = '$userbranch' group by year(Date) order by year(Date) SELECT date_format(Date,'%Y') as month, sum(amount) FROM calibrationdata WHERE Branch = '$userbranch' group by year(Date) order by year(Date) // Can be combined into SELECT DATE_FORMAT( `Date`,'%Y' ) as month , COUNT( * ) as tally , SUM( amount ) as total FROM calibrationdata WHERE Branch = '$userbranch' GROUP BY year( `Date` ) ORDER BY year( `Date` ) Execute the query once, retrieve the values into an intermediate variable, then display that at the relevant point on the page. Also,. make sure that you have a database index supporting querying this table by Branch. Also, take a look at Parameterised Queries (Prepared Statements) to protect against SQL Injection Attacks. Obligatory XKCD Reference: Little Bobby Tables. Regards, Phill W.
  6. Or, perhaps better (i.e. safer) ... switch( $_POST[ 'siti' ] ) { case: 'FIUMI' : case: 'MOLINI' : case: 'VITA' : $category = $_POST[ 'siti' ] ; break; default: throw new \Exception( 'Invalid category!' ); } Why? Just because you send the User an HTML SELECT list to use does not guarantee that the value you receive comes from that list! Regards, Phill W.
  7. How does the User tell your code which "category" a file belongs to? Presumably, that would be another Form field, passed at the same time as the uploaded file itself. [Validate and then] Use that value to construct the target path for the file and pass that value to move_uploaded_file(). // pseudo-code if ( isset( $_POST[ 'btn-upload' ] ) ) { if ( validatePostArguments( $_POST ) ) { $targetFile = buildTargetPath( $_POST[ 'category' ], $_FILES[ 'file' ] ); move_uploaded_file( $file_loc, $targetFile ); } } Regards, Phill W.
  8. You'll also note that my function returns a string which is then displayed by echo(). It's a subtle distinction but means that you can send that string result anywhere you want. You should retrieve the data up front and pass it to the templating "system", not the other way around. Having the templating "system" reaching out to get its own data whenever it needs it will cripple the application. You could wind up running dozens (or hundreds!) of queries where one would do just as well. The principle I'm trying to demonstrate here is that data retrieval (from the database) and creation of content (based on a "template") need to be separate functions and you use PHP code to get the data you want from one into the other. The "front-end" must be parameterised to take the data you pass it and apply those values to the template HTML. The "back-end" must retrieve the required data and put it in a form that you can pass to the "front-end". In my example, I used individual parameters, mainly for clarity. It sounds like you'd be better off passing an array, with key-value pairs containing the data. This allows the templating "system" to take whichever values it wants and use them and "ignore" any that it doesn't need. (This is the classic "XML" principle; a great idea, as long as you don't have to worry about security!). Regards, Phill W.
  9. I think this is something like what you're after: function data () { //Abbrieviated code.... SELECT title, category, description, image_link FROM TABLE1 WHERE product_id=1; return $row ; } function template( string $title, string $category, string $description, string $image_link ) : string { $tmp = '<div class="t">TITLE %s</div>' . '<div class="l">CATEGORY %s</div>' . '<div class="m">DESCRIPTION %s</div>' . '<div class="r">IMAGE LINK <img src="%s"/></div>' ; return sprintf( $tmp, $title, $category, $description, $image_link ); } function go() { $row = data(); echo template( $row['title'] , $row['category'] , $row['description'] , $row['image_link'] ); } Regards, Phill W.
  10. MySQL should be able to cope with loading 31000 rows with ease. What error(s) are you getting when try to load it? I would suggest loading the whole file into a "staging" table and then transferring data from that into your "proper" tables. Regards, Phill W.
  11. In your login page, you need to extract the data from the data record you've retrieved and store it into the session, as you do for the username. $query = 'SELECT username, phone FROM users WHERE username=? AND password=?'; // bind parameters $result = mysqli_query($con, $query) or die(mysql_error()); $rows = mysqli_num_rows($result); if ($rows >= 1) { $_SESSION['username'] = $username; $_SESSION['phone'] = $result[ 'phone' ]; . . . Learn to use parameterised queries (which is much easier with PDO) to protect against SQL Injection attacks. Obligatory XKCD reference: Little Bobby Tables Never use "select *" in Production code. If somebody [else] adds some multi-Giga-byte columns holding the User's life story in video form, your super-quick login page suddenly slows to a crawl, having to read those massive fields that you've absolutely no interest in. Kudos for storing hashed passwords. Regards, Phill W.
  12. You should be checking every single input value that comes from the client because you cannot trust anything that it sends to you! You have no control over the client's machine so you must regard it as completely untrusted. Just sending particular HTML to it does not count as control - just fire up the [free, installed-as-standard] "Developer Tools" in your web browser if you don't believe me. You must validate everything server-side and that means checking and cleansing every single input datum as it arrives. Would that not turn them on for every single User? Cue wide-spread confusion, complaints and bug reports! Yes, upgrades can be disruptive but I'd be surprised if every upgrade causes you problems. Or, perhaps, your codebase is simply older - the more versions you have to "jump" across, the more likely you're going to have problems. Sadly, software upgrading is like a diesel-powered hamster wheel - once you climb onto it and start running, it's very very hard to stop. (Unless you use VB6, of course - abandoned by "Our Friends in Redmond" in 2002 but still going strong today. 😉 ). To me, this sounds like you're either working with highly volatile data structures that change a lot or you have a lot of "dead" code handling data items that no longer exist. All the more reason to guard against missing elements properly. Regards, Phill W.
  13. Not sure about best, but this should do the trick: <?php sacconicase_post_thumbnail(); $am = get_the_author_meta( 'discount', $post->post_author ); if ( $am ) printf( '<div class="mostrasconto">&nbsp;-%s%%</div>', $am ); ?> Regards, Phill W.
  14. I don't think you need password_verify() at all here. When saving the password, hash the entered, plaintext, password and store the hashed value. When logging in, hash the entered, plaintext, password and compare that to what's in the database table. Saving password (as you currently have): $hashed_password = password_hash($password, PASSWORD_DEFAULT); . . . $sql = "INSERT INTO users (first_name, last_name, email, password_hash) VALUES (:first_name, :last_name, :email, :password_hash)"; . . . $stmt->bindParam(':password_hash', $hashed_password); Logging in: $email = $_POST['email']; $password = $_POST['password']; $hashed_password = password_hash( $password, PASSWORD_DEFAULT ); $sql = "SELECT a, b, c FROM users WHERE email = :email and password_hash = :hashed_password"; . . . $stmt = $pdo->prepare($sql); $stmt->bindParam(':email', $email); $stmt->bindParam(':hashed_password', $hashed_password ); $stmt->execute(); $user = $stmt->fetch(); If you get no rows back, either the username or entered password is wrong. Regards, Phill W.
  15. Does your application know what to do with raw SQL passed as a QueryString argument? (If it does then I'd suggest that's a pretty poor design). if it doesn't then I see no point in defending against this. Hackers can throw this (and lots of other) stuff at your application, but it won't get them anywhere if your code doesn't try to do anything with it. Of course, you should vigorously validate and clean any inputs you do receive and that you do intend to do things with. Regards, Phill W.
  16. Almost always - Yes. The only exception is when you only ever access or retrieve the whole value, commas and all, as a single unit via some other identifier (perhaps to supply that value to some application code that expects it in that "shape"). But ... as soon as you decide you want to pick that value apart, to extract part of the value or, worse, to find rows by part of that value, then you must reconsider its storage and "re-shape" it something that your database can better work with. Databases are generally: Really good at finding small pieces of "stuff" and bolting them together, but Really rubbish at taking big chunks of "stuff" and pulling them apart. Why do you think string manipulation functions are so "under-developed" in most DBMSes, compared to most programming languages? It's just not what they're built to do. Regards, Phill W.
  17. Not should they! NEVER store passwords in plain text (i.e. as entered by the User). Put the entered password through a one-way hashing algorithm and store the output of that. When the user tries to log in, hash the entered password and compare that with what's in the database. That way, you have no character set issues (hashes are all plain ASCII characters) and no Reportable Data Breach if and when someone makes off with a copy [of a backup] of your database! Regards, Phill Ward.
  18. Taking a wild guess at your database structure, your query should look more like this: SELECT v.field_1 . . . , v.field_n /* Don't use "select *" in Application code. */ , b.BrandName , b.brandID as bid , l.LocationName , l.locID as lid from tblvehicles v join tblbrands b on v.VehiclesBrand = b.brandID join tbllocations l on v.Location = l.locID Regards, Phill W.
  19. BIG problem with this SQL. You want the total of total_value for each client, but which values of company_name, country, etc. should the query return? On any other DBMS (and even a properly-configured MySQL), this query would be thrown out with an error because the database cannot work it out which one you would want and so gives up. Your [poorly-configured] MySQL is simply returning any old, arbitrary value for each field that happens to be lying around in its buffer as it reads the data. In your query, you've aliased that value as tval, so you would access it using: $valByClient = $row['tval']; If you have a known "list" of client_id values before you execute the query, consider using the "in" clause to get the database to do the filtering (far more efficiently than your "looping" code ever will). SELECT c.id as clientid ... from client as c left join quote as q on c.id = q.client_id and 1 = q.open WHERE c.id in ( 1, 2, 3, 4 ) group by c.id order by c.id Regards, Phill W.
  20. Can't be done ... unless your PHP code actually runs on the User's own machine, which it [almost certainly] doesn't. No part of the HTTP protocol shares that information from client to [web] server. I would suggest that this is also a Bad Idea. Never had your computer replaced or upgraded? New computer, new MAC address, User can't log in, complaints to the Service Desk and Application Bug Reports ensue. Lots of Grief that you really don't need. Not really. I assume that your company as some sort of Information Security policies or, at the very, very least, Terms and Conditions of Use and one of the really, really basic ones should include "not sharing passwords". If they want to do something stupid like hand their passwords around, they've got far bigger problems. Regards, Phill W.
  21. Taking a step back and looking not at how to do this but, rather, why you want to do it in the first place ... What do the icons represent? Are they the icons chosen by clients to represent themselves on your site or are they just a list of possible icons that someone could choose from? If you're going to have a grid of links to each client then it doesn't matter if they're duplicated - that's why they chose. If it's something (an avatar?) to pick from, then use a Reducing Set - create one array with the icons in it and another, initially of the same size with the index of each one. Then, as you [randomly] pick each icon, remove it's index from the second array so you can't choose that one again. Regards, Phill W.
  22. Fix the root cause of the problem (the duplicated data), not the symptom (the misbehaving application). As I have oft said elsewhere: Forget the Code and get into the Data. If you really do have duplicated [truck] data, then you'll likely have to do a lot of mucking about with the Application code to get something that looks right. Or you find and eliminate the duplicate Data and all the problems go away. I couple of things it might be: It might be genuinely duplicated data. If so, first sort out the duplication and then put database constraints in place (unique keys/indexes) to prevent it "creeping" back in. It might be that the queries getting the data are somehow bringing back multiple copies of the same thing. Some tables use multiple-column, Composite keys (despite MySQLAdmin's best efforts to not support them) and if a query is written that omits one of those key fields in its joins, you wind up with exactly this kind of duplication. Regards, Phill W.
  23. If you always, always, always retrieve and use that comma-separated text as a single unit and never, ever, ever query individual elements of it then (and only then) you can store it in a single field. Treat it like a BLOB and you can store it like a BLOB. As soon as you suspect that you might, one day, possibly, want to find those records that have one (or more) of these elements in them, then you absolutely must store the data "properly" and split it out into separate tables, as others have described. Failing to do so will give you major problems in finding the data, most of them relating to performance as you Table-Scan through millions of records, substring-ing into this field for each and every one of them. Remember, relational databases are really, really good at finding little bits of stuff and bolting them together. They are generally pretty rubbish at finding big chunks of stuff and pulling them apart. Regards, Phill W.
  24. Your problem is this line: A private function is accessible only within the class in which it is defined (your class, "C"). A final function is one that is known to subclasses (of "C"), but those subclasses are not permitted to override that function. Since a private function is not known to subclasses, it cannot be meaningfully marked as final, hence the Warning. Either remove the final modifier or change the "private" modifier to "protected". Protected functions are known to subclasses and, by default, can be overridden by those subclasses. Neither private nor protected functions are available to any other class. See also Visibility in the Documentation. Regards, Phill W.
  25. I would guess that you're building your SQL in a string variable, complete with values entered by the user, and then trying to execute that string against the database. If that's the case, you're falling foul of a classic SQL Injection Attack. $sql = "select * from table1 where username = '$uName'" But here the User is entering something like O'Brien, so your SQL string looks like this ... $sql = "select * from table1 where username = 'O'Brien'" ^ Boom! ... and blows up! Read up about prepared statements (a.k.a. Parameterised Queries). Obligatory XKCD Reference: Little Bobby Tables. Regards, Phill W.
×
×
  • 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.