Welcome Guest, Not a member yet? Register   Sign In
Releasing CI Models in javacript! [ajax proxy]
#1

[eluser]GreatSlovakia[/eluser]
Imagine you could directly call your models right from your javascript. Just think a few seconds what that would mean... thought about it? In ColdFusion there is native functionality for this and now I build it into codeigniter as well Big Grin

EXAMPLE

Let's first explore how it looks like:

A fairly normal model, except for the new "__JS" method. This method defines that the model can be used from javascript (the allow some more customization which I will explain later on)

exampleModel.php:
Code:
<?php
class Modelname extends CI_Model {

    function __JS(){
        return true;
    }

    function hello($name='world'){
        return array("hello" => $name);
    }

    function sql(){
        $this->db->select()->from('data');
        return $this->db->get()->result();
    }

}

Next there is some configuration stuff I will skip, so let's look at the most simplistic controller possible:

exampleController.php
Code:
<?php
class Test extends CI_Controller {

    public function index(){
        $this->load->ajax_model("exampleModel");
    }

}

And that's it, now if you would enter into the console exampleModel you will get back a javascript object with the same functions and functionality as the original php model: [Image: 2itlerk.jpg] (or look below at the attached file)

Code:
data=exampleModel.sql();
alert(data[0].text);

INSTALLATION

Lets get to the installation stuff, first add the MY_Loader.php to the core directory (copy it from here). Next either create a new controller or add a method to an existing controller containing
Code:
$this->load->ajax_proxy();
and reference this point from your config file by adding
Code:
/*
|--------------------------------------------------------------------------
| Ajax proxy gateway
|--------------------------------------------------------------------------
|
| Define the controller/method which will act as the ajax proxy gateway
| for php models in javascript. The controller/method should contain
| the following call: $this->load->ajax_proxy();
|
*/
$config['ajax_proxy'] = "ajax/index";
And that's it already, you're ready to go Big Grin

CUSTOMIZATION

THE __JS() FUNCTION
Exclude specific methods from being accessed from javascript
Code:
function __JS(){
    return array(
        "type"=>"exclude",
        "methods"=>Array("sql")
    );
}
Or specifically specify which methods can be called (e.g. if you want to call the constructor function you will need to specify it here by hand). The following will ONLY allow you to call the sql function:
Code:
function __JS(){
    return array(
        "type"=>"included",
        "methods"=>Array("sql")
    );
}

THE ajax_model() FUNCTION

Just like with the normal model function it is possible to specify a second parameter containing the name which the model should use, e.g.
Code:
public function index(){
    $this->load->ajax_model("exampleModel","modelName");
}
will cause an object to be available in javascript called modelName

Tips, Tricks & Security with the __JS() function
Exposing models to the outside world might be quite dangerous to do, however using the __JS function you can protect your model whilst keeping all your checks outside the functions themselves. Take for example
Code:
function __js(){
    $CI =& get_instance();
    if($CI->ion_auth->logged_in()){
        return true;  
    }else{
        return false;  
    }
}
which won't allow anybody to access the functions whilst not being logged in and you can take this to the next level by checking the $_POST['data'] array to see whether the requested action is allowed, for example quite often it is possible to check whether the user has access to the relevant record ($_POST['data']['id']) or allow users access to different methods depending on the groups they are in. This is normally not necessary of course (the last part), but it does show the countless possibilities provided by the __JS function.

FAQ

Why did I place this inside an Loader.php extend?
Despite the fact that this could just as well be used as a stand alone library (just a few small changes would be necessary), I created it like this because I am currently working on implementing a number of functions from coldfusion in codeigniter and I would like these functions to be part of the core, as that's unlikely to happen anytime soon (due to the way the impregnable guidelines which protect codeigniter) I want to at least treat and design it as much as core stuff as possible. Secondly I am still trying to build a neat solution which would make "ajax" a reserved controller name and bypass the need of the ajax_proxy() function. I got quite close to this by building a hellish MY_Router.php file, but it was so ugly that I didn't dare to release it Tongue.

