Learn Continuously

As one of the best developers, you know you have to stay on top of all the new technologies. You know that you have to have a trusted training partner you can turn to when you need to learn something new.

We are your trusted training partner. We announce new training events on our mailing list often. Join us and come learn with us.

Our Students

Your needs are unique. What you need to learn depends largely on your career path and current level. We teach students at each level differently.

Senior Devs

Require a deep knowledge with very little hand-holding.

Mid-Level Devs

Deep learning with the ability to ask questions to fully understand.

New Devs

Need instructors who know how to lead them to understanding.

Our Instructors

The best instructors to teach developers are professional developers. We are professional developers.

Andrew Caya

Andrew Caya

Senior Consultant and Trainer

Andrew Caya is a Zend Certified PHP Engineer and a Zend Certified Architect. He is also the creator of Linux for PHP and LightMVC, the lead developer of a popular Joomla extension and a contributor to many open source projects.
Cal Evans

Cal Evans

Senior Consultant and Trainer

For the past 15 years Cal has worked with PHP and MySQL on Linux, OSX, and Windows. He has built a variety of projects ranging in size from simple web pages to multi-million dollar web applications.
Doug Bierer

Doug Bierer

Senior Consultant and Trainer

Doug is certified in PHP 5.1, 5.3, 5.5 and 7.1, Zend Framework 1 and 2. He has authored a bunch of books and videos for O'Reilly / Packt Publishing on PHP, Security and MongoDB.

Recent Blog Posts

PHP 7.4: The Strange Case of ArrayObject

When upgrading a website from one version of PHP to the next, there is one phrase that inevitably strikes fear into the heart of even the most intrepid PHP developer: Backwards Compatible Breaks. There … I’ve said it.  Might as well be screaming Voldemort, Voldemort, Voldemort at the top of my lungs in Hogwarts, right?  (Harry Potter fans take note!) OK … but what does this have to do with The Strange Case of ArrayObject?  To explain, let’s first have a look at ArrayObject and get_object_vars().

 

Enter get_object_vars()

Although hotly disputed by many reputable developers, personally I really like get_object_vars().  There are caveats to its use, of course.  For example, if used from the “outside,” it can only read public properties.  Otherwise, it’s extremely simple to use, and is an excellent tool for converting object properties into an associative array.

In the simple code block shown here, an ArrayObject instance is created and initialized with an array.  Running getArrayCopy()  and get_object_vars() should return the same results … right?

$obj = new ArrayObject(['A' => 1,'B' => 2,'C' => 3]);
var_dump($obj->getArrayCopy());
var_dump(get_object_vars($obj));

To test this absurdly simple example, I spun up two Linux for PHP docker containers, one running PHP 7.3, and the other running PHP 7.4.  As expected, when running this example under PHP 7.3, identical results were obtained:

php 7.3 get_object_vars()

Whistling happily to myself, I then ran the exact same code on the PHP 7.4 docker container.  I then had to rub my eyes, clean my glasses (not done often enough, at least according to my wife!), and look again.  It seems there’s something missing …  Have a look for yourselves!

php 7.4 get_object_vars()

At this point, as you may have suspected, I stopped whistling.  Uh … hmmm …  NOTE TO SELF: after upgrading to PHP 7.4, make sure you use getArrayCopy() and not get_object_vars() when working with ArrayObject!

 

It Gets Worse!

BC breaks … BC breaks … I kept mumbling to myself, they’re normal, right?  even expected, right?.  Taking a deep breath, I barreled ahead with my test.  Thinking back to the countless times I’ve used get_object_vars(), I created another simple example.  How many of you have done something like the getVars() method shown here?  (No, don’t answer that question: I don’t want to be the only one in the room to raise my hand!)

class Test extends ArrayObject
{
    public $id = 12345;
    public $name = 'Cal Evans';
    public function getVars()
    {
        return get_object_vars($this);
    }
}

Now, granted, when extending ArrayObject, even running versions of PHP earlier than 7.4, you can expect the unexpected.  Putting the above class to use, here is an example code block:

$test = new Test(['A' => 1,'B' => 2,'C' => 3]);
var_dump($test->getVars());
var_dump($test->getArrayCopy());
var_dump($test);

So, again, a class that extends ArrayObject is initialized with an array.  Now here’s where it gets even more strange.  What you would expect is that get_object_vars() would return both $id as well as $name, in addition to whatever was created upon instantiation, right?  Wrong!  Here is the output from PHP 7.3:

get_object_vars() as method

 

And the output from PHP 7.4:

get_object_vars() as method

On second glance, the output from PHP 7.4 seems to make more sense.  If we run get_object_vars() internally, we would expect it to pick up the internally defined properties.  On the other hand, getArrayCopy() returns the value of the array created upon initialization.  Thus, to get both, the getVars() method would just need to combine the two as shown in this example:

public function getVars()
{
    return array_merge(
        get_object_vars($this),
        $this->getArrayCopy()
    );
}

 

Got It … Anything Else?

Well … now that you ask … yes, there is something else, and please stop moaning and pounding your desk won’t you?  The changes internal to PHP 7.4 that resulted in the behavior demonstrated above also affects array navigation functions such as reset(), current() and next().  In case you haven’t used these functions extensively, they’re “old school” ways of navigating arrays.  reset() moves the array pointer to the “top” of the array (i.e. first element), current() returns the current value, and next() moves the array pointer to the next element.

As before, we start with a simple ArrayObject instance, initialized with an associative array:

$obj = new ArrayObject(['A','B','C']);

Here is the “traditional” way of navigating arrays, using reset(), current() and next():

reset($obj);
while ($item = current($obj)) {
    echo $item . ' ';
    next($obj);
}

And here is the same thing, using iteration methods instead:

$it = $obj->getIterator();
while ($item = $it->current()) {
    echo $item . ' ';
    $it->next();
}

As you probably expected, given that you’ve read this article up to this point, the results in PHP 7.3 are identical:

ArrayObject Iteration

And, as you might also have expected, the traditional array navigation functions don’t work against a PHP 7.4 ArrayObject instance:

ArrayObject Iteration

And that’s all she wrote!

 

Conclusion

Recognition of potential code breaks is half the battle.  As long as you are aware of potential breaks, you know what to look for potential breaks in your application post-upgrade.  As you have from the test code discussed in this post, using the internal methods will return results consist with earlier versions of PHP 7.4.  You can still use get_object_vars(), however you need to be aware that the internally generated storage array is treated differently in PHP 7.4.  This means that it may be necessary to mix the results of get_object_vars() with getArrayCopy() to arrive at the desired results.

All in all, it’s extremely important to bear in mind that a PHP 7.4 upgrade is definitely a good thing.  Performance has been improved, and there are many many enhancements that give you greater control over your code.  To name just one: PHP 7.4 introduces property level types.  These and other improvements will be addressed here in future posts.

SHAMELESS PLUG: we offer an online PHP 7.4 update course that covers, in approximately 2.5 hours, not only backwards compatibility breaks, but also infrastructural changes, language enhancements, and the ability to make direct “C” language calls, and other really cool stuff.

Thanks for reading and Happy Coding!

PHP 7.4 Direct “C” Calls

Do You “C”?

C language was developed at Bell Labs by Dennis Ritchie in late 1972. Since that time, despite the introduction of its object-oriented cousin C++, this language continues to dominate the programming language landscape. As PHP itself is written in C, the ability to directly load C shared libraries, and to gain direct access to C functions and data structures is an incredibly important addition to the PHP language.  This goal has been accomplished in PHP 7.4 with the introduction of FFI (Foreign Function interface).

 

What the “FFI”?

The idea behind FFI is neither new, nor surprising (given that PHP is written in “C”). FFI was actually first introduced as a PECL extension in January 2004 by Wez Furlong and Ilia Alshanetsky.  Wez and Ilia are both core PHP developers who have worked on dozens of extensions, most notably the PDO (PHP Data Objects) extension.  Given the success of LuaJTI/FFI and Python/CFFI in fast prototyping, however, a newly re-architected version of FFI was proposed in December of 2018 by Dmitry Stogov, and accepted into PHP 7.4.  The proof of concept was an experimental binding of PHP to the TensorFlow library (a machine learning platform), using the new version of FFI.

 

Great Expectations

Before getting into details, it’s extremely important to set expectations.  Do not use FFI if you have a need for speed!  This might seem an odd thing to say given that FFI gives us direct access to “C” language libraries and functions, however the reality is that native PHP functions, and PHP extensions are tightly integrated.  In contrast, making calls to “foreign” functions involves additional translation and overhead.  If you are still not convinced, have a look at this benchmark, taken from the RFC re-introducing FFI to PHP.  The table shows time of execution of an ary3 benchmark from bench.php. Times are stated in seconds; lower is better.  As you can see the problem is not confined to PHP: other languages with FFI implementations see a similar performance drop.

ary3 benchmark

So … Why Bother?

The next logical question is: why bother?  Why use FFI at all?  The answer is threefold.  First and foremost, if you are in the process of evaluating a custom PHP extension, using FFI allows you to do fast prototyping.  You can craft “C” language functions and libraries piece by piece, and test the functionality immediately using FFI.  Another reason is that FFI gives the PHP developer direct access to foreign C libraries and functions, opening a whole new world to the language.  Imagine, for example, that you develop for a customer who owns a custom machine shop.  If each machine is programmable (as most are these days), you can use FFI to tap into an C libraries used.  Finally, FFI includes the ability to preload C libraries in advance, somewhat alleviating the performance drop.

Preparing the C Code

Now that your expectations are set properly, let’s have a look at how this whole thing works.  As a practical example, have a look at this C function, which implements a bubble sort.  For those fortunate developers who were never assigned this as a university C language course assignment, a bubble sort iterates through an array at most “N” times, where “N” represents the number of elements in the array.  On each pass, an element index X is compared with an element index X+1.  If element[X] > element[X+1], the two elements are swapped.  Thus lower values tend to “bubble” up, and higher values bubble down.  When no swaps have been made, the iteration stops.

Here is an example of a bubble sort written in C:

#include <stdio.h>
void bubble_sort(long [], long);
void bubble_sort(long list[], long n) {
  long c, d, t;
  int p;
  for (c = 0 ; c < n - 1; c++) {
    p = 0;
    for (d = 0 ; d < n - c - 1; d++) {
      if (list[d] > list[d+1]) {
        /* Swapping */
        t         = list[d];
        list[d]   = list[d+1];
        list[d+1] = t;
        p++;
      }
    }
    if (p == 0) break;
}}

We then compile this simple function into an object file, and then produce a shared library (*.so) file:

gcc -c -Wall -Werror -fpic bubble.c
gcc -shared -o libbubble.so bubble.o

Creating the FFI Instance in PHP

We are now in a position, in our PHP 7.4 demo app, to define an FFI instance.  As you can see from the code block shown below, we use the FFI::cdef() method to identify the C function signature as the first argument, and the shared library as the second:

$ffi = FFI::cdef(
    "void bubble_sort(long [], long);",
    "./libbubble.so");

We then create simple wrapper code which populates an FFI C array with random values:

$max   = 16;
$array = FFI::new('long[' . $max . ']');
for ($i = 0; $i < $max; $i++) $array[$i] = rand(0,9999);

The code making the actual call to the C function is next:

$ffi->bubble_sort($array, $max);

And finally, assuming we add code to produce properly formatted output, here are the before and after results:

Final Words

In closing, you now have an idea where and when to use the new PHP 7.4 feature, the FFI extension.  You also have an idea how to incorporate a “native” C language function directly into your PHP code.  Happy coding1

 

Why Learning is Important

For the past decade, my career has centered around educating developers. I’ve considered it my personal mission to help raise up the next generation of developers. That’s one of the reasons I’m excited about working with Foreach Code Factory on the Continuous Learning project.

Staying current in technology is hard

To stay current, developers have to continue to learn, constantly, they have to learn continuously. Developers who do not learn will soon be left behind. I don’t think anyone has talked about this better than my friend Olivia Liddell on the episode “No BS Engineering” episode “Learning to Learn

Finding trusted training sources is hard

As I travel around and talk to developers, I rarely run into a developer who disagrees with this. They understand that since the tech we use changes fast, we have to change and adapt fast as well. Some have the time and the passion to search out, vette, and consume the tutorials, blog posts, videos, and all the great learning resources available on the web. The problem they run into is a matter of reputation and trust.

If you know the author of the content and they have a good reputation, then this part is easy. If however, you don’t know the author, then you have to decide if the content is trustworthy. While the internet is full of great learning resources for developers, we all know that there is a lot of bad advice out there as well. (Also, advice that was good 5 years ago but is now bad advice)

Stop wasting time with bad content

Foreach Code Factory:Continuous Learning will change how you spend your “learning time”. Stop wasting time chasing down current, valid, and trusted training materials, FCF:Continuous Learning has you covered. Each of our trainers already has a reputation for crafting quality training materials. We pride ourselves on our reputation and are diligent in building out new  training opportunities for developers.

We want to earn your trust. We want to be your trusted training partner. Join us for one of our free mini courses and judge for yourself. I know you’ll like what you see.