1

I'm working on a project and I would like know which is the best way for show the data after having insert a record on the database having an complex structure html between use the structure in php or jQuery and why?.

Example of scenario:

I'm building a system of posts and comments. When the user write the post and publish it an call ajax trigger the function php and it insert the information on the database. until here all ok, but then I have to display the message insert on the wall of the user, so which the best way for display that post insert?

There are so many different way, but which is the best keeping attention on speed, security, and compatibility?

some example, suggest are welcome:

<script> // default example of call ajax
        $.ajax({
            type: "POST",
            url:  'http://localhost/ajax_ouput_post',
            dataType: 'json',
            data: { id_user : 1, title : "Hello everyone", content : "Good morning" },
            success: function(html) {
              // output under php example
            },
            error: function(){
                  alert('Error on ajax call');
            }
        });
    </script>

1- I create the template for the output in php.

<?php 
 function ajax_output_post() {
   $title = $_POST['title'];
   $content = $_POST['content'];
   $id_user = $_POST['id_user'];
   
   // all the check for the input
  
   $query = // insert data on mysql @return id_post;

   $select_last_post_mysql = // select the last query from the db using id_user and id_post

   foreach ($select_last_post_mysql as $post) {
      $template = // html structure;
      $template .= // continue html structure;
        if ($post->photo == 1) {
           $template .= // <div>photo user</div>
        }
      $template .= // ecc...
   }

   echo json_encode(array('template' => $template));

 }

?>

jquery output

<script>
  $(#wall).append(html.template);
</script>

php second example with output jQuery template

<?php 
     function ajax_output_post() {
       $title = $_POST['title'];
   $content = $_POST['content'];
   $id_user = $_POST['id_user'];
   
   // all the check for the input
  
   $query = // insert data on mysql @return id_post;

   $select_last_post_mysql = // select the last query from the db using id_user and id_post

   foreach ($select_last_post_mysql as $post) {
        $title_json = $post->title;
        $content_json = $post->content;
        if ($post->photo == 1) {
          $photo_user_json = $post->photo_user;
        } else {
          $photo_user_json = "";
        }
        $id_post = $post->id_post;
   }

   echo json_encode(array('title' => $title_json, 'content' => $content_json, 'id_post' => $id_post));

 }
?>

jquery

<script>
// in jquery
        var Template = {
           main_container: "<div class='post_container' data-post='" + html.id_post + "'>",
              title: "<div class='title'>" + html.title + "</div>",
              content: "<div class='content'>" + html.content + "</div>",
           close_main: "</div>",
           run: function() {
                return Template.main_container + Template.content + Template.close_main;
           }
       };
     $('#wall').append(Template.run());
</script>
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Fabrizio Fenoglio
  • 5,767
  • 14
  • 38
  • 75

2 Answers2

1

Well, there is not really a 'best' way to do this, it always depends on the concrete situation.

In your case you could:

  • simply attach the user post to the DOM via javascript, without knowing whether it was inserted to the database or not (because you have all data of the post at client side available, you do not need to select it again)

  • attach the user post by javascript (like in the point above) after you know it was inserted (in the success handler, but still no data in response from php)

I would recommend not to select the inserted data again anyway, except you need an auto generated value like id or inserted-timestamp, instead you could simply return the values of the request in your response after the insert.

Hope this helps.

NiMeDia
  • 995
  • 1
  • 15
  • 27
  • 1
    Thank you for the explanation this is true! But i did another select because i don't pass all the datas of the user like id_picture, ecc... But your explanation is clear. Thank you – Fabrizio Fenoglio Dec 06 '13 at 13:54
0

There are a few ways to accomplish this, and there are tradeoffs to be made for each of them.

The simplest way to accomplish this is to retain the user input in javascript as answered by Nico above. The pro for this method is it is very simple to accomplish and move on to other problems and due to this simplicity, has few moving parts to be misused. The major con for this method is that it means the frontend is making blind assumptions about what is going on when the backend logic processes the data, which presents the risk of misinforming the user about what happened if the backend silently fails, and this sort of bug is often difficult to catch until it bites someone and they complain. This is probably your best answer for simple use cases, but if you intend to scale it or introduce significant complexity this makes the likelihood of bugs high and should be replaced.

As per your given example, you seem to be on this frame of thought already. So to address each of your given concerns, first I would say that compatibility is best addressed by being generally unopinionated. This is appropriate for a library meant to be used for general consumption, but is not necessarily preferable for a private project or internal business logic, which require opinion to execute a specific desired result. The major caveat in terms of compatibility is that templating is handled by the frontend at least as often as the backend. It may in some cases be done in ReactJS or Angular, or it may be done on the backend by Twig, or any number of other things. If you want wide compatibility, then this should have some configuration for whether to pass response in raw format or accompanied by a template. In the case of private business logic or an app you are building with a specific purpose, the underlying point is to accomplish a specific result, and either using the existing templating structure of the system or picking one and sticking to it is preferable so you are focusing on the end goal and not getting distracted. But either way a github library author and a app developer would likely solve this same problem in completely different ways, and neither of them are wrong.

In terms of security, the typical concerns all apply. Individual approach is mostly arbitrary, provided you cover these bases if user input is being output, entered into template content, or stored in a database.

In terms of speed, the javascript DOM option is always going to be the fastest. However you can make it almost as fast depending how much tolerance for optimization you have. You could perhaps use client side storage to cache unmodified templates client side, and just use a hash of the template content as its identifying key so it automatically flushes when you change the template on the server. If you then send the key to the server and it matches, you don't need to serve the template in the response body because the client already has the correct one. If the template hash on the backend is different, you serve the new one, bust the storage cache for that template and replace the key and value with the new one. This will make the template body, which is almost certainly the longest part of the response, only need to be sent when changes are made. You would need to inject the values into the static template clientside to do it this way, and still obtain those from the server on each request. On the backend, you do not want to make a separate SELECT statement. You want to store the values in an array and just return those if your INSERT query is successful, like maybe something like this:

<?php
// List of keys that MUST be present for the query to succeed. Don't bother calling the db if any of these did not come in the request.
$expected_keys = [
    'id_user',
    'title',
    'content' // add whatever else has to be passed
];

// key/val for db insert
$vals = [];

try {
    // verify expected keys are provided
    foreach ( $expected_keys as $k => $expected ) {
        if !(array_key_exists ( $expected, $_POST ) ) {
            // not a valid post, return an error
            throw new \InvalidArgumentException( sprintf( 'Expected field [%1$s] was not provided. ', $expected ) );
        }
        // retain the field in $vals for insert
        $vals[ $expected ] = $_POST[$expected];
    }
    
    $dsn = "mysql:host=localhost;dbname=myDatabase;charset=utf8mb4";
    $options = [
        \PDO::ATTR_EMULATE_PREPARES   => false,
        \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC
    ];
    $pdo = new \PDO($dsn, "username", "password", $options);
    $stmt = $pdo->prepare(
        'INSERT INTO `myTable` ( `:' .
            implode( '`, `:', array_keys( $vals ) ) .
        '` ) VALUES (' .
            implode( '", ":', $vals ) .
        ');'
    );
    $stmt->execute( $vals );
    $stmt = null;
    
}

// User error
catch \InvalidArgumentException $e {
    // return 400 Bad Request and $e->getMessage() as the error message
}
// Server error
catch \Exception $e {
    // log or whatever and return a 500 error
}

// return success with whatever you need to send back from $vals or $_POST
mopsyd
  • 1,877
  • 3
  • 20
  • 30