Home » Php » php – Best practice: Use same form for creation and update

php – Best practice: Use same form for creation and update

Posted by: admin July 12, 2020 Leave a comment

Questions:

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

How to&Answers:

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.

Answer:

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.

Answer:

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.

Answer:

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.

Answer:

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.