PHP Swagger and Yii - php

I have searched and found i have been lost all day now, and I feel I am going round in circles.
I have written, (with help of a few guides), a simple API for my Yii based application.
I have now come to document this API for other to use it.
I read everywhere that Swagger seems to be the way to go to implement, API documentation.
However I can seem to get anywhere on how to use this application
I have followed the instructions on Swagger PHP
Now I am lost has anyone got any examples of what to do next.
I have tried doing some self annotations of my ApiController.php and this doesnt work. I have been trying using the swagger.phar command line, but I still get no where.
I know you will need a lot more information but i dont know what bits of info you need so rather than pasting lots of useless information please ask and i will send anything you need.
To be honest all i would like is some simple API documentation but it just seems impossible.
Cheers

I have implemented swagger-php in my project. Please follow the below suggested instructions :
1) Download swagger-php(github.com/zircote/swagger-php) and swagger-ui(github.com/wordnik/swagger-ui). Extract them to your workspace.
2) Create a folder called swagger-api and blank php file called index.php in you workspace and paste the following code.
<?php
use Swagger\Annotations as SWG;
/**
* #SWG\Resource(
* apiVersion="0.2",
* swaggerVersion="1.2",
* resourcePath="/api.php",
* basePath="http://localhost/swagger-api/"
* )
*/
// Run this in url
// localhost/index.php?action=get_app_list
// This is the API,show the list in array
/**
*
* #SWG\Api(
* path="/api.php?action=get_app_list",
* description="Operations about get app list",
* produces="['application/json']",
* #SWG\Operations(
* #SWG\Operation(
* method="GET",
* summary="Find facet by ID",
* notes="Returns a facet based on ID",
* type="ListResult",
* nickname="getAllResults",
* #SWG\ResponseMessages(
* #SWG\ResponseMessage(
* code=400,
* message="Invalid ID supplied"
* ),
* #SWG\ResponseMessage(
* code=404,
* message="facet not found"
* )
* )
* )
* )
* )
*/
function get_app_list()
{
//normally this info would be pulled from a database.
//build JSON array
$app_list = array(array("id" => 1, "name" => "Web Demo"),
array("id" => 2, "name" => "Audio Countdown"),
array("id" => 3, "name" => "The Tab Key"), array("id" => 4,
"name" => "Music Sleep Timer"));
return $app_list;
}
$possible_url = array("get_app_list");
$value = "An error has occurred";
if (isset($_GET["action"]) && in_array($_GET["action"], $possible_url))
{
switch ($_GET["action"])
{
case "get_app_list":
$value = get_app_list();
break;
$value = "Missing argument";
break;
}
}
//return JSON array
echo(json_encode($value));
?>
3) Create a folder named swagger-docs in workspace.
4) Open you terminal and go the location of swagger-php in you workspace(i.e cd workpace/swagger-php).
5) Execute the following in your terminal
php swagger.phar /workspace/swagger-api -o /workspace/swagger-docs (This can be executed where we contain swagger.phar file).
6) You will see some files created on your swagger docs folder.
7) Open index.html in swagger-ui/dist/
8) Replace -: url: "http://petstore.swagger.wordnik.com/api/api-docs" to url: "http:localhost/swagger-docs"
9) Run localhost/swagger-ui/dist in your browser.

Related

Get random posts through WordPress API

