Search code examples
javascriptphpbackbone.js

How to execute php through javascript


I am currently using PHP with Backbone.js and in some places I am using PHP to interact with my MySQL server and fill the frontend with Backbone/javascript.

This is the sample PHP I am trying to execute.

$query="select id,username,message,useremail,date from contact";
$result =mysqli_query($connection,$query);
if ($result) {
    echo '<table id="hor-minimalist-b" summary="Users List">
    <thead>
        <tr>
            <th scope="col">User ID</th>
            <th scope="col">User Name</th>
            <th scope="col">User Message</th>
            <th scope="col">User Email</th>
            <th scope="col">Date</th>
        </tr>
    </thead>
    <tbody>';
    while($resultarray=mysqli_fetch_array($result)){
        echo "
        <tr>
            <td>{$resultarray['0']}</td>
            <td>{$resultarray['1']}</td>
            <td>{$resultarray['2']}</td>
            <td>{$resultarray['3']}</td>
            <td>{$resultarray['4']}</td>
        </tr>
        ";
    }
    echo "</tbody>
    </table>";
}

One way is to make a PHP file and make a ajax request to get the HTML output and append in a div container. But since I have way too many PHP code snippets, I wanted to somehow use javascript to ease me, since I am implementing backbone (http://myurl/#link/feed).

Currently, I tried an ugly way: using HTML and calling javascript functions through PHP's echo.


Solution

  • A summary of my comments:

    Gradually integrating Backbone into an existing PHP website is shooting yourself in the foot. Backbone shines when used correctly within a single-page app feeding its data from a RESTful API.

    What you would need is to make a REST API with PHP, exposing your data from the server through different url endpoints used by backbone models and collections. PHP can return anything, it's not limited to HTML, so you could return JSON which javascript can easily parse.

    How to use Backbone with PHP

    The backend API

    Here's a really simple PHP endpoint based on your code.

    example_ajax.php

    <?php
    $query ="select id,username,message,useremail,date from contact";
    $result = mysqli_query($query);
    $rows = array();
    while($r = mysqli_fetch_assoc($result)) {
        $rows[] = $r;
    }
    
    // return the array as JSON so Backbone can automatically parse it.
    print json_encode($rows);
    

    See Creating a simple REST API in PHP

    There are PHP frameworks that handle REST API for you, like:

    The frontend data handling

    Create a custom collection which binds to our newly created endpoint:

    var ContactCollection = Backbone.Collection.extend({
        url: "example_ajax.php",
    });
    

    The static template

    And handle the HTML templating with Backbone views.

    First prepare the HTML template, could be a static HTML on the server.

    <table id="hor-minimalist-b" summary="Users List">
        <thead>
            <tr>
                <th scope="col">User ID</th>
                <th scope="col">User Name</th>
                <th scope="col">User Message</th>
                <th scope="col">User Email</th>
                <th scope="col">Date</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
    
    <script type="text/template" id="contact-template">
        <td><%= id %></td>
        <td><%= username %></td>
        <td><%= message  %></td>
        <td><%= useremail %></td>
        <td><%= date %></td>
    </script>
    

    Backbone views

    Then the views:

    var ContactView = Backbone.View.extend({
        tagName: 'tr',
        template: _.template($('#contact-template').html()),
        initialize: function(options){
            // optional, automatically remove the html of this row only.
            this.listenTo(this.model, 'remove', this.remove);
        },
        render: function() {
            this.$el.empty().append(this.template(this.model.toJSON()));
            return this;
        },
    });
    

    The list view below uses the ContactView as a child view.

    var ContactListView = Backbone.View.extend({
        el: "#hor-minimalist-b", // uses existing element in the page
    
        initialize: function(options) {
            // cache a jQuery element to use as a container for the child views.
            this.$body = this.$('tbody');
    
            // optional, automatically adds a new contact when the collection changes
            this.listenTo(this.collection, 'add', this.renderContact);
        },
        render: function() {
            this.$body.empty();
            this.collection.each(this.renderContact, this);
            return this; // always return this for chaining
        },
    
        renderContact: function(model) {
            var view = new ContactView({ model: model });
            this.$body.append(view.render().el);
        },
    });
    

    How to use it

    var collection = new ContactCollection(),
        view = new ContactListView({ collection: collection });
    view.render();
    
    collection.fetch();
    

    The .fetch() function makes a GET call to something like http://www.example.com/example_ajax.php, which should return an array.

    Why an API? Why not send SQL queries from JavaScript?

    JavaScript runs on the client side, which you should never trust. Instead, you expose specific endpoints on your server, which you can trust. This is why you need an API.

    Sending SQL queries from javascript is a bad idea for several reasons:

    • SQL Injection: Someone could fetch/change anything in your database (including stealing password, or nuking the database all together),
    • It's an open door to your server,
    • Lacks trusted validation, or it's harder to validate a SQL query string,
    • Tight coupling, e.g. making it harder to share queries code between different client (mobile app, website, desktop app, etc)

    It can be done, but it shouldn't.

    phpMyAdmin is an example of an application which takes SQL written by the user and runs it as-is.

    If it's in a controlled environment, like a local intranet, and you want to access MySQL from client-side JavaScript, you could write a php script which takes the body of a request and pass it directly to a MySQL database, returning the result as JSON.

    For example, there's a lib named Squel.js which serve to build SQL query strings. They have a big red box on the frontpage which reads:

    NOTE: It is recommended that you do NOT create queries browser-side to run on the server as this massively increases your exposure to SQL Injection attacks.

    Additionnal reading: