
We are now going to look at how to create a C++ class to encapsulate our extension code. This is useful if you want to group similar functions or methods in one structure.
In the sample code below, we will setup a class to display a Yearly calendar as a HTML table. The helloworld extension will define a class called Cal which will have one callable method getYearly(<year>) . The year passed as argument is what will be printed. Obviously this extension is only useful when called in a web page, although it can be used in a command line php also.
WRITING CLASSES
Creating a C++ class in your extension main.cpp requires small changes to the standard C++ code .
- All classes must be derived from Php::Base
- Any class method which will be callable from PHP should use Php::Value for returning values and Php::Parameters for passing arguments.
- Any method which are used only internally within the class need not follow any special PHP considerations.
- In the *get_module() function we need to declare our class and its public methods and then use extension.add() to add the declared class.
THE CALENDAR CODE
#include <phpcpp.h> #include <iostream> #include <iomanip> #include <string> using namespace std; class Cal : public Php::Base { public: Cal(void); Php::Value getYearly(Php::Parameters ¶ms); protected: int mYear; string mMonths[13]; string mWeekDays [8]; int mDays [13]; int firstDayOfMonth(int month, int year); }; /** * Constructor - initialize data * */ Cal::Cal(void) { mMonths[0] = ""; // month starts from 1 mMonths[1] = "January"; mMonths[2] = "February"; mMonths[3] = "March"; mMonths[4] = "April"; mMonths[5] = "May"; mMonths[6] = "June"; mMonths[7] = "July"; mMonths[8] = "August"; mMonths[9] = "September"; mMonths[10] = "October"; mMonths[11] = "November"; mMonths[12] = "December"; mDays[0] =0; mDays[1] = 31; mDays[2] = 28; mDays[3] = 31; mDays[4] = 30; mDays[5] = 31; mDays[6] = 30; mDays[7] = 31; mDays[8] = 31; mDays[9] = 30; mDays[10] = 31; mDays[11] = 30; mDays[12] = 31; mWeekDays[0] = ""; mWeekDays[1] = "Sun"; mWeekDays[2] = "Mon"; mWeekDays[3] = "Tue"; mWeekDays[4] = "Wed"; mWeekDays[5] = "Thu"; mWeekDays[6] = "Fri"; mWeekDays[7] = "Sat"; } /** * Using a standard c++ algorithm to find day of week for a date * Parameters: * month - month number * year - year * Returns: * dow = day of week, sun =0, mon=1 etc. */ int Cal::firstDayOfMonth(int month, int year) { int dow = 0; int day = 1; int t[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; year -= month < 3; dow = ( year + year/4 - year/100 + year/400 + t[month-1] + day) % 7; return dow; } /** * Print yearly calendar as html <table> * Each row will have 7 td columns for the days of the week * Parameters: * year - year to print for */ Php::Value Cal::getYearly(Php::Parameters ¶ms) { int year = 0; year = (int) params[0]; string output = ""; mYear = year; if (mYear < 1900 || mYear > 2100) { std::cout << "Year is " << mYear << ". Year must be between 1900 and 2100" << endl; return output; } // check for leap year if ((mYear % 4 == 0 && mYear % 100 != 0) || (mYear % 400 == 0)) mDays[2] = 29; output.append("<table width=100%% cellpadding=2 cellspacing=2 border=1>"); for (int i =1; i <=12; i ++) { output.append("<tr valign=top>"); output.append("<td colspan=7 align=center><b>"); output.append(mMonths[i]); output.append(", "); output.append(to_string(mYear)); output.append("</td></tr>"); //print weekday labels output.append("<tr valign=top>"); for (int j = 1; j <= 7; j++) { output.append("<td><font color=red>"); output.append(mWeekDays[j]); output.append("</font></td>"); } output.append("</tr>"); // print days int daysPrinted = 0; output.append("<tr valing=top>"); for (int j = 1; j <= mDays[i]; j++) { // move display head to the correct day of week for 1st if (j == 1) { int dow = firstDayOfMonth(i, mYear); for (int spaces=0; spaces < dow; spaces++) { output.append("<td> </td>"); daysPrinted ++; } } output.append("<td>"); output.append(to_string(j)); output.append("</td>"); daysPrinted ++; if (daysPrinted % 7 == 0) { output.append("</tr>"); // start next row if more days are left if (j < mDays[i]) output.append("<tr valign=top>"); daysPrinted = 0; } } // for (int j = 1; j <= mDays[i]; j++) // close pending <tr> if (daysPrinted > 0) output.append("</tr>"); } // for (int i =1; i <=12; i ++) output.append("</table>"); return output; } /** * tell the compiler that the get_module is a pure C function */ extern "C" { /** * Function that is called by PHP right after the PHP process * has started, and that returns an address of an internal PHP * strucure with all the details and features of your extension * * @return void* a pointer to an address that is understood by PHP */ PHPCPP_EXPORT void *get_module() { // static(!) Php::Extension object that should stay in memory // for the entire duration of the process (that's why it's static) static Php::Extension extension("helloworld", "1.0"); // @todo add your own functions, classes, namespaces to the extension Php::Class<Cal> cal("Cal"); cal.method("getYearly", &Cal::getYearly, {Php::ByVal("year", Php::Type::Numeric, true)} ); extension.add(std::move(cal)); // return the extension return extension; } }
Follow the normal steps to build the extension as given in the previous posts:
- Run make
- Run sudo make install
- Run sudo ./webenable
The PHP code to test the extension is just a few lines of code:
$cal = new Cal(); $calendar = $cal->getYearly(2015); echo($calendar); The web page output is shown below:
Leave a Reply