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