So what does this exactly do?
Look at the image which you doubtlessly missed, as ExpresionEngine seems to not support img tags or something :S [Image: 2itlerk.jpg] or check out the attachment below.

How does this work?
When you call one of the javascript functions it will JSON.stringify the arguments and call the ajax proxy controller method which in turn will call the model for your, which will json_encode() the return value for you which will be returned by the javascript function to your script. However, in essence, you probably should worry about that and simply use it. The only thing you might need to be aware of is that you should only return arrays or simple types (integers, strings, etc.) inside your model, although objects will sometimes work as well.

... why is there a 6000 character limit :S...
#2

[eluser]benboi[/eluser]
Looks nice, thanks Wink ill give it a try.
#3

[eluser]GreatSlovakia[/eluser]
Hope u liked it at least@benboi. Got to say I am suprised nobody liked it "more". I just mean, when I first heard about ajax proxies in coldfusion my initial reaction was... why in the world would you need "proxies" for that... later on I read through it and once I realised what it actually did I was really excited about it. I mean, it's the most fluent two-way communication I have ever heard about between javascript and php.

Would anybody care to explain why they think this isn't great? (and I am not talking about my implementation, but about the idea itself, because fair is fair, all credits go to whoever came up with this first (although the implementation wasn't easy neither Tongue))
#4

[eluser]Sayian[/eluser]
Thanks!

Looks worthwhile to test out this weekend.
#5

[eluser]Sayian[/eluser]
Hello,

Tested this out and I'm having problems getting it to work.

I followed the above directions for installation.

-- In config.php

Code:
$config['ajax_proxy'] = 'test/index';

-- In Controller "Test.php"

Code:
class Test extends MY_Controller {

    public function __construct()
    {
        parent::__construct();
    }

    public function index() {

        $this->load->ajax_model("Modelname","modelName");
    }

}

-- In Modelname.php

Code:
class Modelname extends CI_Model {

    function __JS(){
        return true;
    }

    function hello($name='world'){
        return array("hello" => $name);
    }

    function sql(){
        $this->db->select()->from('data');
        return $this->db->get()->result();
    }

}

... Then from another controller named Dashboard

Code:
class Dashboard extends Account_Controller {

    public function __construct()
    {
        parent::__construct();

        // Load needed libraries.
        $this->load->ajax_proxy();

    }

And I get the following errors:

Code:
A PHP Error was encountered

Severity: Notice

Message: Undefined index: model

Filename: core/MY_Loader.php

Line Number: 26
A PHP Error was encountered

Severity: Notice

Message: Undefined index: model

Filename: core/MY_Loader.php

Line Number: 27

Fatal error: Cannot access empty property in /home/***/application/core/MY_Loader.php on line 27

I'm pretty tired and might have missed something small .. nice work so far though.
#6

[eluser]GreatSlovakia[/eluser]
Hmm... guess I wasn't clear enough, so the ajax_config should point to a controller[slash]method which contains ONLY
Code:
$this->load->ajax_proxy();
Next in the page you want to load a model you use the normal model loading syntax with the ajax_ added before it, so e.g.
Code:
$this->load->ajax_model("Modelname");
So in other words, you had those two switched around.


Secondly it's a (very) good idea to place the
Code:
$this->load->ajax_model("Modelname");
always inside the head portion of your view, as technically it outputs some javascript stuff.

So what you need to prepare before using it is the following (although you can customize it in lots of different ways Tongue)

- Core
-- MY_Loader.php
- Config
-- config.php containing
Code:
$config['ajax_proxy'] = "ajax";
- Controllers
-- Ajax.php containing
Code:
<?php
class Ajax extends CI_Controller {

    public function index(){
        $this->load->ajax_proxy();
    }
}

And lastly I am going to update the the customization portion of the OP with a cool way to use the __JS function in combination with security and user authentication in half an hour or so (currently working on a project where I am using it Big Grin)




Theme © iAndrew 2016 - Forum software by © MyBB