I am building a self-test project which can give 10 questions at one time from a question list. I want the 10 questions should be different every time I start the test. The front-end is React and the back-end is WordPress by using WordPress API.
Previously I used orderby=rand in the query by implementing a plug-in
<?php
/**
* Plugin Name: REST API - Post list randomize
* Description: Randomize the content list in REST API passing `orderby=rand` as parameter.
* Version: 1.0.0
* Author: Felipe Elia | Codeable
* Author URI: https://codeable.io/developers/felipe-elia?ref=qGTOJ
*/
/**
* Add `rand` as an option for orderby param in REST API.
* Hook to `rest_{$this->post_type}_collection_params` filter.
*
* #param array $query_params Accepted parameters.
* #return array
*/
function add_rand_orderby_rest_post_collection_params( $query_params ) {
$query_params['orderby']['enum'][] = 'rand';
return $query_params;
}
add_filter( 'rest_post_collection_params', 'add_rand_orderby_rest_post_collection_params' );
It worked perfectly until 2 weeks ago. Without modifying any code, it was just broken. I used Postman to test, such as http://localhost/wp/wp-json/wp/v2/questions?per_page=10&orderby=rand. The response is
"code": "rest_invalid_param",
"message": "Invalid parameter(s): orderby",
"data": {
"status": 400,
"params": {
"orderby": "orderby is not one of author, date, id, include, modified, parent, relevance, slug, include_slugs, title."
}
}
Two weeks ago if I used the same query, it could give me 10 random questions. It looks like the plug-in cannot add rand successfully as a parameter for orderby in WordPress like before.
BTW, the functionality of orderby=rand in WP isn't broken because if I manually add rand as a parameter in WP core code, the above query can work again.
Does anybody know what's wrong with the plug-in or some latest updates in WP causing the problem?
Another thing is I saw some articles mentioning ORDERBY = RAND() in MySQL will affect the performance severely when the database is large. So I wonder whether I should use orderby=rand in the query to get random questions or think about other ways to do the job. Does anybody have any suggestions for this performance issue? Thanks!
Found the answer. I need to make the first parameter rest_post_collection_params of add_filter function to the correspondent post type.
The original rest_post_collection_params is for the WP default posts type. Because I use ACF(Advanced Custom Fields, another plug-in to create customized post types) to create my own post types, such as books, I need to change the first parameter to rest_books_collection_params. If you have more customized post types, just create as many as add_filter functions for each of them.
Just have no ideas why I could use rest_post_collection_params for all my customized post types 3 weeks ago but not now. Anyway, since it is solved, don't bother. My project is more front-end oriented. WP is just storage.
BTW, probably someone has noticed that rest_post_collection_params is for the WP default post type posts. In the parameter it uses single form post for the plural form posts. This only works for the WP default post type. For customized types, if it is books, the parameter should be rest_books_collection_param; if questions, then rest_questions_collection_param. Keep the parameter exactly the same as the post type.
For Getting Unique Questions:
table: wp_question_filter_list
id ip_address question_list
1 1.21.23 1,2,3,4,5
2 1.21.24 1,4,6,7,8
3 1.21.25 4,5,6,8,9
function get_unique_questions($ip_address){
global $wpdb;
$table_name = $wpdb->prefix . 'question_filter_list';
$unique_id_list=$wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE ip_address=%d",$ip_address), ARRAY_A);
if (count($unique_id_list) > 0) {
$question_data=$unique_id_list[0];
$arr_question=array();
if(isset($question_data['question_list']) && $question_data['question_list']!=''){
$arr_old_question_id_list=explode(",",$question_data['question_list']);
}
$excludes = implode(',', $arr_old_question_id_list);
$arr_question_id_list=$wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE ip_address='".$ip_address."' AND id NOT IN('".$excludes."') "), ARRAY_A);
set_unique_questions($ip_address,$arr_question_id_list);
}
function set_unique_questions($ip_address,$arr_question_id_list){
global $wpdb;
$table_name = $wpdb->prefix . 'question_filter_list';
$unique_id_list=$wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE ip_address=%d",$ip_address), ARRAY_A);
if (count($unique_id_list) > 0) {
$question_data=$unique_id_list[0];
$arr_question=array();
if(isset($question_data['question_list']) && $question_data['question_list']!=''){
$arr_old_question_id_list=explode(",",$question_data['question_list']);
}
if(is_array($arr_question_id_list) && !empty($arr_question_id_list)){
foreach($arr_question_id_list as $single_question){
array_push($arr_question,$single_question);
}
}
$str_question_id_list=implode(",",$arr_question);
$wpdb->update($table_name, array(
'question_list' => $str_question_id_list
), array(
'ip_address' => $ip_address
));
}else{
$str_question_id_list=implode(",",$arr_question_id_list);
$data = array(
'ip_address' => $ip_address,
'question_list' => $str_question_id_list,
);
$wpdb->insert($table_name, $data);
}
$result = $wpdb->insert($table_name, $item);
}
$ip_address=$_SERVER['REMOTE_ADDR'];
$arr_question_list=get_unique_questions($ip_address);
echo "<pre>";
print_r($arr_question_list);

Internal error due to serialization with paramconverter

I have an API which takes multiple input values. One of them is a date.
When the date is sent, all is fine.
But, when the user isn't sending a date, I have an error 500 with this error message:
Invalid datetime "Some invalid data", expected format Y-m-d\TH:i:sP.
So I wanted to check if the data sent had the format required.
But I don't understand how things are working, hope you can help.
This is what I have
/**
*
* #Rest\Post(
* path = "/signup",
* name = "api_users_add"
* )
* #Rest\View(StatusCode=201, serializerGroups={"user_detail"})
* #ParamConverter(
* "user",
* converter="fos_rest.request_body",
* options={"deserializationContent"={"groups"={"Deserialize"}}},
* )
* #ParamConverter(
* "profile",
* converter="fos_rest.request_body",
* options={"deserializationContent"={"groups"={"Deserialize"}}},
* )
*/
public function postUserAction(Request $request, User $user, Profile $profile)
{
if (!preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$profile->getBirth())){
return new JsonResponse([
'success' => false,
'message' => "Date d'anniversaire au mauvais format"
]);
}
}
But in fact, I never go into this condition, the error 500 is triggered before.
I guess this has something to do with the #ParamConverter from Profile who can't "deserialize" when birth is not a DateTime.
Thing is, I would like to check what is sent (as I did into my condition) in order to avoid this internal error. But I can't find where this is handled on my code.
Thanks for the help.
Considering this : symfony doc for Param converter fos rest bundle
What I am looking for is to find where the validationErrors are specified.

Magento: White page on order view page

Posted this on http://magento.stackexchange.com but I haven't gotten an answer.
I am getting this error for a while and I am clueless to what is wrong with it. Whenever I click the view order page, I get a blank page. Now I installed some code on my index.php that displays the errors.
This is the error that I get:
Array ( [type] => 1 [message] => Class
'Mage_Sales_Block_Order_Info' not found [file] =>
/app/code/core/Mage/Core/Model/Layout.php [line] => 491 )
This is line 491 (and context)
/**
* Create block object instance based on block type
*
* #param string $block
* #param array $attributes
* #return Mage_Core_Block_Abstract
*/
protected function _getBlockInstance($block, array $attributes=array())
{
if (is_string($block)) {
if (strpos($block, '/')!==false) {
if (!$block = Mage::getConfig()->getBlockClassName($block)) {
Mage::throwException(Mage::helper('core')->__('Invalid block type: %s', $block));
}
}
if (class_exists($block, false) || mageFindClassFile($block)) {
$block = new $block($attributes);
}
}
if (!$block instanceof Mage_Core_Block_Abstract) {
Mage::throwException(Mage::helper('core')->__('Invalid block type: %s', $block));
}
return $block;
}
Seems nothing is wrong there (and why should it, its magento default code)
Now the next part is somewhat strange. I expected the class to live in app/code/core/Mage/Sales/Block/Order/Info I looked it up. The folders Order/Info didnt exist in my folder. Nor in the fresh install zip.
What is going on and more importantly, how can I fix this?
I hope you are using latest version of magento never mind even if it is old looks like you are missing some order block files try copying all the files properly. some times you may miss some files while you download the files from magento website check your magento zip file size that you downloaded.

why my streaming api code does not echo anything in php (twitter app)?

