PHP help please

Soldato
Joined
24 May 2006
Posts
3,824
Location
Surrey - UK
Hi guys,

Trying to figure out how to pass an ID as a variable from a checkbox.

Basically i have a list of results from mysql displayed, in that table are checkboxes. Now i'm wanting to assign the name of the checkbox as a variable.

No problem there, can be done, what i'm stuck on is how to determine what the ID is when grabbing the POST data.

I have my form like so....

PHP:
<form method="post" action="'.$_SERVER['PHP_SELF'].'">

// Some of my table data

<input type="checkbox" name="'.$myvariable.'">

// Some more table data

<input type="submit" name="submit" value="OK" class="btn" />
I need a way to check which checkboxes are checked then perform my DB query.

So when i move along to my query i can do....

PHP:
if ($_POST['submit'] == ok) {

   if(isset($_POST['$myvariable'])) {
   
   $newvar = $_POST['$myvariable'];

   }

}
However i can't do it that way, it simply doesn't work as the variable is a variable obviously.

I'm proberly approaching this in the wrong way, so looking for a fresh head to help me figure it out... ;)

I'll explain more, basically i have news posts stored in a DB table, along with those i have a comments table, the comments have AID set to match the article(news posts) they were posted to.

Now i'm working on the admin section, so i grab a list of news articles, along with those i grab the comments associated.

The checkboxes allow an admin to check if they wish to remove some comments attached to a given article.

So you have a list of comments with checkboxes, so you check which ones you want to remove, then hit Submit and it moves onto the query.

So what i need to do is figure out how to know which boxes were checked.

Any help appreciated.....

I'll post back if i figure it out in any case... :)

Here's an image to clarify..

removecd1.jpg
 
Last edited:
Ok i think i've got it, will post back when it's working so i can show how it was done... :)

Ok solved passing the ID along using a foreach loop and value array for the inputs.

Unfortunately stuck again....

I run a DELETE mysql query to delete the comments for the comments table but i'd like to perform an update on the news table to. The news table has a column called comments which is update +1 when a comment is posted, but i also need to update that column minus one (-1) for each DELETE.

I've tried including a second query inside the loop but it just falls over with a standard error on line 1, which is obviously the opening <?php.

Here's the loop..

PHP:
foreach ($_POST['remove'] as $commentid)
    {
        dbadmin('mydatabase');
        $delcomments = 'DELETE FROM news_comments WHERE id='.$commentid.'';
        $delquery = mysql_query($delcomments)or die(mysql_error());
        $message = 'Comments were removed';
    }
As soon as i plonk another query in the loop i receive the message mentioned...
 
Last edited:
Ok, another problem solved, i was using an include for the comment deletion and had the include outside the initial query, resulting in not being able to identify the article ID to be associated with....

Problem resolved....

Until the next question..... :)

EDIT: Seems the query is flawed as i also need to pass along the given article ID to, for now it's passing along the ID of the first article and not the one the comments are associated with...

I'll work it out and post back if i get stuck...

Thanx to anyone who can offer suggestions...
 
Last edited:
please replace:

PHP:
$delcomments = 'DELETE FROM news_comments WHERE id='.$commentid.'';

with

PHP:
$delcomments = 'DELETE FROM news_comments WHERE id='.(int)$commentid;

assuming your ID is numeric, that will stop anything harmful from potentially being passed through post, and it just good practice to escape things that come through post. Though this isn't strictly escaping, it will convert a string to the number 0, so it'll be harmless.
 
Also, use PDO for any new projects as it gives a nicer unified way of doing prepares which is better than trying to remember casts on each variable.

Please read up on writing secure code with php as it could prevent some major headaches further down the line.
 
Great guys looks like i have a lot to look at then... and yes the ID is numeric Sic, thanx...

I'd been following several guides around the web, so my code is made from pieces of other examples, but for the most part i understand what's going on. (heck i wrote the comments secion all by myself....:) *sorry had to say that, i'm proud of my work... ;) )

Shoseki the prepared statements look like a great idea, i'll read up.....

philjohn i honestly have no idea what PDO is, care to enlighten? And i have been reading up on secure code, but then that's subjective to the person providing the information, so i have an idea, whether that's the same idea as yours i don't know.

Can anybody suggest some minor do's and do not's......?

