tags:

views:

79

answers:

5

Hi everyone,

I'm just curious and was wondering how you guys handle it if you want to use the same html form and as far as possible the same php code to create and update an item.

Example:
On one page you can create a database entry with name, email address and age.
On a different(?) page you see the form fields filled with your data and you can edit and save it.

I have my ways to accomplish this using pretty much the same code - but I'm hoping to learn something here. So how would you handle this task?

Thanks & Cheers, sprain

A: 

Yes, that's the only acceptable solution.

Here is a little example of CRUD application which store the input form in a template:

<?  
mysql_connect(); 
mysql_select_db("new"); 
$table = "test"; 
if($_SERVER['REQUEST_METHOD']=='POST') { //form handler part: 
  $name = mysql_real_escape_string($_POST['name']); 
  if ($id = intval($_POST['id'])) { 
    $query="UPDATE $table SET name='$name' WHERE id=$id"; 
  } else { 
    $query="INSERT INTO $table SET name='$name'"; 
  } 
  mysql_query($query) or trigger_error(mysql_error()." in ".$query); 
  header("Location: http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF']);  
  exit;  
}  
if (!isset($_GET['id'])) { //listing part: 
  $LIST=array(); 
  $query="SELECT * FROM $table";  
  $res=mysql_query($query); 
  while($row=mysql_fetch_assoc($res)) $LIST[]=$row; 
  include 'list.php'; 
} else { // form displaying part: 
  if ($id=intval($_GET['id'])) { 
    $query="SELECT * FROM $table WHERE id=$id";  
    $res=mysql_query($query); 
    $row=mysql_fetch_assoc($res); 
    foreach ($row as $k => $v) $row[$k]=htmlspecialchars($v); 
  } else { 
    $row['name']=''; 
    $row['id']=0; 
  } 
  include 'form.php'; 
}  
?>

form.php
<form method="POST">
<input type="text" name="name" value="<?=$row['name']?>"><br>
<input type="hidden" name="id" value="<?=$row['id']?>">
<input type="submit"><br>
<a href="?">Return to the list</a>
</form>

list.php
<a href="?id=0">Add item</a>
<? foreach ($LIST as $row): ?>
<li><a href="?id=<?=$row['id']?>"><?=$row['name']?></a>
<? endforeach ?>

Of course, some fancy form constructor, like HTML_QuickForm2 coud be used instead of plain HTML template - you know its constant programmer's hunger not to repeat himself, even in naming an HTML field, field value and error key :)
But personally I prefer plain HTML.

Col. Shrapnel
+5  A: 

Pretty easily - if an ID of an existing item (which the user is authorised to edit) is supplied in the query string, then it's an edit operation.

If no ID is supplied in the query string, it's a create operation.

The fields are pre-populated based on the existing values from the database if it's an edit operation, or based on default values or empty strings if it's a create operation.

thomasrutter
it's not possible to not populate field values, as we're using the same form :)
Col. Shrapnel
Sure you can...<input type="text" value="<?php echo @$valueFromDB; ?>" /> might not be the best way- but it works. If the form is for a new entry then the value is empty, otherwise displays the entry from the database.
Jesse
oh no. you have never used to debug your application or you'd never even mention that.
Col. Shrapnel
To clarify, the pre-population happens regardless. The form is pre-populated with sensible defaults (where applicable, or just null values if you like) if there is no existing record, and it's pre-populated with the current column values of the record if there is.
thomasrutter
A: 

I guess this is not the right answer but it might be interesting for you anyway.

There is an orm project called doctrine: http://www.doctrine-project.org/projects/orm/1.2/docs/en

// User Id might be an existing id, an wrong id, or even empty:
$user_id = 4;
$user_id = null;

// Fetch the user from the database if possible
$user = Doctrine::getTable('Model_User')->find($user_id);

// If there was no record create a new one
if ( $user === false )
    $user = new Model_User();

// Change some data
$user->title = $newValue;

// Perform an update or an insert:
$user->save();

As you see you don't have to care about sql. Doctrine does that for you and your code becomes easier to read and to debug.

Ghommey
...and hard as hell to step aside from common tasks :)
Col. Shrapnel
I haven't reached this point yet. May you give me an idea of how such tasks look like?
Ghommey
+3  A: 

The way I see it is that reusing identical markup for form between create/edit works for some cases, but not for all. I find that forms -- though they may map to the same database table -- are really defined by their context. For example, if you had a 'users' table, you might have a 'create' form with username, email, password, but after that user exists you want them to retain their identity on their site, so the username field would not appear in an 'edit' context. I'm classically a PHP developer, but I have come to appreciate the approach that Django takes, where you create a model (table) that defines the basic validation for each field and you can create as many forms as you that build off of, or modify/extend from that definition. If you're writing from scratch, you'll probably find it practical to make your validation methods very portable and/or find ways to make your form fields context-sensitive.

Chris Forrette
Absolutely. It is frequent to have business differences between an insertion and an update, perhaps some fields are not editable once inserted, perhaps some fields are editable only at first insertion, and it may be inserted on one page, edited on more. That said, whenever it is possible, I reuse the same forms.
snowflake
+1  A: 

That's the way I always do it now. Are you using an MVC system at all? I use one controller with two different actions (urls = person/new + person/edit/xxxx_id).

the code is then something like:

function new()
    errors = []
    if (get)
        data = blank_record()
    elseif (post)
        data = posted_data
        if (create(data))
            redirect_to_listing()
        else
            errors = describe_errors
    show_form(data, errors)

function edit()
    errors = []

    if (get)
        data = get_from_db(id)
    elseif (post)
        data = posted_data
        if (save())
            redirect_to_listing()
        else
            errors = describe_errors
    show_form(data, errors)

Note that once it gets to the form there's always an object called data that the form can render, it may be blank, from the db, or posted data. Either way it should always be the same format.

The reason I split new and edit is that I find that often enough they are actually quite different in their behaviours and the load and save steps.

Aidan Kane