Manol Posted December 8, 2014 Share Posted December 8, 2014 Hello. I would like to make an ajax call and get some data back. The way I use to do it is, make a call from javascript to a url that would be a pw page that uses the template that would return the data, like this: Define a page under /web-service/get-page that uses getpage.php template Javascript (angularjs) $http({url: '/web-service/get-page/', method: "POST", data: { pageId: pageId }} ) .success(function(response){ deferred.resolve(response); }); PHP template ( getpage.php ) <?php /** * datos enviados mediante JSON * @return [type] [description] */ function getPost(){ $request = file_get_contents('php://input'); return json_decode($request,true); } $getPost = getPost(); $pageId = $getPost['pageId']; $pagina = wire('pages')->get($pageId); $array = array(); // fields to be avoided $avoid = array("FieldtypeFieldsetOpen", "FieldtypeFieldsetClose","FieldtypeFieldsetTabOpen","FieldtypeFieldsetTabClose"); foreach($pagina->fields as $field) { if (!in_array($field->type, $avoid)) { // si el campo no esta vacio if( htmlentities($pagina->get($field->name)) ) $array[$field->name] = htmlentities($pagina->get($field->name)); } } echo json_encode($array); ?> My question is: How can I avoid creating a template and defining a page that uses it? I wish to intercept the ajax call from a module and return the data from that module without creating templates and pages. Is that possible? Thank you. Link to comment Share on other sites More sharing options...
kongondo Posted December 8, 2014 Share Posted December 8, 2014 (edited) How can I avoid creating a template and defining a page that uses it? See options #1 (post to script outside PW directories) and 3 (post to same page) here: https://processwire.com/talk/topic/407-processing-contact-forms/?p=3106 I wish to intercept the ajax call from a module and return the data from that module without creating templates and pages. If you go with option #3 you can intercept right within same page, call your module, do your stuff and return the data Btw, in case you were not aware...https://processwire.com/talk/topic/225-how-to-work-with-ajax-driven-content-in-processwire/ if($config->ajax) { // page was requested from ajax // can optionally include external php scripts // call your module and do stuff } Edited December 8, 2014 by kongondo 5 Link to comment Share on other sites More sharing options...
Manol Posted December 9, 2014 Author Share Posted December 9, 2014 Probably what I'm asking for is simpler than what I've exposed in the lines above. Just need to catch an ajax call from a pw module and return some data back. .The ajax call can come from a mobile device or other website located in a different server. Thank you Link to comment Share on other sites More sharing options...
Soma Posted December 9, 2014 Share Posted December 9, 2014 You can with a autoload module in the init() method, use the wire("config")->ajax and maybe check for post values etc and return output then exit() if(wire("config")->ajax){ if(wire("input")->post->something){ echo "hello"; exit; } } 2 Link to comment Share on other sites More sharing options...
Manol Posted December 9, 2014 Author Share Posted December 9, 2014 Still not getting there. 1.- Javascript (angularjs) $http.post('http://mywebpage/user/', {name:'manol'}). success(function(data) { console.log(data); }). error(function(data) { console.log(data); }); 2.- and I wish to get json data back # PW MODULE $array = array(); $array['name'] = wire("user")->name; $array['language'] = wire("user")->language->title; $event->return = json_encode($array); 3.- Which hook or whatever should I use?, http://mywebpage/user/ doesn't correspond to any template. Link to comment Share on other sites More sharing options...
Jan Romero Posted December 9, 2014 Share Posted December 9, 2014 You can create a web-accessible php file anywhere on your server and bootstrap ProcessWire from there, without creating a page as far as PW is concerned. An example: <?php /* This file is nowhere in particular and not a template or anything. */ require_once("./cms/processwire/index.php"); $name = $wire->input->post->name; if ($wire->input->post->name == 'manol') { $m = $wire->modules->get('CoolModule') die($m->welcome($name)); } die('Hello anyway.'); I have no experience with this, so I can’t tell you about potential drawbacks, if there are any. Another way to avoid creating a “page” would be to allow urlSegments for your root page and handle the input there. It would look like any other page but it won’t disturb anyone’s aesthetic sensibilities in the admin backend. 1 Link to comment Share on other sites More sharing options...
kongondo Posted December 9, 2014 Share Posted December 9, 2014 @Jan....minus the urlSegments bit, that's exactly one of the answers I provided in my post above (#2)...which @Manol didn't consider as the solution 1 Link to comment Share on other sites More sharing options...
Jan Romero Posted December 9, 2014 Share Posted December 9, 2014 Whoops, sorry, I’m embarrassed. I only skimmed the code samples. @Manol: if I understand correctly, you want to create this “pseudo page” (web-accessible, but not any distinct file or PW page) from within your module? 1 Link to comment Share on other sites More sharing options...
Manol Posted December 9, 2014 Author Share Posted December 9, 2014 Just want to call a pw webservice from a mobile device and the service logic within a pw module. Link to comment Share on other sites More sharing options...
Jan Romero Posted December 9, 2014 Share Posted December 9, 2014 (On mobile, haven’t tested) Maybe try hooking into ___PageNotFound() in ProcessPageView. It gives you the requested URL, so you can check if that’s what your module expects and process it. That way your module could remain self-contained. If $input isn’t populated at that point, you should always be able to go through $_POST. 1 Link to comment Share on other sites More sharing options...
Jan Romero Posted December 10, 2014 Share Posted December 10, 2014 I just tested it and I think this is what you want. Here’s a complete demo module: class NotFoundIntercept extends Wire implements Module { public static function getModuleInfo() { return array( 'title' => 'Not Found Intercept ', 'version' => 001, 'summary' => 'Hooks into pageNotFound so you can handle URLs that don’t belong to any page.', 'href' => 'https://processwire.com/talk/topic/8510-module-intercept-ajax-call/', 'autoload' => true, ); } public function init() { wire()->addHook('ProcessPageView::pageNotFound', $this, 'intercept404'); } protected function intercept404($event) { $url = $event->arguments('url'); if ($url != '/my_pseudo_page/') return; //Let pageNotFound() handle it header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK', true, 200); $name = $_GET['name']; if ($name) die("Hola $name! Como estas?"); else die("Sup, guest?"); } } Now you can open ejemplo.es/my_pseudo_page/?name=Manol and – provided that page doesn’t exist in PW – it will greet you. Of course, if the front page has urlSegments enabled, it will just accept that instead, and your module won’t be triggered... 3 Link to comment Share on other sites More sharing options...
Manol Posted December 10, 2014 Author Share Posted December 10, 2014 Fantastic Jan you're my star, it was a really good idea, now: PwAngular.module class PwAngular extends WireData implements Module, ConfigurableModule { ... public function init() { $this->addHook('ProcessPageView::pageNotFound', $this, 'webService'); ... public function webService($event) { // Check if asking for a web service $url = $event->arguments('url'); if ($url != '/web-service/') return; //Let pageNotFound() handle it header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK', true, 200); // Get post Data $request = file_get_contents('php://input'); $getPost = json_decode($request,true); $action = $getPost['action']; switch ($action) { case "getPage": $pageId = $getPost['pageId']; $event->return =$this->get_Page($pageId); break; } } protected function get_Page($pageId) { $pagina = wire('pages')->get($pageId); $array = array(); // fields to be avoided $avoid = array("FieldtypeFieldsetOpen", "FieldtypeFieldsetClose","FieldtypeFieldsetTabOpen","FieldtypeFieldsetTabClose"); $array['id'] = $pagina->id; foreach($pagina->fields as $field) { if (!in_array($field->type, $avoid)) { // si el campo no esta vacio if( htmlspecialchars($pagina->get($field->name)) ) if($field->type == "FieldtypePage"){ $buscar = htmlspecialchars($pagina->get($field->name)); $paginas = $pages->get($buscar); $array[$field->name] = $paginas->title; } else { // if textarea do not strip html tags if($field->type == "FieldtypeTextarea" || $field->type == "FieldtypeTextareaLanguage" ){$array[$field->name] = $pagina->get($field->name);} else {$array[$field->name] = htmlspecialchars($pagina->get($field->name));} } } } return json_encode($array); } my.js $http.post('http://ip/web-service/', {action: 'getPage', pageId: 1046 }) .success(function(data) { console.debug("success",data); }) and BUMP! working. Link to comment Share on other sites More sharing options...
Soma Posted December 10, 2014 Share Posted December 10, 2014 You don't really have to hook page not found... just check for ajax and a POST var in the init() of a autload module as I wrote before ... public function init(){ if(!$this->config->ajax) return; if($this->input->webservice){ $id = $this->input->id; echo json_encode(array("status" => "ok", "data" => $id)); exit; } } and you would call a url like your root http://domain.com/?mywebservice&id=10 or using post works with same code 3 Link to comment Share on other sites More sharing options...
Manol Posted December 10, 2014 Author Share Posted December 10, 2014 Hi Soma. I've tried your way like you posted yesterday and today but I'm getting back the whole page maybe because my call is $http.post('http://ip/web-service/', {action: 'getPage', pageId: 1046 }) .success(function(data) { console.debug("page",data); }) As Jan pointed $this->addHook('ProcessPageView::pageNotFound', $this, 'webService'); is working for me, maybe is not the best way but it works as expected. Thank you Link to comment Share on other sites More sharing options...
Soma Posted December 10, 2014 Share Posted December 10, 2014 It works. You might haven't configured all correct. This in the init() method public function init() { if($this->config->ajax && $this->input->it == "webservice/"){ if(!$this->input->action) return; $out = array( "it" => $this->input->it, "action" => $this->input->action, "pageid" => $this->input->pageid, ); header('Content-type: application/json'); echo json_encode($out); exit(); } } and then this jquery ajax call work just fine <script> $(function(){ $.ajax({url:'/webservice/', data: {action: 'getPage', pageid: 1001}, method: 'post'}).success(function(data){ console.log("page", data); }); }); Nothing wrong with the PageNotFound as far as I can tell I'm using both approaches 3 Link to comment Share on other sites More sharing options...
Jan Romero Posted December 10, 2014 Share Posted December 10, 2014 Ooooh, I didn't know about $input->it. That's awesome. Where does it come from, though?! I've never seen it anywhere. Where in the core is it prepared? Link to comment Share on other sites More sharing options...
Soma Posted December 11, 2014 Share Posted December 11, 2014 It comes from htaccess $_GET['it'] Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now