I am trying to use the Streaming API from php, I use the code from Matt Harris Streaming code but when I run the code with exec function nevers display a single word neither an error, how can I see the result of the exec function or what am I doing wrong?
This is my code:
<?php
/**
* Very basic streaming API example. In production you would store the
* received tweets in a queue or database for later processing.
*
* Instructions:
* 1) If you don't have one already, create a Twitter application on
* https://dev.twitter.com/apps
* 2) From the application details page copy the consumer key and consumer
* secret into the place in this code marked with (YOUR_CONSUMER_KEY
* and YOUR_CONSUMER_SECRET)
* 3) From the application details page copy the access token and access token
* secret into the place in this code marked with (A_USER_TOKEN
* and A_USER_SECRET)
* 4) In a terminal or server type:
* php /path/to/here/streaming.php
* 5) To stop the Streaming API either press CTRL-C or, in the folder the
* script is running from type:
* touch STOP
*
* #author themattharris
*/
function my_streaming_callback($data, $length, $metrics) {
echo $data .PHP_EOL;
return file_exists(dirname(__FILE__) . '/STOP');
}
require 'tmhOAuth.php';
require 'tmhUtilities.php';
$tmhOAuth = new tmhOAuth(array(
'consumer_key' => 'Y1qoRrUSevAnfpzPJiVpQ',
'consumer_secret' => 'usZvJYGl1y5IRmImyNSVRGyOajMzsBMubzZND7Uh4',
'user_token' => '435894914-UHEEk87wPsiYI4tjSOxYiVvcKZdYon5qSxI376nN',
'user_secret' => '1MDdrNBaMZLStfHmngmEjaW6Lkfy5cNR9ySXiqaGw',
));
$method = 'https://stream.twitter.com/1/statuses/filter.json';
// show Tweets which contan the word twitter OR have been geo-tagged within
// the bounding box -122.41,37.77,-122.40,37.78 OR are by themattharris
$params = array(
'track' => 'soyprole',
// Around Twitter HQ. First param is the SW corner of the bounding box
'locations' => '-122.41,37.77,-122.40,37.78',
'follow' => '777925' // themattharris
);
$tmhOAuth->streaming_request('POST', $method, $params, 'my_streaming_callback');
// output any response we get back AFTER the Stream has stopped -- or it errors
tmhUtilities::pr($tmhOAuth);
and the code that runs the script:
<?php
exec("C:\wamp\www\appTwitterNuevo3\script.php");
?>
exec("C:\wamp\www\appTwitterNuevo3\script.php");
That's not how you execute a PHP file. Also, you have invalid \ (backslashes) there.
You may want to try either of these :
include("C:\\wamp\\www\\appTwitterNuevo3\\script.php");
or
system("C:\\wamp\\php\\php.exe C:\\wamp\\www\\appTwitterNuevo3\\script.php");

How to properly generate exceptions in PHP/Dojo when returning javascript code

I am having difficulty understanding how exceptions are handled when code is fetched dynamically via AJAX and executed via eval. With clientside javascript, it is rather simple, if I have a piece of code such as this
var j = 'some string';
j.propA.x++;
this will raise an exception because propA, which is of type undefined does not have an x. Furthermore, the exception raised is very easy to understand.
Now lets put the above code in a text file, lets call it test.js, and store it on the server. Now lets load it dynamically with Ajax. I am using the following code to load it dynamically
dojo.xhrGet({
url: 'load.php',
handleAs: "javascript",
content : {
fileName : 'test.js'
},
load: function(returnValue) {
/*Do Something*/
},
error: function(errorMessage) {
/*Report Error*/
}
});
Here is a very basic php script for loading the file and returning it as javascript code
<?php
$fileName = $_GET['fileName'];
$handle = fopen($fileName , 'r');
$script = fread($handle, filesize($fileName));
fclose($handle);
echo $script;
?>
In the above dojo.xhrGet call, the error property can be set to a function to display the error message, here is an example of some of the many ways this can be done.
error: function(errorMessage) {
console.error(errorMessage);
console.error(errorMessage.arguments);
console.error(errorMessage.message);
console.error(errorMessage.stack);
console.error(errorMessage.type);
}
Below is an example of the output. Although this output is for a different problem, it highlights how incomprehensible it is:
Cannot read property 'x' of undefined
TypeError: Cannot read property 'x' of undefined
at eval at <anonymous> (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:3088)
at Object.load (http://192.168.1.8/easel.js:166:6)
at http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:89998
at _144 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36518)
at _142 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36328)
at [object Object].<anonymous> (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36994)
at _144 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36780)
at _142 (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36328)
at [object Object].<anonymous> (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:36994)
at Object.resHandle (http://o.aolcdn.com/dojo/1.6/dojo/dojo.xd.js:14:92730)
non_object_property_load
I am assuming dojo.xd.js:14 is the line where the eval statement is.
If one knows what they are looking for, the above might suffice. However, is there an easier, or at least a more productive way to deal with exceptions arising in eval?
Here is a somewhat similar question.
Phikin provided a good solution to this problem below so I gave him the bounty. Using his solution, I got an output which looked something like this (I cut it down a bit)
ReferenceError in JS Code detected: (url: module.require.php?module=MainMenu.Bg_S)
easel.js:211Error Message: ReferenceError: apple is not defined
easel.js:213(function(){
return function(args){
dojo.require("Shape");
Module.assert('MainMenu_V');
/**
* The rectangular background of the Main View
* #property MainMenuBg_S
* #type Shape
**/
new Shape({
/**
* Unique descriptive name used when later accessing this shape via '$$()'
* #param name
* #type String
**/
name : 'MainMenu.Bg_S' ,
/**
* Left side of this rectangle
* #param x
* #type Number
**/
x : $$('MainMenu_V').x ,
/**
* Top of this rectangle
* #param y
* #type Number
**/
y : $$('MainMenu_V').y ,
/**
* Width of this rectangle
* #param w
* #type Number
**/
w : $$('MainMenu_V').w ,
/**
* Height of this rectangle
* #param h
* #type Number
**/
h : $$('MainMenu_V').h ,
/**
* Type of this Shape
* #param h
* #type Number
**/
type : shapeType.RECTANGLE ,
/**
* Generate function which contains all the graphics instructions, as well as the contexts
* to preload and initialize. This is currently under development. Backgrounds should NEVER
* have mouse events associated with them as a redraw of a background implies a redraw of
* every single displayObject infront of the background.
* #param generate
* #type method
**/
generate : function (){
var x = this.x << 0 , y = this.y << 0 , h = this.h << 0 , w = this.w << 0 , a = this.a;
this.graphics(contextID.LEAVE).lf([hsl(180,100,60,0.9),hsl(180,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.ENTER).lf([hsl(135,100,40,0.9),hsl(135,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.CLICK).lf([hsl(90,100,40,0.9),hsl(90,50,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.RCLICK).lf([hsl(90,110,40,0.9),hsl(80,60,20,0.45)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.DBLCLICK).lf([hsl(45,100,40,0.9),hsl(45,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.DBLRCLICK).lf([hsl(10,100,40,0.9),hsl(10,100,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.LPRESS).lf([hsl(110,25,40,0.9),hsl(110,25,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.RPRESS).lf([hsl(110,50,40,0.9),hsl(110,50,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
this.graphics(contextID.SCROLL).lf([hsl(110,50,40,0.9),hsl(110,50,20,0.75)],[0,1],0,h/2,w,h/2).dr(x,y,w,h).ef();
if (debugFlags.BOUNDINGBOX()){
this.graphics(contextID.ENTER).ss(2).s(rgba(0,255,0,a)).dr(this.boundingBox.softBounds.L +4<<0, this.boundingBox.softBounds.T +4<<0, this.boundingBox.softBounds.w-8<<0 , this.boundingBox.softBounds.h-8<<0).es();
this.graphics(contextID.ENTER).ss(2).s(rgba(255,0,0,a)).dr(this.boundingBox.bounds.L +4<<0, this.boundingBox.bounds.T +4<<0, this.boundingBox.bounds.w-8<<0 , this.boundingBox.bounds.h-8<<0).es();
this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[0].x+4 , this.boundingBox.points[0].y+4 , 4).ef();
this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[1].x-8 , this.boundingBox.points[1].y+4 , 4).ef();
this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[2].x-8 , this.boundingBox.points[2].y-8 , 4).ef();
this.graphics(contextID.ENTER).f(rgba(0,0,255,a)).dc(this.boundingBox.points[3].x+4 , this.boundingBox.points[3].y-8 , 4).ef();
}
},
/**
* Arguments to pass to the mouse initialization function. These will get mixed in (via
* dojo.mixin) to the mouse object. To increase performance, the signalOrderIn has been set to
* NOHIT. This will limit the number of redraws (remember background redraws are extremely
* expensive as they require redrawing everything in the container). The signalOrderOut is
* then set to BLOCK to prvent anything behind the background from receiving mouse signals
* (this is actually unecessary as the only think behind the background is, and always should
* be, the container, which itself has signalOrderIn and signalOrderOut set to NOHIT and BLOCK
* respectively).
* #param mouse
* #type Object
**/
mouse : {
_signalOrderIN : signalFlags.NOHIT ,
_signalOrderOUT : signalFlags.BLOCK
} ,
/**
* All views are initially loaded via Ajax. Generally, views do not have any preconditions, beyond
* that the stage be present. They can, however, and generally do, have modules they require. These
* are called after this view has been created and loaded (load() function call). They are called
* in the order of the sub arrays. In the example below:
* [[A , B , C , D , E , F , G]]
* The 7 modules are requested in that order, but, due to Ajax, they can be loaded in any order.
* In the below example, on the other hand:
* [[A] , [B , C , D , E , F , G]]
* Modules B-G depend on module A, therefore, module A is ordered to be loaded first.
* #property providedModules
* #type Array[Array[String]]
* #protected
**/
providedModules : [[]] ,
/**
* Carries out all the initializations when loading the module
* #method load
* #protected
**/
load : function (){
0/apple;
$$('MainMenu_V').addChild(this);
} ,
/**
* Carries out all memory deallocation when leaving the module (generally only necessary if modules
* were loaded but not added to stage as in the case with cached bitmaps)
* #method leave
* #protected
**/
leave : function (){
}
});
$$('MainMenu.Bg_S')._code="dojo.require(\"Shape\");...";
};
}());
easel.js:217Error triggered by: function (_2bd){return err.call(args,_2bd,_2b7);}
easel.js:220XHR Object:
easel.js:221
Object
args: Object
handleAs: "javascript"
query: null
url: "module.require.php?module=MainMenu.Bg_S"
xhr: XMLHttpRequest
__proto__: Object
easel.js:222Error Object:
easel.js:223
ReferenceError
arguments: Array[1]
message: "—"
stack: "—"
type: "not_defined"
__proto__: Error
dojo.xd.js:14
ReferenceError
arguments: Array[1]
message: "—"
stack: "—"
type: "not_defined"
__proto__: Error
dojo.xd.js:14
ReferenceError
arguments: Array[1]
message: "—"
stack: "—"
type: "not_defined"
__proto__: Error
The only thing it's missing, that I need, is the ability to indicate what line the problem occurred.
Here is a snipped that detectes non-network related errors from an xhr-get request and outputs some information about it in the console.
There is an extra isEvalError() function that goes through all eval-error types... which I am not really proud of. A nicer way could be by getting the parent object of the errorMessage sub-classes.
I think you can ditch isEvalError() generally, because there shouldn´t be any other error possible in this block.
function isEvalError(errorMessage){
return errorMessage.name == "RangeError" ||
errorMessage.name == "ReferenceError" ||
errorMessage.name == "SyntaxError" ||
errorMessage.name == "URIError" ||
errorMessage.name == "TypeError";
}
var foo = dojo.xhrGet({
url: 'stacko.js',
handleAs: "javascript",
load: function(returnValue) {
console.log("load: "+returnValue);
},
error: function(errorMessage,ioargs) {
//request worked fine, this must be a non-network related error
if(ioargs.xhr.readyState == 4 && ioargs.xhr.status == 200) {
if(isEvalError(errorMessage)){
//show eval-error, url request & the JS code that causes the exception
//eval-error types: RangeError,ReferenceError,SyntaxError, URIError, TypeError
console.error(errorMessage.name+" in JS Code detected: (url: "+ioargs.url+")")
console.error("Error Message: "+ errorMessage);
console.error(ioargs.xhr.responseText);
}
//a little reflection - if u want to know who triggered this error
//(although in this case the output is not very helpful )
console.error("Error triggered by: "+arguments.callee.caller.toString());
//last but not least log the error & the xhr-request object for more information
console.error("XHR Object:");
console.error(ioargs);
console.error("Error Object:");
console.error(errorMessage);
}
}
});
It really depends on what you mean "productive way to deal with exceptions". If all you need to do is view the exception contents, a simple
console.log(errorMessage);
will allow you to effortlessly inspect the error object in decent browser like Chrome or Firefox (with Firebug). (Instead of forcing you to do a ton of console.log statements)
An annoying thing about Dojo exceptions inside asynchronous code is that they are always caught and handled so most browser debuggers ignore them. A notable exception to this rule is Chrome, where you can tell the debugger to pause on all exceptions.
BTW: I don't see how Javascript exceptions and Dojo have anything to do with PHP in this case, since they occur on the client side and there is nothing the server can do about them. Also, what the hell are you doing by sending Javascript code in the AJAX? Most of the time a client does a request it will be for data, in plain text, JSON or XML.

Categories