I found this very interesting project on github: https://github.com/brannondorsey/apibuilder
After starting using it, I noticed that the request limitation won't work properly. The value for the requests in the MySQL database counts to "1000" (or the limit set in $hits_per_day), but the API output is still some data from the database.
The expected error message is simply attached to the API response.
But I would like to have an API that doesn't allow any output and only the error message. Below you can find the concerning file.
public function get_json_from_assoc(&$get_array){
$json_obj = new StdClass();
$pretty_print = $this->pretty_print;
if(!$this->find_config_errors()){
if(isset($get_array['pretty_print'])){
if(strtolower($get_array['pretty_print']) == "true") $pretty_print = true;
if(strtolower($get_array['pretty_print']) == "false") $pretty_print = false;
}
//if API is public or if API is private and a correct private key was provided
if(!$this->private ||
$this->private &&
isset($get_array['private_key']) &&
$this->private_key == $get_array['private_key']){
$query = $this->form_query($get_array);
if($this->check_API_key()
|| !$this->API_key_required){
//if search was included as a parameter in the http request but it isn't allowed in the api's config...
if(isset($get_array['search']) &&
!$this->search_allowed){
$json_obj->error = "search parameter not enabled for this API";
}
else if(isset($get_array['exclude']) &&
!$this->exclude_allowed){
$json_obj->error = "exclude parameter not enabled for this API";
}else{
if($results_array = Database::get_all_results($query)){
if(is_array($results_array)){
// deletes key => value pairs if the value is empty. Only works if array is nested:
// http://stackoverflow.com/questions/5750407/php-array-removing-empty-values
$results_array = array_filter(array_map('array_filter', $results_array));
foreach($results_array as $result_array){
foreach($result_array as $key => $value){
if($key == "COUNT(*)"){
$count = $value;
break;
}
}
}
if(!isset($count)) $json_obj->data = $results_array;
else $json_obj->count = $count;
//COME BACK need to make count only parameter work
}
}else $json_obj->error = "no results found";
}
//only attempt to increment the api hit count if this method is called from a PUBLIC API request
if($this->API_key_required){
$query = "SELECT " . $this->API_hit_date_column_name . " FROM " . Database::$users_table . " WHERE " . $this->API_key_column_name . " = '" . $this->API_key . "' LIMIT 1";
$result = Database::get_all_results($query);
//increments the hit count and/or hit date OR sets the error message if the key has reached its hit limit for the day
if($this->update_API_hits($this->API_key, $result[0][$this->API_hit_date_column_name]) === false){
$json_obj->error = "API hit limit reached";
}
}
}else $json_obj->error = "API key is invalid or was not provided";
//if there was a search and it returned no results
if($this->search != "" &&
!$this->search_has_been_repeated &&
isset($json_obj->error) &&
strstr($json_obj->error, $this->no_results_message) == true){
$this->search_in_boolean_mode = true; //set search in boolean mode to true
$this->search_has_been_repeated = true; //note that the search will now have been repeated
//$this->JSON_string = $this->get_json_from_assoc($get_array, $object_parent_name); //recurse the function (thus re-searching)
return $this->get_json_from_assoc($get_array); //recurse the function (thus re-searching)
}
}else{ //API is private but private_key is invalid or was not provided
$json_obj->error = "this API is private and the private key was invalid or not provided";
}
}else{ //config errors were present
$pretty_print = true; //always output errors in pretty print for readability
$json_obj->config_error = $this->config_errors;
}
return ($pretty_print && version_compare(PHP_VERSION, '5.4.0') >= 0) ? json_encode($json_obj, JSON_PRETTY_PRINT) : json_encode($json_obj);
}
I'm trying to load my Drupal (6) website and I got this message:
warning: call_user_func_array()` expects parameter 1 to be a valid callback, function '_print_mail_access' not found or invalid function name in C:\wamp\www\mysite\includes\menu.inc on line 454.
The line 454 is in this function:
function ctools_menu_get_active_help() {
$output = '';
$router_path = ctools_menu_tab_root_path();
// We will always have a path unless we are on a 403 or 404.
if (!$router_path) {
return '';
}
$arg = drupal_help_arg(arg(NULL));
$empty_arg = drupal_help_arg();
foreach (module_list() as $name) {
if (module_hook($name, 'help')) {
// Lookup help for this path.
if ($help = module_invoke($name, 'help', $router_path, $arg)) {
$output .= $help ."\n";
}
// Add "more help" link on admin pages if the module provides a
// standalone help page.
if ($arg[0] == "admin" && module_exists('help') && module_invoke($name, 'help', 'admin/help#'. $arg[2], $empty_arg) && $help) {
$output .= theme("more_help_link", url('admin/help/'. $arg[2]));
}
}
}
return $output;
}
What am I doing wrong?
I've checked a condition in my script, but am having problems with the if statement. Please check my code:
function __construct($user=null)
{
parent::__construct();
require_once 'model/chanell_model.php';
$this->theme->msg='.....';
$this->db = new chanell_model();
if ($user==null && !parent::isLog()){
$this->themes=2;
}elseif ($user===null){
echo 'print';
$this->db->getChanellData();
}elseif($user!==null){
echo 'print';
}else{
$this->db->getChanellData($user);
}
}
How could be possible in same time $user == null and also $user != null.
In this code both echo commands will work .
I've also used == instead of === .
Sorry for my English. Any help would be great.
Take a long breath
if ($user===null){ echo 'bye'; }else{ echo 'hi'; }
if this piece of code will write 'bye' and 'hi' at the same time, so it's time to change your computer... :)
More seriously,
Try to debug your code and XDEBUG will be your friend for life :)
And for the immediate test, you can run your constructor as follow
function __construct($user = NULL) {
parent::__construct();
require_once 'model/chanell_model.php';
$this->theme->msg = '.....';
$this->db = new chanell_model();
$debug = TRUE;
$executionId = uniqid();
$debugMessage = '';
if ((is_null($user)) && (!parent::isLog())){
$this->themes=2;
if ($debug) {
$debugMessage .= "First condition executed, id: <" . $executionId . ">\n";
}
}
elseif ($user===null){
echo 'print';
$this->db->getChanellData();
if ($debug) {
$debugMessage .= "Second condition executed, id: <" . $executionId . ">\n";
}
}
elseif($user!==null){
echo 'print';
if ($debug) {
$debugMessage .= "Third condition executed, id: <" . $executionId . ">\n";
}
}
else{
$this->db->getChanellData($user);
if ($debug) {
$debugMessage .= "Fourth condition executed, id: <" . $executionId . ">\n";
}
}
if ($debug) {
print $debugMessage;
}
}
You will see, that the same execution id (simulated by uniid) can not run twice
Also :
use `NULL` instead of `null`
to test if value is null use `is_null()`
Fourth condition will never run!!
Do not forget to remove the debug mess once you've finished
I've found a lot of attempts at all-inclusive error handling implementations, and I figured I might write up a wiki-style to hopefully provide a complete solution that I came up with.
The question is:
"How might one catch, handle, or intercept ALL error types in PHP?"
Now - this might be deemed a 'rewrite' by some - but I don't know that there's been a comprehensive solution proposed.
There are three kinds of error handlers you need:
set_exception_handler, to catch any otherwise uncaught exceptions.
set_error_handler to catch "standard" PHP errors. I like to first check it against error_reporting to see if it's an error that should be handled or ignored (I generally ignore Notices - probably bad but that's my choice), and throw an ErrorException, letting the exception handler catch it for outputting.
register_shutdown_function combined with error_get_last. Check the value of ['type'] to see if it is E_ERROR, E_PARSE or basically any fatal error types you want to catch. These normally bypass set_error_handler, so catching them here lets you grab them. Again, I tend to just throw an ErrorException, so that all errors end up being handled by the same exception handler.
As for how you implement these, it depends entirely on how your code is set up. I usually do an ob_end_clean() to purge any output, and present a nice error page telling them that the error has been reported.
There are a number of levels of PHP errors, some of these require setting separate error handlers, and in order to catch every error PHP might throw up - you must write something that encompasses all of these 'types' of errors -- startup, 'runtime', and exceptions.
My solution to catch every ( as far as I can tell ) error that comes down the pipe:
A couple of global variables
An initialization method
4 'non-OOP' error handler methods
An ErrorHandler class with an 'AppendError' method - which is where one might make modifications to how exactly errors are output or not ( in this case, errors are just dumped to the screen in some minimal HTML from this method )
...
// Moved this line to the bottom of the 'file' for usability -
// I keep each of the above mentioned 'pieces' in separate files.
//$ErrorHandler = new ErrorHandler();
$ErrorCallback = "HandleRuntimeError";
$ExceptionCallback = "HandleException";
$FatalCallback = "HandleFatalError";
$EnableReporting = true;
$ErrorLevel = E_ALL;
function InitializeErrors()
{
if($GLOBALS["EnableReporting"])
{
error_reporting($GLOBALS["ErrorLevel"]);
if( isset($GLOBALS["ErrorCallback"]) && strlen($GLOBALS["ErrorCallback"]) > 0 )
{
set_error_handler($GLOBALS["ErrorCallback"]);
// Prevent the PHP engine from displaying runtime errors on its own
ini_set('display_errors',false);
}
else
ini_set('display_errors',true);
if( isset($GLOBALS["FatalCallback"]) && strlen($GLOBALS["FatalCallback"]) > 0 )
{
register_shutdown_function($GLOBALS["FatalCallback"]);
// Prevent the PHP engine from displaying fatal errors on its own
ini_set('display_startup_errors',false);
}
else
ini_set('display_startup_errors',true);
if( isset($GLOBALS['ExceptionCallback']) && strlen($GLOBALS['ExceptionCallback']) > 0 )
set_exception_handler($GLOBALS["ExceptionCallback"]);
}
else
{
ini_set('display_errors',0);
ini_set('display_startup_errors',0);
error_reporting(0);
}
}
function HandleRuntimeError($ErrorLevel,$ErrorMessage,$ErrorFile=null,$ErrorLine=null,$ErrorContext=null)
{
if( isset($GLOBALS['ErrorHandler']))
{
// Pass errors up to the global ErrorHandler to be later inserted into
// final output at the appropriate time.
$GLOBALS['ErrorHandler']->AppendError($ErrorLevel,"Runtime Error: " . $ErrorMessage,$ErrorFile,$ErrorLine,$ErrorContext);
return true;
}
else
{
PrintError($ErrorLevel,$ErrorMessage,$ErrorFile,$ErrorLine,$ErrorContext);
return true;
}
}
function HandleException($Exception)
{
if( isset($GLOBALS['ErrorCallback']))
{
// Parse and pass exceptions up to the standard error callback.
$GLOBALS['ErrorCallback']($Exception->getCode(), "Exception: " . $Exception->getMessage(), $Exception->getFile(), $Exception->getLine(), $Exception->getTrace());
return true;
}
else
{
PrintError($Exception->getCode(), "Exception: " . $Exception->getMessage(), $Exception->getFile(), $Exception->getLine(), $Exception->getTrace());
return true;
}
}
function HandleFatalError()
{
$Error = error_get_last();
// Unset Error Type and Message implies a proper shutdown.
if( !isset($Error['type']) && !isset($Error['message']))
exit();
else if( isset($GLOBALS['ErrorCallback']))
{
// Pass fatal errors up to the standard error callback.
$GLOBALS["ErrorCallback"]($Error['type'], "Fatal Error: " . $Error['message'],$Error['file'],$Error['line']);
return null;
}
else
{
PrintError($Error['type'], "Fatal Error: " . $Error['message'],$Error['file'],$Error['line']);
return null;
}
}
// In the event that our 'ErrorHandler' class is in fact the generator of the error,
// we need a plain-Jane method that will still deliver the message.
function PrintError($ErrorLevel,$ErrorMessage,$ErrorFile=null,$ErrorLine=null,$ErrorContext=null)
{
if( class_exists("ErrorHandler"))
$ErrorTypeString = ErrorHandler::ErrorTypeString($ErrorLevel);
else
$ErrorTypeString = "$ErrorLevel";
if( isset($ErrorContext) && !is_array($ErrorContext) && strlen($ErrorContext) > 0 )
$ErrorContext = str_replace("#", "<br/>\r\n#", $ErrorContext);
$ReturnValue = "";
$ReturnValue .= "<div class=\"$ErrorTypeString\" style=\"margin: 10px;\">\r\n";
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Error Level:</span> <span class=\"ErrorValue\">$ErrorTypeString</span></p>\r\n";
if( isset($ErrorFile) && strlen($ErrorFile) > 0 )
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">File:</span> <span class=\"ErrorValue\">'$ErrorFile'</span></p>\r\n";
if( isset($ErrorLine) && strlen($ErrorLine) > 0 )
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Line:</span> <span class=\"ErrorValue\">$ErrorLine</span></p>\r\n";
if( isset($ErrorContext) && is_array($ErrorContext))
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Context:</span><span class=\"ErrorValue\">" . var_export($ErrorContext,true) . "</span></p>\r\n";
else if( isset($ErrorContext) && strlen($ErrorContext) > 0 )
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Context:</span><span class=\"ErrorValue\">$ErrorContext</span></p>\r\n";
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Message:</span> <span class=\"ErrorValue\">" . str_replace("\r\n","<br/>\r\n",$ErrorMessage) . "</span></p>\r\n";
$ReturnValue .= "</div>\r\n";
echo($ReturnValue);
}
class ErrorHandler
{
public function AppendError($ErrorLevel,$ErrorMessage,$ErrorFile=null,$ErrorLine=null,$ErrorContext=null)
{
// Perhaps evaluate the error level and respond accordingly
//
// In the event that this actually gets used, something that might
// determine if you're in a production environment or not, or that
// determines if you're an admin or not - or something - could belong here.
// Redirects or response messages accordingly.
$ErrorTypeString = ErrorHandler::ErrorTypeString($ErrorLevel);
if( isset($ErrorContext) && !is_array($ErrorContext) && strlen($ErrorContext) > 0 )
$ErrorContext = str_replace("#", "<br/>\r\n#", $ErrorContext);
$ReturnValue = "";
$ReturnValue .= "<div class=\"$ErrorTypeString\" style=\"margin: 10px;\">\r\n";
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Error Level:</span> <span class=\"ErrorValue\">$ErrorTypeString</span></p>\r\n";
if( isset($ErrorFile) && strlen($ErrorFile) > 0 )
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">File:</span> <span class=\"ErrorValue\">'$ErrorFile'</span></p>\r\n";
if( isset($ErrorLine) && strlen($ErrorLine) > 0 )
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Line:</span> <span class=\"ErrorValue\">$ErrorLine</span></p>\r\n";
if( isset($ErrorContext) && is_array($ErrorContext))
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Context:</span><span class=\"ErrorValue\">" . var_export($ErrorContext,true) . "</span></p>\r\n";
else if( isset($ErrorContext) && strlen($ErrorContext) > 0 )
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Context:</span><span class=\"ErrorValue\">$ErrorContext</span></p>\r\n";
$ReturnValue .= "<p class=\"ErrorData\"><span class=\"ErrorKey\">Message:</span> <span class=\"ErrorValue\">" . str_replace("\r\n","<br/>\r\n",$ErrorMessage) . "</span></p>\r\n";
$ReturnValue .= "</div>\r\n";
echo($ReturnValue);
}
public static function ErrorTypeString($ErrorType)
{
$ReturnValue = "";
switch( $ErrorType )
{
default:
$ReturnValue = "E_UNSPECIFIED_ERROR";
break;
case E_ERROR: // 1 //
$ReturnValue = 'E_ERROR';
break;
case E_WARNING: // 2 //
$ReturnValue = 'E_WARNING';
break;
case E_PARSE: // 4 //
$ReturnValue = 'E_PARSE';
break;
case E_NOTICE: // 8 //
$ReturnValue = 'E_NOTICE';
break;
case E_CORE_ERROR: // 16 //
$ReturnValue = 'E_CORE_ERROR';
break;
case E_CORE_WARNING: // 32 //
$ReturnValue = 'E_CORE_WARNING';
break;
case E_COMPILE_ERROR: // 64 //
$ReturnValue = 'E_COMPILE_ERROR';
break;
case E_CORE_WARNING: // 128 //
$ReturnValue = 'E_COMPILE_WARNING';
break;
case E_USER_ERROR: // 256 //
$ReturnValue = 'E_USER_ERROR';
break;
case E_USER_WARNING: // 512 //
$ReturnValue = 'E_USER_WARNING';
break;
case E_USER_NOTICE: // 1024 //
$ReturnValue = 'E_USER_NOTICE';
break;
case E_STRICT: // 2048 //
$ReturnValue = 'E_STRICT';
break;
case E_RECOVERABLE_ERROR: // 4096 //
$ReturnValue = 'E_RECOVERABLE_ERROR';
break;
case E_DEPRECATED: // 8192 //
$ReturnValue = 'E_DEPRECATED';
break;
case E_USER_DEPRECATED: // 16384 //
$ReturnValue = 'E_USER_DEPRECATED';
break;
}
return $ReturnValue;
}
}
$ErrorHandler = new ErrorHandler();
Now - code out of the way...
To implement this, it's as simple as including this file, and executing the 'InitializeErrors' method. Beyond this, it's up to you what you want to Do with the errors; this is simply a wrapper for every error that PHP might generate - and to make changes to how any given error is handled, it's basically as simple as evaluating it in the 'AppendError' method and responding accordingly.
-- I should note - I implemented return values for reasons I cannot explain, and I should review my own work on that front - but I'm not terribly sure it has any bearing on the result.
Into file [Config.php] in [phpMyAdmin-4.6.5.2-all-languages] you can find:
/**
* Error handler to catch fatal errors when loading configuration
* file
*
*
* PMA_Config_fatalErrorHandler
* #return void
*/
public static function fatalErrorHandler()
{
if (!isset($GLOBALS['pma_config_loading'])
|| !$GLOBALS['pma_config_loading']
) {
return;
}
$error = error_get_last();
if ($error === null) {
return;
}
PMA_fatalError(
sprintf(
'Failed to load phpMyAdmin configuration (%s:%s): %s',
Error::relPath($error['file']),
$error['line'],
$error['message']
)
);
}
and just in end of file:
register_shutdown_function(array('PMA\libraries\Config', 'fatalErrorHandler'));
I have been trying to write a class to be used for displaying errors and error log.
class CError {
//Error Logging
var $Log;
public function Log($Comment, $Detail = ""){
$Log .= $Comment . "\n";
if ($Detail !== ""){
$Log .= "--" . $Detail . "--\n";
}
}
public function Clear_Log(){
$Log = "";
}
public function Display_Log(){
echo $this->Log;
}
//Error Display
var $ErrorCode = array(
0 => "0: No Error Code found, so either you got here by some rogue code or ...",
1 => "1: General Error, if you are here something went wrong",
2 => "2: Invalid information provided",
3 => "3: Alternate path taken, check message for details",
42 => "42: Here is your answer, but do you know the question?",
50 => "50: You messed with the Creepers without your Diamond Sword, didn't you",
9001 => "9001: Its over 9000... or more likely a value used was to large",
418 => "418: I'm a Teapot, found the error that drove you crazy"
);
public function Error($Error = 0, $ShowLog = false){
if ($Error === ""){
$Error = 0;
}
foreach ($ErrorCode as $key => $value){
if($key == $Error){
echo "<h3 style='color:red'>" . $value . "</h3><br />";
}
}
if($ShowLog == true){
echo $this->Log;
}
}
}
This is how I use the error class
include 'CError.php';
$Error = new CError;
$Error->Log("Email is Required");
$Error->Display_Log();
$Error->Error(2,true);
The problem is, nothing is displayed when used. It is skipped I think but not sure. I do not have access to the error logs for the server so I do not know if an error is being produced or not but the code will run through to the exit points in my main code(irrelevant to the class)
--EDIT--
The answers that tell to change $Log with $this->Log has fixed the issue with the $Log variable. It still has not fixed the issue with the error code array being displayed in the foreach loop.
--EDIT--
I solved the issue by adding $this->ErrorCode to the foreach loop.
You need to access class variable like $this->Log() in Log and Clear_Log() functions.
Try:
public function Log($Comment, $Detail = ""){
$this->Log .= $Comment . "\n";
if ($Detail !== ""){
$this->Log .= "--" . $Detail . "--\n";
}
}
public function Clear_Log(){
$this->Log = "";
}
You should modify $this->Log in methods Log and Clear_Log, like you access it in Display_Log. And you just access a local variable.
you're using the name Log for both function as well as variable. try changing the name for any one.