简体   繁体   中英

Cleaning up PHP Code

I've noticed I am a very sloppy coder and do things out of the ordinary.

Can you take a look at my code and give me some tips on how to code more efficiently? What can I do to improve?

session_start();



/*check if the token is correct*/
if ($_SESSION['token'] == $_GET['custom1']){

    /*connect to db*/
    mysql_connect('localhost','x','x') or die(mysql_error());
    mysql_select_db('x');



    /*get data*/

    $orderid = mysql_real_escape_string($_GET['order_id']);
    $amount = mysql_real_escape_string($_GET['amount']);
    $product = mysql_real_escape_string($_GET['product1Name']);
    $cc = mysql_real_escape_string($_GET['Credit_Card_Number']);
    $length = strlen($cc);
    $last = 4;
    $start = $length - $last;
    $last4 = substr($cc, $start, $last);
    $ipaddress = mysql_real_escape_string($_GET['ipAddress']);
    $accountid = $_SESSION['user_id'];
    $credits = mysql_real_escape_string($_GET['custom3']);




    /*insert history into db*/
    mysql_query("INSERT into billinghistory (orderid, price, description, credits, last4, orderip, accountid) VALUES ('$orderid', '$amount', '$product', '$credits', '$last4', '$ipaddress', '$accountid')"); 
    /*add the credits to the users account*/
    mysql_query("UPDATE accounts SET credits = credits + $credits WHERE user_id = '$accountid'");

    /*redirect is successful*/
    header("location: index.php?x=1");
}else{

    /*something messed up*/
    header("location: error.php");
}

Your code seems pretty standard. You should probably use indentation of some sort, and for the MySQL queries use prepared statements instead of just including variables in the middle of the query. From a style point of view it's mostly fine though

You may want to look into using a framework, or at least an object-relational mapper.

It really makes SQL operations very easy if you're using an object-oriented approach.

For example, with my framework, it only takes a few lines of code to create a new User after they've filled out a registration form. Of course there's tons of code encapsulated behind the object to prevent any funny business or hacking attempts, but it makes it very simple to work with.

$account = new Account();
$account->insert(array(
    'userid' => $id,
    'accountpass' => $passhash,
    'accountemail' => $emailhash
));

I haven't used any well-known frameworks or object relational mappers, but I've heard that CodeIgniter, Kohana, and Doctrine are a few good ones. However they have a learning curve so you should know beforehand if your application is big enough to warrant learning another API.

Passing a credit card number, and IP address via GET is not very secure, the URL containing the GET string may be retained in the browser history. How are you assigning $_GET['ipAddress'] ? You should use $_SERVER['REMOTE_ADDR'] instead.

To get the last 4 digits of a credit card, you can save a few lines of code by doing:

$last4 = substr($cc,-4);

Depends what you mean by "clean" here. The whole thing would benefit immensely from basic indentation - pretty much, moving your existing whitespace to somewhere where it's more productive. (Your line breaks seem pretty inconsistently distributed, for one.) Indentation and line break consistency greatly boost code readability.

On the next level of style, I see why you have the need to assign a ton of variables there, given that you're working with the raw MySQL functions. If you plan to stick with that system, at least assign the variables in a sensible order, not to mention that I made a few other changes and notes below.

// Let's just strip all non-numerics from the card number so that we can validate it.
$cc = preg_replace('/[^0-9]/', '', $_GET['Credit_Card_Number']);
if(strlen($cc) != 12) {
    // The card number is invalid; go back to form and try again.
}
$last4 = substr($cc, -4); // A negative start value is cleaner.

$accountid = $_SESSION['user_id'];

$amount = mysql_real_escape_string($_GET['amount']);
$credits = mysql_real_escape_string($_GET['custom3']);
// note: don't trust that users won't change the ipAddress parameter before submitting
$ipaddress = mysql_real_escape_string($_GET['ipAddress']);
$orderid = (int) $_GET['order_id'];
$product = mysql_real_escape_string($_GET['product1Name']);

I broke the variable assignments into three blocks. The first is for data transformation, the second is for fetching data from non-GET sources, and the third is basic assignment from $_GET variables, sorted into alphabetical order. The assignments now are much more structured, and it is easy to find any given line. (This is, of course, not by any means a standard way of breaking things up; it's just what made sense here.)

That's all that matters about good code - that it's easy for you to maintain. Do whatever works best for you, but I suspect that, in the long run, code readability and organized variable assignments work well.

Also, as others have mentioned, consider using something like PDO for database operations, which allows you to use prepared statements and avoid all those escaping functions. You may also want to look into an ORM like Doctrine , or perhaps a full-fledged framework . Using more powerful tools has a higher learning curve, but also lead to more productivity once proficient in OOP.

The first thing that leaps out at me is that there is a pretty big security hole in your code. By putting $_GET variables directly into SQL queries, you leave yourself open to a wide range of attacks. Additionally, as it appears to be using get data for billing, one could manipulate their own account balance by playing around with the get variables.

I would recommend some data checks on the incoming GET data before dumping it into the database.

I would add that every time you see yourself repeating the same action, you might want to create a function.

If tomorrow you want to change the way you escape your data, you will have to edit all the lines where you're using mysql_real_escape_string for instance.

why not adding a function such as

function escape_data($data) {
    $escaped_data = mysql_real_escape_string($data);
    // room for more actions ...
    return ($escaped_data);
}

also, if you're applying the same function to all the members of an array (here $_GET), you might find array_map() useful:

$_GET = array_map('escape_data', $_GET);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM