Skip to content
phalcon edited this page Aug 30, 2012 · 15 revisions

The aim of this document is to explain the functions used internally in the development of the C extension.

General Considerations

The way the code is written is not the usual, if you compare the code of Phalcon with other extensions you'll see a huge diference, this has several objectives:

  • Don't repeat yourself, if PHP has a functionality already developed, why do not simply use it?
  • Writing the code more in a PHP style, this will help to PHP developers to introspect easily understanding the internals of PHP objects. Reflection
  • Help the Phalcon user to obtain more human backtraces
  • Avoid dealing with low-level issues, whenever possible.

Phalcon API

We, the creators of Phalcon, are mainly PHP programmers, we are lazy and do not want to deal 100% of the time with low-level details and segmentation faults. Moreover we want a fast and stable framework. For this reason we have created the Phalcon API. The use of this API helps us to write C code in a PHP style. We have developed a number of functions to help the programmer to write code more interoperable with PHP in a easier way.

Phalcon API is based on the Zend API, but we have added more features to facilitate the work. Phalcon is a very large project, frameworks need to be developed and improved every day, the Phalcon API helps us write code in C more stable and familiar to PHP developers.

Common Structures

Some concepts before you begin:

Zvals Most variables used in the framework are Zvals. Each value within a PHP application is a zval. The Zvals are polymorphic structures, ie a zval can have any value (string, long, double, array, etc.). Inspecting some code you will see that most variables are declared Zvals. PHP has scalar data types (string, null, bool, long and double) and non-scalar data types (arrays and objects). There is a way to assign a value the zval according to the data type:

PHALCON_INIT_VAR(name);
ZVAL_STRING(name, "Sonny", 1);

PHALCON_INIT_VAR(number);
ZVAL_LONG(number, 12000);

PHALCON_INIT_VAR(price);
ZVAL_DOUBLE(price, 15.50);

PHALCON_INIT_VAR(nothing);
ZVAL_NULL(nothing);

PHALCON_INIT_VAR(is_alive);
ZVAL_BOOL(is_alive, false);

Zend Class Entries Another common structure we used is the zend class entry. That structure help us to describe a class, its name, method, default properties, etc.

//Get the class entry
class_entry = Z_OBJCE_P(this_ptr);

//Print the class name
fprintf(stdout, "%s", class_entry->name);

Memory Management

As you may know, the memory management in C is all manual. Within a PHP extension, we can leverage the use of the Zend Memory Manager, however management remains manual.

To help in the creation of Phalcon, we have created a memory manager that basically track every variable allocated in order to free it before exit the active method:

For example:

PHP_METHOD(Phalcon_Some_Component, sayHello){

        zval *greeting = NULL;

        PHALCON_MM_GROW();

        PHALCON_INIT_VAR(gretting);
        ZVAL_STRING(greeting, "Hello!", 1);

        PHALCON_MM_RESTORE();
}

PHALCON_MM_GROW starts a memory frame in the memory manager, then PHALCON_INIT_VAR allocates memory for the variable greeting, before exit the method we call PHALCON_MM_RESTORE, this releases all the memory allocated from the last call to PHALCON_MM_GROW.

By this way, we can be sure that all the memory allocated will be freed, avoiding memory leaks. Let's pretend that we used 10-15 variables, releasing manually the memory of them can be tedious.

Variable Creation

As noted above, all variables must be initialized before use. Even should be reset again when we change its value, for example:

//Declare the variable
zval some_number = NULL;

//Initialize the variable and assign it a string value
PHALCON_INIT_VAR(some_number);
ZVAL_STRING(some_number, "one hundred");

//Reinitialize the variable and change its value to long
PHALCON_INIT_VAR(some_number);
ZVAL_LONG(some_number, 100);

When declaring the variables is important initialize them to NULL. By doing this, PHALCON_INIT_VAR will know if the variable needs memory or it already have memory allocated.

Object Instantiation

Instantiate objects of the framework classes is easy:

PHALCON_INIT_VAR(route);
object_init_ex(route, phalcon_mvc_router_route_ce);

PHALCON_INIT_VAR(pattern);
ZVAL_STRING(pattern, "#^/([a-zA-Z0-9\\_]+)[/]{0,1}$#", 1);
PHALCON_CALL_METHOD_PARAMS_1_NORETURN(route, "__construct", pattern, PH_CHECK);

Throwing Exceptions

When you throw an exception using the Phalcon API, the current flow of execution will be stopped, returning to the last PHP code block when a Phalcon method where called.

There two ways to throw exceptions, the first, when the exception object only receives a string as parameter:

PHALCON_THROW_EXCEPTION_STR(phalcon_exception_ce, "Hey this is an exception");

Or building the exception manually and then throwing it:

PHALCON_INIT_VAR(exception_message);
PHALCON_CONCAT_SVS(exception_message, "Unable to insert into ", table, " without data");

PHALCON_INIT_VAR(exception);
object_init_ex(exception, phalcon_db_exception_ce);

//The exception constructor must be manually called
PHALCON_CALL_METHOD_PARAMS_1_NORETURN(exception, "__construct", exception_message, PH_CHECK);
phalcon_throw_exception(exception TSRMLS_CC);
return;
Clone this wiki locally