5. How I got started with HPHP, HHVM & Hack
• Back in 2009 I started work on a large project.
• PHP 5.3 was new at the time.
• None of the frameworks were using it yet.
2009
6. How I got started with HPHP, HHVM & Hack
• The team and I wanted to take advantage of the new features which
PHP 5.3 offered.
7. How I got started with HPHP, HHVM & Hack
• So we decided to roll our own
framework.
8. How I got started with HPHP, HHVM & Hack
• Around that time, Facebook
was showing off HPHP (Hip-
Hop PHP).
• I played around with it and it
was Fast.
• Really fast.
9. How I got started with HPHP, HHVM & Hack
• HPHP was a PHPTranspiler.
• It converted PHP to C++ and then compiled that into binary to run as
highly-optimized executable machine code.
10. How I got started with HPHP, HHVM & Hack
• We wanted our new framework
to support HPHP.
• Gaps in PHP support.
• SPL was incomplete.
• We filled them in ourselves.
11. How I got started with HPHP, HHVM & Hack
• Nutshell was born.
12. How I got started with HPHP, HHVM & Hack
• Fast Forward 4 years.
• It’s now 2013.
• Facebook has just released HHVM (Hip-HopVirtual Machine).
• Now I live and work in Malaysia.
2009 2013
13. How I got started with HPHP, HHVM & Hack
• Introducing Nuts n Bolts.
• Our CMS built on top of
Nutshell.
• There is a bit of a story behind
this…
14. How I got started with HPHP, HHVM & Hack
• Don’t drunk code in production!
15. How I got started with HPHP, HHVM & Hack
• Eventually Nuts n Bolts was a solid CMS.
• We used it for dozens of projects.
• But it was a CMS.
• It was never architected to be anything more than that.
• But we had started pushing it well beyond it’s architecture.
17. How I got started with HPHP, HHVM & Hack
• Wasn’t handling high traffic.
• Wasn’t handling big data.
18. How I got started with HPHP, HHVM & Hack
• It’s now 2015.
• We had larger projects coming up.
• So it was time for a new solution.
2009 2013 2015
19. How I got started with HPHP, HHVM & Hack
• Our goal wasn’t to build another CMS.
20. How I got started with HPHP, HHVM & Hack
• New development team.
• New goals.
• New methodologies and practices.
21. How I got started with HPHP, HHVM & Hack
• Focus on writing new code, not fixing quirks and bugs.
• Better insight into the code.
• Strongly typed.
22. How I got started with HPHP, HHVM & Hack
• Hack was written by Facebook
for Facebook.
• Runs on HHVM.
• It’s PHP, with a lot more
features.
23. How I got started with HPHP, HHVM & Hack
• In the end we chose Hack.
• It met our requirements for
what we wanted moving
forward.
• Simple stepping stone from
PHP.
24. How I got started with HPHP, HHVM & Hack
• It’s now 2016.
• Our new framework has a 1.0.0 pre release.
• Our new application platform is getting close.
2009 2013 2015 2016
25. How I got started with HPHP, HHVM & Hack
• But wait…
26. How I got started with HPHP, HHVM & Hack
• This isn’t a presentation about
building frameworks.
• This isn’t a presentation about
our new platform.
• Come back next year for that!
27. Successes
• Every team member has become a better developer.
• Our products are more solid and robust.
• We can do more with less.
• We have a great framework and an amazing platform.
28. • Can use pre-baked Images or bake scripts
Installation
Getting Started with HHVM & Hack
29. • Manual installation is simple with pre-built packages.
• Ubuntu is as simple as “sudo apt-get install hhvm”.
• Alternatively build from source.
• https://github.com/facebook/hhvm
Installation
Getting Started with HHVM & Hack
30. • Analyses source code before run time for typing errors.
• Catches issues with code before they become bugs!
TheType Checker
Getting Started with HHVM & Hack
31. • Type Checking is performed with the hh_client program which comes
with HHVM.
• It also integrates with various editors.
TheType Checker
Getting Started with HHVM & Hack
32. TheType Checker
Getting Started with HHVM & Hack
<?hh //strict
class App
{
public function exec():void
{
$this->run(['bar']);
}
public function run(array<string,mixed> $array):void
{
var_dump($array);
}
}
Top Level Code Example
33. • ReadThe Manual!
• http://docs.hhvm.com/ - Everything you need in one place.
• A great series on getting started available on EngineYard.
• https://blog.engineyard.com/2014/hhvm-hack
Learning
Getting Started with HHVM & Hack
34. • Hack looks like PHP.
• Often feels like PHP
• But it’s not PHP.
• There are quite a number of differences.
What’s the Difference?
35. • Hack opens with a different tag.
• Instead of <?php, hack opens with <?hh instead.
• Hack does not permit a closing tag. ?> will cause an error.
• Hack will not process the file as a Hack file if the first 4 characters
does not match the Hack opening tag.
• Hack files end with the .hh extension.
What’s the Difference?
OpeningTag
36. • Top level code is not permitted.
• This is often known as procedural or objectless code.
• In most situations, Hack does not permit this.
What’s the Difference?
Unsupported –Top Level Code
<?hh //strict
function foo(int $x, int $y):int
{
return $x+$y;
}
foo(1,3);
Top Level Code Example
37. • The previous example will cause the type checker to throw an error.
• The method foo() was called at the top level.
What’s the Difference?
Unsupported –Top Level Code
38. • Sometimes it’s unavoidable.
• Small changes make the type checker happy.
What’s the Difference?
Unsupported –Top Level Code
39. What’s the Difference?
Unsupported –Top Level Code
<?hh //strict
function foo(int $x, int $y):int
{
return $x+$y;
}
topLevel.hh
<?hh //strict
require_once('topLevel.hh');
class Bar
{
public function __construct()
{
foo(1,3);
}
}
index.hh
40. • The previous example works because there is no unsupported top
level code.
• The require statement is allowed.
What’s the Difference?
Unsupported –Top Level Code
require, require_once
include, include_once
namespace
use
class, trait, interface
function
41. • References are common practice in PHP.
• Hack doesn’t permit them.
• The type checker cannot do proper analysis of the code if it uses
references.
• References violate the rules that the type checker follows to properly
analyze code.
What’s the Difference?
Unsupported – References
42. • PHP’s roots are in HTML.
• Mixing HTML and PHP has always been possible.
• Hack doesn’t allow this.
• The HHVM runtime cannot recognize files like this when used as a
Hack file (.hh).
What’s the Difference?
Unsupported – HTML
44. • Hack also has something like React built in.
• It’s called XHP and it looks something like this:
What’s the Difference?
Unsupported – HTML
<?hh //strict
$name='John Doe';
print <p>Hello {$name}</p>;
XHP Example
45. • Some PHP intrinsic (or language constructs) are not supported in
Hack.
What’s the Difference?
Unsupported – Intrinsics
isset()
empty()
unset()
46. • Dynamic creation of code is not allowed.
• eval and create_function are not supported.
• Dynamic syntax like the following isn’t supported.
What’s the Difference?
Unsupported – Dynamic Code
$this->$foo;
$this->$foo();
$$foo;
Unsupported Dynamic Syntax
47. • Variable variables.
• Variable methods.
• Variable properties.
• All not supported because it’s impossible for the type checker to
guarantee what the results will be.
What’s the Difference?
Unsupported – Dynamic Code
48. • PHP4 style constructors.
• Template-style PHP syntax – if…endif and family.
• Incrementing and Decrementing a string with ++ and --.
• Word literal operators. Use “&&” instead of “and” etc.
• “break x” and family are no longer allowed.
• Hack is case sensitive. So if the class name is “Foo”, you cannot
instantiate it with “new foo()”.
• Hack is more strict when calling methods in classes. Use “$this”,
“self” and “static” appropriately.
What’s the Difference?
Unsupported – Other
49. • Start withTypes.
• Explore some other features along the way.
What’s the Difference?
New Stuff
50. • PHP has been lacking types for a long time.
• Recently introduced into PHP 7.0.
• Slightly improved in PHP 7.1.
• Will continue to improve.
What’s the Difference?
New Stuff
51. • Type Annotations are what makes Hack so great.
• They can be defined on:
• Class Properties
• Method and Function Parameters
• Method and Function returns
• Constants
• And you can type some of the new types.
What’s the Difference?
New Stuff
52. What’s the Difference?
<?php
class DB
{
public function upsert($record,$condition=[],$options=[])
{
//...
}
}
Basic PHP Example
• Consider the following example:
• An imaginary method.
• Can insert or update a record in a database.
53. What’s the Difference?
<?php
class DB
{
public function upsert(Array $record, Array $condition=[],$options=[])
{
//...
}
}
PHP 5 Example
56. What’s the Difference?
<?hh //strict
class DB
{
public function upsert
(
array<string,mixed> $record,
array<string,mixed> $condition=[],
array<string,mixed> $options=[]
):?array<string,mixed>
{
//...
}
}
Hack Example
57. What’s the Difference?
<?hh //strict
type CommonStringKeyArray=array<string,mixed>;
class DB
{
public function upsert
(
CommonStringKeyArray $record,
CommonStringKeyArray $condition=[],
CommonStringKeyArray $options=[]
):?CommonStringKeyArray
{
//...
}
}
Hack Aliases Example
58. What’s the Difference?
<?hh //strict
type CommonStringKeyArray =array<string,mixed>;
type DBRecord =CommonStringKeyArray;
type DBQuery =CommonStringKeyArray;
type DBQueryOptions =CommonStringKeyArray;
class DB
{
public function upsert
(
DBRecord $record,
DBQuery $condition=[],
DBQueryOptions $options=[]
):?DBRecord
{
//...
}
}
Hack AliasingAlias Example
59. What’s the Difference?
<?hh //strict
type CommonStringKeyArray =array<string,mixed>;
type DBRecord =CommonStringKeyArray;
type DBQuery =CommonStringKeyArray;
type DBQueryOptions =shape
(
'order' =>int,
'limit' =>int,
'offset‘ =>int
);
class DB
{
public function upsert
(
DBRecord $record,
DBQuery $condition=[],
DBQueryOptions $options=[]
):?DBRecord
{
//...
}
}
Hack Shape Example
60. What’s the Difference?
<?hh //strict
require_once('types.hh');
class DB
{
private ?DBConnection $connection;
private bool $connected=false;
private DBQuery $lastQuery;
public function upsert
(
DBRecord $record,
DBQuery $condition=[],
DBQueryOptions $options=[]
):?DBRecord
{
//...
}
}
HackTyped Properties Example
61. What’s the Difference?
<?hh //strict
require_once('types.hh');
class DB
{
private ?DBConnection $connection;
private bool $connected=false;
private DBQuery $lastQuery;
public function upsert
(
DBRecord $record,
DBQuery $condition=[],
DBQueryOptions $options=[]
):?DBRecord
{
//...
}
}
HackTyped Properties Example
63. What’s the Difference?
HackTypes
void Used for methods which don't return anything.
noreturn
Used for functions and static methods indicating that the function can
never return because it either exists or throws an exception.
mixed A catch all which includes null and void.
<object> Any predefined class.
this For methods which return $this.
num A union type of int and float.
arraykey A union type of string and int.
64. • Most types can be prefixed with “?”.
• This makes it acceptable for a method to return null in addition to the
stated type.
• This does not apply to void or noreturn.
• mixed already includes null.
HackTypes
What’s the Difference?
65. • Hack doesn’t allow the “callable” type in strict mode.
• Instead, you need to express the shape of the callable.
HackTypes
What’s the Difference?
67. • Hack supportsTuples.
• Tuples are considered as arrays.
• But they have restrictions.
HackTypes
What’s the Difference?
68. • Tuples have a fixed size and fixed types.
• Values may be changed. But must be the same type.
HackTypes
What’s the Difference?
function findFirst(array<string> $arr, string $likeRegex):(string, int)
{
//...
}
Tuple Example
69. • Enum is another type supported by hack.
HackTypes
What’s the Difference?
enum Size:int
{
SMALL =0;
MEDIUM =1;
LARGE =2;
XLARGE =3;
}
Enum Example
70. • Collections are provided to as specialized classes.
• They implement specific container patterns.
• Almost always better to use.
• Better optimization results from HHVM.
Collections
What’s the Difference?
71. • Hack provides 4 types of collections.
Collections
What’s the Difference?
Map
Vector
Set
Pair
72. • A collection of values with strings or integers as index keys.
• This collection is the most similar in functionality to when comparing
with a PHP array.
Collections – Map
What’s the Difference?
73. • A collection of values which only supports integer indexed keys.
Collections –Vector
What’s the Difference?
74. • A special collection.
• It is keyless.
• It only supports strings and integers as values.
Collections – Set
What’s the Difference?
75. • Another special collection.
• It only supports 2 values.
• It has 2 indexed keys – 0 and 1.
• It is immutable.
Collections – Pair
What’s the Difference?
76. • Each type of collection has an immutable counterpart.
• Except Pair because it is already immutable.
Collections – Immutables
What’s the Difference?
ImmMap
ImmVector
ImmSet
77. • Each type of collection has a literal syntax that can be used in place of
“new X()”.
Collections – Literal Syntax
What’s the Difference?
Map{'foo'=>1,'bar'=>2};
Vector{1,2,3}
Set{'a',1,'b',2}
Pair{0.21455657,123.25366212}
Literal Collection Syntax
78. • Attributes
• Allow you to apply metadata to things like classes and methods.
• This is reflectable.
Many Other New Features
What’s the Difference?
79. Many Other New Features
What’s the Difference?<<
command('encryptString'),
arguments
(
[
['--config','-c'],
'Path to config files.'
],
[
['--input','-i'],
'The string to encrypt.'
],
[
['--syslock','-s'],
'Enable this option to restrict the output to only work on this server.' se
]
)
>>
public function encryptString(Command $command)
{
//...
}
Attributes
80. • Pipe Operator
• The Pipe operator allows for a more concise, fluid syntax for chaining
together expressions.
Many Other New Features
What’s the Difference?
$path=implode('/',explode('',$this->getPath()));
The OldWay
$path =$this->getPath()
|>explode('',$$)
|>implode('/',$$);
The NewWay
81. • Constructor Promotion
• Trait and Interface Requirements
• Async
• Lambdas
• And many other small ones…
Many Other New Features
What’s the Difference?
82. Pitfalls
• Some tips to help you avoid common traps.
• Remember that this is not PHP.
• In many ways it looks like PHP, but its behaviour can be very different.
83. Pitfalls
• Always use the type checker.
• It’s not an accessory which you boot up sometimes.
• It’s your pre-emptive strike against the infectious bug overlords.
85. Pitfalls
• PHP allows for some very dynamic code.
• It’s very forgiving.
• HHVM does not allow this and trying to trick the type checker can
cause unforeseen behaviours in your code.
86. Pitfalls
• Sometimes HHVM forgives.
• This leads toWTF moments.
• It works! But… wait what???
• Side effects can be caused by bad code.
• Mostly happens when the type checker is used incorrectly or not at
all.
• Sometimes it’s a bug in HHVM.
87. Pitfalls
• Partial mode is NOT your friend.
• Don’t write your code against partial mode.
• There are many benefits to writing strict Hack.
88. Pitfalls
• HHVM will run PHP code with Hack code and Hack code with PHP
code.
• Great for code migration.
• Bad for achieving a 100% strict codebase.
89. Pitfalls
• Sometimes you’ll be developing against a third party library.
• It could be from composer (Yes, everything from composer will run on
HHVM!)
• In this case, you can use a HHI definition file to explain to the type
checker, all the methods and types which come from those libraries.
90. Stuck? Help is Easy!
• Sometimes you’ll get stuck.
• Try these:
• Stack Overflow
• Google
• Github
• The Facebook developers are friendly and helpful.
91. Returning to PHP
• You can try, but returning to PHP is unavoidable.
• Sometimes you’ll be working with third party PHP libraries.
• Other times, what you need isn’t available in Hack but is in PHP.
• This is OKAY.
92. Returning to PHP
• HHVM fully supports PHP and will continue to do so moving forward.
• The tools available for PHP also work with Hack.
We started running into performance issues.
We patched them.
Patches on top of patches.
Patches turned into Hacks.
Hacks turned into Performance bottlenecks.
Bottlenecks crashed servers.
There were a lot of new and interesting frameworks.
As well as new server side languages. And improvements to many old ones.
There were some great high-performance PHP solutions around.
HHVM was one of them.
But Facebook had also just released Hack.
We’re a PHP shop. Nobody here really speaks languages like Java and it really didn’t interest us.
This is a story about how we transformed our development environment.
From a chaotic, typeless mess.
Into a strict, issue free, strongly typed one.
Mention migrating to Hack.
Mention migrating to Hack.
Mention migrating to Hack.
It gives JavaScript developers an XML-like syntax to use natively in JavaScript.
Also developed by Facebook.
XHP is a huge topic.
There is not time to cover it in detail today.
But it’s really great. Please take some time to look into it yourselves.
There is A LOT of new features in Hack.
Today I cannot go through them all.
We will cover the big ones.
Okay so now we have some very basic typing. This is using PHP's object typing. But we still don't get enough infromation about the method to know what the arrays should look like or what the
If we move to PHP7, we get a little bit more control.
So now we understand what the expected return type is. So it implies that it will return a refreshed version of $record. But we're still not 100% sure. Also, if the record fails to insert, what do we still need to return the array? or should we be returning null. With this syntax, it's not possible to cover both situations.
PHP 7.1 helps with this a little bit.
So now we can see that the function could return null in case of a failure, and an array in case of a success.
This is the absolute limit of PHP. At least until late 2017 when we expect to see PHP 7.2.
So how does Hack close the gaps on the lack of information here.
And how does it help to elimiate issues that could be encountered within the method when an array of the wrong shape is given?
Let's take a look at the Hack version of this method.
So now we've added restrictions to what the array can look like. So our array keys must be strings, and we're allowing any type as the value.
This is possible because hack supports Generics.
Generics allow things to be parameterized. So that types can be represented by placeholder names. When instantiated, a type is associated with it.
So in the case above, when the array is instantiated the types "string" and "mixed" get associated with the array and the restictions are enforced.
We can make our example even cleaner with type aliasing.
So now we have a better understanding of what the array is just by reading the type.
Or we can break it down further, by aliasing our alias.
Now it's even more readable.
Often times you'll want to restrict the shape of the array. That is, what keys are allowed. You can do this with a shape.
A shape is an array. So the $options parameter would now be restricted to being an array with the specified keys and their restricted types.
You can also type class properties.
In addition to array variations.
1. So the first one to watch out for is the type checker - Always use it.
If you've left it off for a while, or you've merged in a bunch of code from team members and they've had it off. Then you run it and you get hundreds of lines of errors from the type checker. This can become quite overwhelming and you may just simply decide to ignore it and keep on going.
By doing this you're certainly not doing yourself or anyone else any favors. The problems will keep stacking and can even lead to the software not running correctly.
2. This leads me to my next point. Don't try and trick the type checker.
PHP allows you to do some very dynamic stuff with your code. It's super forgiving. Hack is not. Hack does not support any dynamic code. There are tricks you can do to get around this, and they've even been documented. But there are limits to these.
Some example of things that go wrong:
Early in the development of Nuclio, I had a situation where I needed an object before the stack which created it had finished. I devised a way to do this, however in doing so, I confused the interpreter and it ended up executing the stack twice. In hindsight this was a stupid decision to even try and do this and it was refactored to work in a different way.
With everything in Hack, you'll define types on things. In particular, arrays, maps and vectors. Somtimes when using it in a loop, if a type is not met correctly during runtime, HHVM won't throw an exception. Instead it will stop and attempt the next iteration.
This is a harder one to work through, but I'm sure they're working on a fix for such oddities.
3. It may be tempting to put every script into "partial" mode if you don't feel like working through some of the tricky scenarios to make your code 100% Hack compatible.
This is fine but eventually will take its toll on performance. HHVM will not always be able to offer the most optimal execution of those non-strict files. And when there are a lot of them the performance hit can start to build up.
At first, it may take you a little more time than usual to make your code 100% Hack compatible, but the benefits of doing so will pay off in the end. And the more you stick to pure hack code, the easier it will become. Soon you'll be fluent and all the bad practices of your PHP days will be gone.