I'm escaping my queries (mysql_escape_string), stripping my post data, etc... anything i should be aware of?

Bearing in mind my code right now is quick and easy, so i work on the tightening it up last. No point escaping and stripping anything until the code works, then i can go back and strip tags etc.... It's running on a local install, so no risk security wise right now...and it's a personal project, so no dead line etc....

Shoseki, my sql statements are in PHP docs, i was to the understanding the query is not passed as text inside a PHP file.... care to expand on what you said?

Thanks to all you guys for the comments/suggestions, keep em coming...
 
Last edited:
Whatever you use to store the sql files, it isn't the file itself that is the problem (though you can add something to the htaccess file I believe to stop them being parsed) its more a matter of me putting "' AND 1=1" to retrieve all records etc.
 
Is that not what mysql_escape_string can be used for?

http://uk2.php.net/mysql_real_escape_string

EDIT: Wrong link...
http://uk2.php.net/manual/en/function.mysql-escape-string.php

I'm already performing my queries with the above. :)

Also have different db privs set for different db users, and use different ones for different tasks, for example i have one user with select only privs on the news and comments tables, so regardless of whether someone manages to exploit the db user the privs will only allow selection from 2 tables. Of course i need to ensure i keep my db connection includes in a safe place, ie. outside the root directory and keep mysql error messages off, unless debugging (or define my own messages that won't expose the document roots).

Anything else i should take note of?
 
Last edited:
No, its different, escape string is just for filtering individual strings... preparedstatements is about setting up pre-defined statements where you only send individual parameters. Its optimized...
 
PDO is the new database access library in PHP (PHP Data Objects) it offers a unified (i.e., no need to learn mysql_*, pgsql_*, oci*_* etc) database access API and offers support for prepared statements which are good as they not only protect against SQL injection, but you can specify the data type a particular element should be.

As far as getting it working, then getting it secure goes - that's a fallacy, if you don't do it right first time the chances of you going back to fix it are infantesimally small.

As far as security goes, a few basic rules of thumb:
  • Don't rely on superglobals, use $_GET, $_POST, $_FILES etc.
  • Don't trust ANY user input, filter and sanitise it (if you can build a library even better, we have a really nice one in our company framework that allows you to specify what filters to apply to which variables and it's automatically done)
  • Make sure you validate form posts (required stuff filled in, items within range etc), and do this client AND server side (once again, a decent library helps here - ours takes a PHP specification of what to validate on the server side and then auto-generates javascript for the client side too)
  • Make sure you protect against cross site scripting - there are some good libraries out there such as HTML Purifier
  • Protect against Cross Site Request Forgery on any important forms (the OWASP website can offer some pointers)
 
Have you had a read of rob millers php security guide. Thought that was excellent personally. Always thought it was a good article that had all the major stuff in one place.

http://php.robm.me.uk/

Yep, great page, had that one up a few times while creating code.... thanks.. ;)

I'm currently using a tweaked version of his password hashing method...

So thanks to Rob if he's around... :)

PDO is the new database access library in PHP (PHP Data Objects) it offers a unified (i.e., no need to learn mysql_*, pgsql_*, oci*_* etc) database access API and offers support for prepared statements which are good as they not only protect against SQL injection, but you can specify the data type a particular element should be.

As far as getting it working, then getting it secure goes - that's a fallacy, if you don't do it right first time the chances of you going back to fix it are infantesimally small.

As far as security goes, a few basic rules of thumb:
  • Don't rely on superglobals, use $_GET, $_POST, $_FILES etc.
  • Don't trust ANY user input, filter and sanitise it (if you can build a library even better, we have a really nice one in our company framework that allows you to specify what filters to apply to which variables and it's automatically done)
  • Make sure you validate form posts (required stuff filled in, items within range etc), and do this client AND server side (once again, a decent library helps here - ours takes a PHP specification of what to validate on the server side and then auto-generates javascript for the client side too)
  • Make sure you protect against cross site scripting - there are some good libraries out there such as HTML Purifier
  • Protect against Cross Site Request Forgery on any important forms (the OWASP website can offer some pointers)

Thanks phil,

Not knowing much about mysql nor php but knowing a bit of both helps. I've just got comfy with MySQL so i'll stick with that for the time being, while i explore PHP so more.

