SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    $books++ == true matsko's Avatar
    Join Date
    Sep 2004
    Location
    Toronto
    Posts
    795
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Organizing AJAX backend components logically

    Seeing as the way AJAX is evolving lately, a common trend is that: almost any operation can be performed without having to refresh/reload/redirect the webpage.

    So I'm wondering, what's a logical way to organize HTML files and PHP code so that these components can be easily prompted and used. I usually code my websites in the format so that when you go from a page to another page it simply runs through a Page class and then spits out the information into a root index file.

    Code:
    .. dynamically included php file ...
    <html>
    <head>
    ... dynamic css ...
    </head>
    <body>
    <div id="header">...</header>
    <div id="content">
    ... dynamic page ...
    </div>
    <div id="footer">...</div>
    ... dynamic JS ...
    </body>
    </html>
    This works fine for new page loads, however, when a AJAX call is made to a page, its simply a waste of process (client and serverside) to strip all the content before the content div and to populate the JS and CSS files into an array.

    Code:
    //Ajax call is made
    returnedAJAXoutput = {
        'js' : [ ... ],
        'css' : [ ... ],
        'cssText' : '...',
        'jsText' : '...',
        'content' : '...'
    };
    For anyone involved in developing complex ajax websites, what kind of method of input/output do you use for your ajax components?
    I can't believe I ate the whole thing

  2. #2
    SitePoint Guru
    Join Date
    Nov 2004
    Location
    Plano
    Posts
    643
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    i've found that organizing my controllers / URLs to be RESTful helps immensely with simplifying AJAX tasks. this is something i picked up from rails, but it's a great design pattern IMO as I feel it's very versatile. i'll try to explain my favorite implementation below.

    for instance, i might have a forum page /forum/15. loading this URL would simply show the user page 1 of a list of threads in this forum in HTML format. On the server side, this would look something like this:

    PHP Code:
    class ForumController {

    public function 
    show(){
      
    // get list of threads
      // do any other processing here
    }

    nothing new here. but say you wanted to make it where when you clicked to view the next page in the list, it loaded it through AJAX instead of a full page load. What you would do is load the same code, but send a flag or a parameter that will let the script know you only need a list of threads and not a full HTML page with header, footer, etc. My preferred way is by using the file format like so: /forum/15.json?page=1. My preferred transport is JSON, but anyone will do (XML, plaintext, etc). Now, you'll just modify your code to only serve up the thread list. Use the format flag to conditionally do a full page load or just the thread list.

    PHP Code:
    class ForumController {

    public 
    show(){
       if (
    $_GET['format'] == 'html'){ show_html(); }
       
    // get list of threads
    }

    public 
    show_html(){
       
    // do any other processing here
    }

    similarly, whatever you use to generate your views should be able to handle this format flag. for me, i have different classes that extend a general Template class i.e. HTMLTemplate, JSONTemplate, XMLTemplate, etc.

    And that's about it in a nutshell. i hope i explained that clearly.

  3. #3
    SitePoint Guru
    Join Date
    Nov 2004
    Location
    Plano
    Posts
    643
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    i was hoping there'd be more discussion on this...i'd like to see how other people do this, i'm always lookin for improvements

  4. #4
    We're from teh basements.
    Join Date
    Apr 2007
    Posts
    1,205
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've been thinking about doing a client-side AJAX MVC using JavaScript Templates (JST) to display JSON-encoded content. I was previously rendering the "portlet" content in one of two (and probably the most obvious) ways, neither of which were particularly satisfactory for creating complex layouts.

    (1) Using DOM methods to build the layout, then appending it to the portlet DIV. This is prone to memory leaks. These can be mitigated by appending nodes/elements starting from the top and working downward, but that's bass-ackwards to the way one would do it intuitively.

    (2) Using string concatenation to build the layout, then setting the portlet DIV's innerHTML property to the string. Not prone to memory leaks, but it still makes the code very difficult to read.

    In either case, the data and presentation are horribly mixed together. As a result, a lot of recoding is required to make even the most minor changes. That's where JST comes in.

    There are several JST engines available. Trimpath tags have a Smarty-like syntax, with data and modifiers separated by a pipe character. Mark Turansky's "Better JavaScript Templates" uses a JSP-like syntax. Modifiers are created by extending the prototypes of the built-in JavaScript classes.

    As for the backend, I usually put the AJAX scripts in a separate "servlets" directory, together with a lightweight version of whatever configuration and initialization files I use for the full HTML pages. I really haven't settled on a way of integrating them more fully into my framework as yet.

  5. #5
    SitePoint Addict webaddictz's Avatar
    Join Date
    Feb 2006
    Location
    Netherlands
    Posts
    295
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by XtrEM3 View Post
    My preferred way is by using the file format like so: /forum/15.json?page=1. My preferred transport is JSON, but anyone will do (XML, plaintext, etc). Now, you'll just modify your code to only serve up the thread list. Use the format flag to conditionally do a full page load or just the thread list.

    PHP Code:
    class ForumController {

    public 
    show(){
       if (
    $_GET['format'] == 'html'){ show_html(); }
       
    // get list of threads
    }

    public 
    show_html(){
       
    // do any other processing here
    }

    It's scary how much my approach looks like yours. I also have "RESTful" URL's in that every resource has it's own URL, and I also determine the response type and content by the file extension. The only difference is that I've actually put the responsibility of determining response type in the view layer, as opposed to the controller.
    Yes, I blog, too.

  6. #6
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by XtrEM3 View Post
    PHP Code:
    class ForumController {

    public 
    show(){
       if (
    $_GET['format'] == 'html'){ show_html(); }
       
    // get list of threads
    }

    public 
    show_html(){
       
    // do any other processing here
    }

    Konstrukt has a separate handler for each content-type your component (controller) supplies. For a regular web application, you'd implement renderHtml:
    PHP Code:
    class MyComponent extends k_Component {
      function 
    renderHtml() {
        return 
    "<p>Hello World</p>";
      }

    You can then implement renderers for different formats, such as renderJson etc.

    The library takes care of selecting the best handler, using the Accept-header (Content-Negotiation). Alternatively, you can specify the content-type as part of the url, like this: http://example.com/foo;json or http://example.com/foo;html

    It's funny (and reassuring) to see that you've come up with basically the same design. I'd recommend that you try to incorporate content-negotiation as the default mechanism to decide the content-type, since it will make your application more aligned with the http-specs. You still need to be able to specify it as part of the url ($_GET['format'] in your case), but you can do both.

  7. #7
    SitePoint Addict
    Join Date
    Dec 2007
    Posts
    348
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I do it much the same way as XtrEM3, I send an extra parameter with the request to identify that request as an AJAX request and the resulting HTML is just the result of the request for that particular part of the page versus the usual way of returning a 'master page' with several dynamic elements populated by various php processes.

  8. #8
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I create a separate page for Ajax, which task is to only return the data needed. It has a separate controller and model. A quick example:

    PHP Code:
    class AjaxController extends S_PageController{
        function 
    pages(){
            echo 
    s::to_json($this->model->get_pages());
            exit;
        }
        function 
    page_by_id(){
            echo 
    s::to_json($this->model->get_page($_GET["id"]));
            exit;
        }

    Then on the front side I simply call the desired data through JavaScript and manage it:
    Code JavaScript:
    load("ajax.php?a=pages",populate_pages);
    or
    Code JavaScript:
    load("ajax.php?a=pages&id=4",display_page);

  9. #9
    We're from teh basements.
    Join Date
    Apr 2007
    Posts
    1,205
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Since my previous post, I've developed a little AJAX framework of sorts. The client consists of a generic state machine, or "portlet", that is initialized by an XML file. The XML file contains a JavaScript template and a behavior set (event handlers for HTML controls in the template) for each method in the back-end "servlet", like so:

    Code:
    <?xml ... ?>
    <portlet servlet-path="http://some_servlet.php">
     <method name="someMethod">
      <template><![CDATA[
    
       <!-- A half-baked example, really... -->
       <? for (i=0;i < someData.length; i++) { ?>
        <tr><td><?=someData[i] ?></td></tr>
       <? } ?>
    
      ]]></template>
      <behavior><![CDATA[
    
       $('#someButton').click(function() {portlet.execute('someOtherMethod',{param1: true, param2: 3.14});});
    
      ]]></behavior>
     </method>
     <!-- And so on for the other servlet methods... -->
    </portlet>
    The execute() method mentioned in the XML file packages the method name and parameters as POST variables and sends the request. The servlet base class has a run() method that executes the named method and handles the details of sending a JSON response to the portlet. I declare the portlet in a Web page like this:

    Code:
    $(document).ready(function() {
     myApp = new Portlet('my_app_description.xml',document.getElementById('divToRenderTheTemplateIn');
     // Render the startup view
     myApp.execute('someMethod',{... params ... });
    });
    The upshot is that the controller is in JavaScript, not in the PHP servlet. The servlet's run() method is the controller part of the server-side MVC; but since it's just a generic dispatcher and JSON-encoder, it doesn't have to be overridden when I extend the servlet base class. Therefore, the extended servlet class is more or less a model, i.e., a set of methods that perform the business logic. This isn't an MVC in the strictest sense, but keeping the controller in the base class provides the necessary separation of concerns between controller and model.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •