Skip to content

Instantly share code, notes, and snippets.

@splittingred
Created April 9, 2012 21:48
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save splittingred/2346752 to your computer and use it in GitHub Desktop.
Save splittingred/2346752 to your computer and use it in GitHub Desktop.
Example of how to use new REST server class in MODX 2.3+
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(.*)$ rest/index.php?_rest=$1 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ rest/index.php [QSA,NC,L]
</IfModule>
<?php
/**
* Found at: Controllers/Box.php
*
* Handle requests to [URL]/Controllers/Box. Automagically handles CRUD (GET/POST/PUT/DELETE) for the xPDOObject class myBox.
*/
class myControllersBox extends modRestController {
public $classKey = 'myBox';
public $defaultSortField = 'name';
public $defaultSortDirection = 'DESC';
}
<?php
/**
* Place in /rest/ directory of site. Add .htaccess file above. Note that our REST controllers are in /rest/Controllers/; they can be anywhere though - just change the basePath config option.
*/
/* first load MODX externally */
require_once '/path/to/modx/config.core.php';
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx = modX::getInstance('rest');
$modx->addPackage('myboxes','/path/to/myboxes/model');
/* now load the REST service */
$rest = $modx->getService('rest','rest.modRestService','',array(
'basePath' => dirname(__FILE__).'/Controllers/',
'controllerClassSeparator' => '',
'controllerClassPrefix' => 'myControllers',
'xmlRootNode' => 'response',
));
$rest->prepare();
if (!$rest->checkPermissions()) {
$rest->sendUnauthorized(true);
}
$rest->process();
/**
* A GET request to our controller at /rest/box.js will output something like this:
*/
{
results: [{
id: 1,
name: 'A Blue Box',
width: 20,
height: 40
},{
/* etc */
}]
,total: 23
}
<!--
A GET request to our controller at /rest/box.xml, however, will output something like this - the class automatically handles XML/JSON output types:
-->
<response>
<results>
<result>
<id>1</id>
<name>A Blue Box</name>
<width>20</width>
<height>40</height>
</result>
<result>
<!-- etc -->
</result>
</results>
<total>23</total>
</response>
Copy link

ghost commented Nov 19, 2013

Hi Shaun,
thank you for this example, unfortunately I get the following error message

{"success": false, "message": "Method not allowed", "object": [], "code": 405}

Please can you tell me how I can create a simple request.
for example:
get username of an existing user based on the id?

Thanks a lot Thomas

@pixelchutes
Copy link

Finally had my MODX 2.3 RESTful breakthrough! In order for me to get this to work, I had to make the following changes:

NOTE the RewriteBase and adjusted RewriteRule paths...

RewriteEngine On
RewriteBase /rest/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(.*)$ index.php?_rest=$1 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ index.php [QSA,NC,L]

Big thanks to @BobRay for his Custom Database Tables post: http://bobsguides.com/custom-db-tables.html
That is what allowed me to connect the dots and establish a working model for use via _$modx->addPackage()_. Just follow that tutorial and then make the following adjustments:

In rest/index.php:

<?php
$modx->addPackage('myboxes','/path/to/myboxes/model');

became:

<?php
$path = MODX_CORE_PATH . 'components/quotes/';
$modx->addPackage('quotes', $path . 'model/','bobs_');

And in rest/Controllers/Box.php:

<?php
public $classKey = 'myBox';

became:

<?php
public $classKey = 'Quotation';

I was able to confirm new record creation (CRUD) via POST, and then retrieve it via GET (e.g. Read):

http://domain.com/rest/box/1
{
    "message": "",
    "object": {
        "author": "mlk",
        "id": 1,
        "quote": "i have a dream",
        "topic": "cool"
    },
    "success": true
}
http://domain.com/rest/box/2
{
    "message": "",
    "object": {
        "author": "neil",
        "id": 2,
        "quote": "one small step",
        "topic": "alright"
    },
    "success": true
}

You should now be able to start customizing your own model and controller in place of the above examples and move forward with native REST in MODX 2.3. 👍

@insytes
Copy link

insytes commented Jun 10, 2014

Brilliant!

I have been thinking about writing up a REST class for a while now. Can't wait to try this one out though.

@fortunto2
Copy link

hi
please help convert rules to nginx+php-fpm

@Ibochkarev
Copy link

nginx configuration

location /rest/ {

  if (!-e $request_filename){
          rewrite ^/rest/(.*)$ /rest/index.php?_rest=$1;
  }

  if (-e $request_filename){
          rewrite ^/rest/(.*)$ /rest/index.php;
  }
}

Please try.

@nick2687
Copy link

Here is an example of how you can preform Basic Auth (login & logout) as a controller.

<?php
/**
 * Found at: Controllers/Auth.php
 *
 * Handle requests to [URL]/Controllers/Auth. Automagically handles login / log-out requests (basic auth) - should only be used over https
 */
class APIAuth extends modRestController {

    public $classKey = 'modUser';
    public $defaultSortField = 'id';
    public $defaultSortDirection = 'ASC';

    public function verifyAuthentication() {

        if ($this->request->method != 'get') Throw new Exception('Method Not Allowed', 405); // Only allow GET requests to the AUTH controller

        if ($this->modx->user || $this->modx->user->id >= 1) { // If user is logged in & user passes the "logout" param than log them out
            if ($_GET['logout']) {  
                $this->modx->runProcessor('security/logout',array(
                                'login_context' => $this->getProperty('loginContext', $this->modx->context->get('key')),
                                'add_contexts' => $this->getProperty('contexts',''),
                            ));
            } 

        }
        if (!$this->modx->user || $this->modx->user->id < 1) {  // If not logged in & user passes a username & password preform basic auth by running login processor
            $c = array(     
                'username' => $_GET['username'],
                'password' => $_GET['password'],
            );
            $this->modx->runProcessor('security/login',$c);

        }


        if (!$this->modx->user || $this->modx->user->id < 1) return false;  //finally do a check to see if user is logged in or not & either send back a true or false
        return true;
    }


    protected function prepareListQueryBeforeCount(xPDOQuery $c) { // If user is logged in return their basic user info


            $c->where(array(
                'id' => $this->modx->user->id
            ));

            return $c;  

    }  


} 

@MarkOdey
Copy link

Hey Guys, I would like to say thank you for the precious insight on how to implement a custom api. It has been very usefull since I am currently working on angularjs and a restful api is very useful if not necessary for it.

I have managed to make make my way pretty fine so far however I have noticed some few details that maybe someone could help me figure out or provide a fix for it.

First, I have noticed that none of my static snippet reference works.

Fatal error: Call to a member function checkPolicy() on a non-object in C:\wamp\www\pictographix\core\model\modx\modx.class.php on line 1880

This would be very useful for me as when I change environement with git, I don't want to resynchronize everytime my database.

Second I am unable to use some shorthand methods available normally with the modResource class and the modChunk. Therefore, getTVValue() , and getChunk() doesn't work. I have been able to countereact this problem but just to ensure compatibility in my code when I request snippets in my chunks it would be better for those to work.

Cheers

Mark

@eveningcoffee
Copy link

Hi, I was hoping someone would be able to help me, I've followed @BobRay 's tutorial for creating a package and made the amends to my files that @pixelchutes listed and I still can't seem to get it to work. I get the error code when I visit www.domain.com/rest.

{"success":false,"message":"Method not allowed","object":[],"code":405}
But it returns nothing when I visit www.domain.com/rest/box/1

@pixelchutes
Copy link

pixelchutes commented Sep 22, 2016

btw, here's the nginx configuration I eventually converted to:

location /rest/ {
    try_files $uri @modx_rest;
}

location @modx_rest {
    rewrite ^/rest/(.*)$ /rest/index.php?_rest=$1&$args last;
}

EDIT: Updated MODX REST docs

@eveningcoffee, did you ever get it straightened out? It could be a matter of where your .htaccess rule is placed (assuming you're on Apache), as in my example it was placed inside the /rest/ folder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment