From 68441d448e377f9a61af5c29c793922fff0d9328 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Sun, 23 Mar 2014 21:11:57 +0100 Subject: errors have a limited buffer, and discard any overflow data, replaced std::cout calls with Php::out calls in the documentation --- documentation/calling-functions-and-methods.html | 6 +- documentation/functions.html | 2 +- documentation/output-and-errors.html | 103 +++++++++++++++++++++++ documentation/variables.html | 18 ++-- 4 files changed, 116 insertions(+), 13 deletions(-) create mode 100644 documentation/output-and-errors.html (limited to 'documentation') diff --git a/documentation/calling-functions-and-methods.html b/documentation/calling-functions-and-methods.html index d3bc3e2..00f166a 100644 --- a/documentation/calling-functions-and-methods.html +++ b/documentation/calling-functions-and-methods.html @@ -36,7 +36,7 @@ void example_function(Php::Parameters &params) for (auto &key : keys) { // output key - std::cout << "key: " << key << std::endl; + Php::out << "key: " << key << std::endl; } // call a function from user space @@ -46,7 +46,7 @@ void example_function(Php::Parameters &params) Php::Object time("DateTime", "now"); // call a method on the datetime object - std::cout << time.call("format", "Y-m-d H:i:s") << std::endl; + Php::out << time.call("format", "Y-m-d H:i:s") << std::endl; // second parameter is a callback function Php::Value callback = params[1]; @@ -60,7 +60,7 @@ void example_function(Php::Parameters &params) Php::Array time_format({time, "format"}); // call the method that is stored in the array - std::cout << time_format("Y-m-d H:i:s") << std::endl; + Php::out << time_format("Y-m-d H:i:s") << std::endl; } /** diff --git a/documentation/functions.html b/documentation/functions.html index 58f2394..c8a521b 100644 --- a/documentation/functions.html +++ b/documentation/functions.html @@ -32,7 +32,7 @@ Php::Value example4(Php::Parameters &params); void myFunction() { - std::cout << "example output" << std::endl; + Php::out << "example output" << std::endl; } extern "C" { diff --git a/documentation/output-and-errors.html b/documentation/output-and-errors.html new file mode 100644 index 0000000..4697854 --- /dev/null +++ b/documentation/output-and-errors.html @@ -0,0 +1,103 @@ +

Output and errors

+

+ You can use regular C++ streams for IO. It is however not + a good idea to use the std::cout and std::cerr streams for output. +

+

+ When PHP runs as a webserver module, stdout is redirected to the + terminal from where the webserver process was originally started, + while you probably want to generate output that ends up in the generated + (HTML) output. But even when PHP runs as a CLI script - and std::cout works - + you still should not write to stdout directly, because it will bypass all + output handlers that may have been set up by the PHP user space script. +

+

+ The PHP-CPP library offers a Php::out stream that can be used instead. This + Php::out variable is an instance of the well known std::ostream class, and + utilizes all the output buffering set up in PHP. All output that you send to + it always ends up where you expect: on stdout for CLI scripts, and in the + generated code for webserver processes. It does essentially the same + as the echo() function in PHP scripts. +

+

+ Php::out is a regular std::ostring object. This also has as consequence that + it uses a buffer that needs to be sync'ed to flush the output. This flush + happens automatically when you add 'std::endl' to the output, or when you + add 'std::sync' explicitly. +

+

+


+/**
+ *  Example function that shows how to generate output
+ */
+void example()
+{
+    // the C++ equivalent of the echo() function
+    Php::out << "example output" << std::endl;
+    
+    // generate output without a newline, and ensure that it is flushed
+    Php::out << "example output" << std::flush;
+
+    // or call the flush() method
+    Php::out << "example output";
+    Php::out.flush();
+    
+    // just like all PHP functions, the Php::echo() function can also be used
+    Php::echo("Example output\n");
+}   
+
+

+

Errors, warnings and notices

+

+ When you want to trigger a PHP error (the C++ equivalent of the PHP + trigger_error()) function, you can use one of the Php::error, Php::notice, + Php::warning and Php::deprecated streams. These are also instances of the + std::ostream class. +

+

+

+


+/**
+ *  Example function that shows how to generate output
+ */
+void example()
+{
+    // generate a PHP notice
+    Php::notice << "this is a notice" << std::flush;
+    
+    // generate a PHP warning
+    Php::warning << "this is a warning" << std::flush;
+
+    // inform the user that a call to a deprecated function was made
+    Php::deprecated << "this method is deprecated" << std::flush;
+    
+    // generate a fatal error
+    Php::error << "fatal error" << std::flush;
+    
+    // this code will no longer be called
+    Php::out << "regular output" << std::endl;
+}   
+
+

+

+ In the above example you can see that we used std::flush and not std::endl. + The reason for this is that std::endl internally does two things: it + appends a newline, and it flushes the buffer. For errors, notices and + warnings we don't need the newline, but we still have to flush the + buffer to actually generate the output. +

+

+ There is something very peculiar with the Php::error stream: when you flush + it, the PHP script ends with a fatal error and your C++ algorithm + immediately exits!! Under the hood, the PHP engine does a longjump to + a place deep inside the Zend engine. In the example function the + 'Php::out << "regular output"; statement is therefore never executed. +

+

+ This all is very unusual, and (according to us) in conflict with the general + rules of decent software engineering. An output-generating function should + not behave like throwing an exception. Code that looks like normal code, + should also behave like normal code, and not do unexpected things like + leaping out of the current call stack. We therefore advise not to use + Php::error - or use it with extreme care. +

diff --git a/documentation/variables.html b/documentation/variables.html index 8c8b328..d577699 100644 --- a/documentation/variables.html +++ b/documentation/variables.html @@ -101,7 +101,7 @@ void myFunction(const Php::Value &value) void myFunction(Php::Value &value) { value += 10; - std::cout << value << std::endl; + Php::out << value << std::endl; if (value == "some string") { @@ -311,8 +311,8 @@ Php::Value array; array["x"] = 10; array["y"] = 20; -std::cout << array["x"] << std::endl; -std::cout << array["y"] << std::endl; +Php::out << array["x"] << std::endl; +Php::out << array["y"] << std::endl;

@@ -359,11 +359,11 @@ object["property2"] = "value2"; object = Php::Object("DateTime", "now"); // methods can be called with the call() method -std::cout << object.call("format", "Y-m-d H:i:s") << std::endl; +Php::out << object.call("format", "Y-m-d H:i:s") << std::endl; // all these methods can be called on a Php::Value object too Php::Value value = Php::Object("DateTime", "now"); -std::cout << value.call("format", "Y-m-d H:i:s") << std::endl; +Php::out << value.call("format", "Y-m-d H:i:s") << std::endl;

Iterating

@@ -385,7 +385,7 @@ void myFunction(const Php::Value &value) for (auto &iter : value) { // output key and value - std::cout << iter.first << ": " << iter.second << std::endl; + Php::out << iter.first << ": " << iter.second << std::endl; } } @@ -439,7 +439,7 @@ void myFunction(const Php::Value &value) Php::Value date = "date"; // "date" is a built-in PHP function and thus can it be called -std::cout << date("Y-m-d H:i:s") << std::endl; +Php::out << date("Y-m-d H:i:s") << std::endl; // create a date-time object Php::Object now = Php::Object("DateTime","now"); @@ -453,7 +453,7 @@ array[1] = "format"; // an array with two members can be called too, the first // member is seen as the object, and the second as the // name of the method -std::cout << array("Y-m-d H:i:s") << std::endl; +Php::out << array("Y-m-d H:i:s") << std::endl;

Global variables

@@ -474,7 +474,7 @@ Php::GLOBALS["b"] = Php::Array({1,2,3,4}); Php::GLOBALS["b"][4] = 5; // and global variables can also be read -std::cout << Php::GLOBALS["b"] << std::endl; +Php::out << Php::GLOBALS["b"] << std::endl;

-- cgit v1.2.3