Had a look over the main pages regarding PDO and it looks easy enough, but it's another method to learn on top of what is great fun already.

Think i'll carry on as is for now, and keep PDO as a future reference when i need something new to play at.

Thanks for the suggestions, and regarding super globals i'm coding with the assumption register globals is off, it seems the norm for most hosts and from what i've read i don't think i'd want them on.

$_FILES is a new one for me though, i'll take a look at that.... ;)

$_POST & $_GET though i've used quite a bit though...

No, its different, escape string is just for filtering individual strings... preparedstatements is about setting up pre-defined statements where you only send individual parameters. Its optimized...

Prepared statements as in PDO though. Great suggestion just not sure i need another method to wrap my head around just yet when i'm just getting comfy with MySQL...

Thanks...
 
Last edited:
PDO is basically just an object oriented version of what you're using already, but it has built-in methods to automatically escape anything you want to pass through it:

PHP:
$pdo = new PDO($dsn,$username,$password); # more info on dsn here http://uk.php.net/manual/en/pdo.construct.php
$stm = $pdo->prepare('
  select * from `table`
  where `name` = :name
'); # create a statement object
$stm->execute(array(
  'name' => $name # :name maps directly onto this and gets automatically escaped
));

so it's much easier to use PDO, and you're much less likely to accidentally leave gaping holes in your code. It's really worth getting in the habit of using.
 
so it's much easier to use PDO, and you're much less likely to accidentally leave gaping holes in your code. It's really worth getting in the habit of using.

It's also the future of low-level DB access in PHP so whilst you'll need to know the mysql_* stuff for legacy apps, any new development should really be using it IMHO.

It is not however a DB abstraction library (but we ended up extending the base objects to create one, which is one of PDO's strengths).
 
To be honest, I think anyone who uses it on a regular basis end up extending it. Either that or using a framework that extends it.
 
So is PDO something i really need for a personal project, as the site is comprised of only 20 pages or so at the moment (only about 10 with near complete code).

Also will PDO work as standard, or does it need to be compiled into PHP? ... i had a read but couldn't see a clear cut answer as to whether that's the case, and i wasn't going to read pages of info for one simple answer.. hehe...

If PDO works as is then i'll take another look. As said before, i can always go back and add it later on if it tickles my fancy... :)

UPDATE:: I had a read while writing this reply, and PDO should just work straight off from what i can gather, but alas i still see it as another method to wrap my head around.

I'll try some basic PDO bits on a test db and pages to see how i get on, unless you guys can reference to some easy PDO guides?......
 
I'll try some basic PDO bits on a test db and pages to see how i get on, unless you guys can reference to some easy PDO guides?......
[/I]

Intro to PDO on Sitepoint.com

It really is very simple though, the example given by another user above is pretty much most of what you need to know. To iterate over a recordset you can then do this:

PHP:
$pdo = new PDO($dsn,$username,$password);
$stm = $pdo->prepare('
  select * from `table`
  where `id` > :id
'); # create a statement object
$stm->bindValue('id', 100, PDO::PARAM_INT); //Bind a value to the named parameter (the :id bit in the query), I prefer this method as it's easier to control programatically than passing an array to the execute method
$stm->execute();
//Now the fun part, we can just do a foreach as PDOStatement class implements the iterator interface
foreach($stm as $row)
{
   echo 'Name: ' . $row['name'] . "<br />\n";
}

One thing to be aware of is there is no mysql_num_rows equivalent as it is not portable (and not good design as most drivers that offer it would actually have to buffer the entire result set first, leading poor performance and increased memory consumption). If you need to find out how many rows are returned by a query, the best way is to

Code:
SELECT
    COUNT(*)
FROM
    `table`
WHERE
    [your where clause here]

As said before, learning to do things right first time will stand you in much better stead going forwards as a programmer.

edit: Also, I would recommend getting a decent PHP IDE as they offers niceties such as code completion, I personally use Eclipse with the PDT plugin (and Subclipse for source code repository acess) and find code-completion to be a real productivity boon (saves you having to look bits and pieces up in API documentation). It really comes into its own if you have a large OO class library (e.g. if using a framework or third-party lib).
 
Last edited:
It's only for fun, nothing important is meant to come of it, but i appreciate the suggestions all the same.

Currently pulling my hair with this at the moment...

Code:
$query1 = 'SELECT id,title,date,author,article,flag,flag_notes,arch FROM news ORDER by id DESC';
$query1 = mysql_escape_string($query1);
$query2 = mysql_query($query1);

// Start while loop for articles
while($rows = mysql_fetch_array($query2)) 
{
    
    // Do some stufff
    $aid = $rows['id'];
    $atitle = $rows['title'];
    $atext = strip_tags($rows['article']);
    $atext = nl2br($atext);
    $atext = substr($atext, 0, 400).'...';
    
    $adate = date("d, F y - h:ia", $rows['date']);
    $aauthor = $rows['author'];

    echo '
    <ul class="adnews_a">
    <li>'.$atitle.'</li>
    <li class="atext">'.$atext.'</li>
    <li>Publish date - '.$adate.'</li>
    <li>Author - '.$aauthor.'</li>
    <li>Article flagged? - '.$rows['flag'].'</li>
    <li class="aform"><form method="post" action="'.$_SERVER['PHP_SELF'].'#'.$aid.'">';
    
    // Query for associated comments....
    $query3 = 'SELECT id,aid,title,text,postdate,flag,poster FROM news_comments WHERE aid='.$aid.' ORDER by id DESC';
    $query3 = mysql_escape_string($query3);
    $query4 = mysql_query($query3);
    $checkrow2 = mysql_num_rows($query4);
    
    // Check comments, if any returned, show header for comments list
    if (!empty($checkrow2))
    {
        echo'<a name="'.$aid.'"></a>Flagged comments<br />
        <ul class="adnews_b">
        <li class="cid">ID</li>
        <li>Title</li>
        <li class="str">Date posted</li>
        <li class="cid">Flag</li>
        <li class="str">Author</li>
        <li class="cid">Delete</li>
        </ul>';
    }
    else
    {
    $message = 'No comments associated with this article';
    }
    
    // Show results of query to comments table    
    while($rows2 = mysql_fetch_array($query4)) 
    {
        $comid = $rows2['id'];
        
        echo '<ul class="adnews_c">
        <li class="cid">'.$rows2['id'].'</li>
        <li>'.$rows2['title'].'</li>
        <li class="str">'.date("d/m/y - h:ia", $rows2['postdate']).'</li>
        <li class="cid">'.$rows2['flag'].'</li>
        <li class="str">'.$rows2['poster'].'</li>
        <li class="cid"><input type="checkbox" value="'.$comid.'" name="remove[]" /></li>
        </ul>';
    }
    
    // If admin has asked to remove some comments...
    if($_POST['admin'] == 'OK') 
    {
        if(isset($_POST['remove'])) 
        {
            foreach ($_POST['remove'] as $commentid)
            {
                $delcomments = "DELETE FROM news_comments WHERE id=$commentid;";
                $update ="UPDATE news SET comments = comments-1 WHERE id=$aid";
                $delquery = mysql_query($delcomments) . mysql_query($update) or die(mysql_error());
                $delquery = mysql_escape_string($delcomments)or die(mysql_error());
            }
            $message = 'Comments were removed';
        } 
        else if(!isset($_POST['remove']))
        {
        $message = 'No items have been selected or an invalid submission was created, so nothing happened!';
        }
    }
    
    // End of article 
    echo '';
    if (!empty($checkrow2)) 
    {
        echo'<li class="right"><input type="submit" name="admin" value="OK" class="btn" /></li>';
    }

    echo '</form></li>';
    
    if(isset($message)) 
    {
        echo '<li class="right">'.$message.'</li>';
    }
    
    echo '</ul><br />';
}
Header, footer and database includes are obviously there to, but i didn't need post that part of the code.

The issue at the moment is when removing a comment it updates every news article 'comments' total instead just the one article.

I perform the delete after this bit...
Code:
// If admin has asked to remove some comments...
    if($_POST['admin'] == 'OK')
I'm proberly going about this wrong, but it's only for fun...

I couldn't quite see how to display the data without nesting the while loops and using the foreach for the comment ids.

Code works, just that one minor hiccup, if you can spot the problem i'd be dead happy... ;)

NOTED: regarding num_rows...

EDIT: Fixed...
 
Last edited:
Back
Top Bottom