3. A BIT ABOUT ME
• Director of Research and Development
at Zinios.
4. A BIT ABOUT ME
• Helped grow the PHP community in
Sydney.
• Established the annual PHP
Phunconference in Sydney.
5. A BIT ABOUT HHVM & HACK
• HHVM originally started off as HPHP.
• Hip-Hop PHP.
• Was released in 2009.
6. A BIT ABOUT HHVM & HACK
• HPHP was a PHP Transpiler.
• It converted PHP to C++ and then compiled that into binary to
run as highly-optimized executable machine code.
7. A BIT ABOUT HHVM & HACK
• In 2013 Facebook released
HHVM.
• Hip-Hop Virtual Machine.
8. A BIT ABOUT HHVM & HACK
• Hack was written by Facebook
for Facebook.
• Open sourced to the public in
2015.
9. A BIT ABOUT HHVM & HACK
• Hack is PHP, with a lot more
features.
• It’s stricter.
• Type orientated.
• Runs on HHVM.
10. • Hack looks like PHP.
• Often feels like PHP
• But it’s not PHP.
What’s the Difference?
11. • Analyses source code before run time for typing errors.
• Catches issues with code before they become bugs!
The Type Checker
What’s the Difference?
12. • Type Checking is performed with the hh_client program which
comes with HHVM.
• It also integrates with various editors.
The Type Checker
What’s the Difference?
13. The Type Checker
What’s the Difference?
<?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
14. • The Type Checker gives the following error:
The Type Checker
What’s the Difference?
15. • 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?
Opening Tag
16. • 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
17. • 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
18. • Sometimes it’s unavoidable.
• Small changes make the type checker happy.
What’s the Difference?
Unsupported – Top Level Code
19. What’s the Difference?
Unsupported – Top Level Code
<?hh //partial
function foo(int $x, int $y):int
{
return $x+$y;
}
foo(1,1);
topLevel.hh
<?hh //strict
require_once('topLevel.hh');
class Bar
{
public function __construct()
{
foo(5,3);
}
}
index.hh
20. • 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
21. • 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
22. • 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
23. • But wait...! There is a way!
What’s the Difference?
Unsupported – HTML
24. • 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
25. • Some PHP intrinsic (or language constructs) are not supported
in Hack.
What’s the Difference?
Unsupported – Intrinsics
isset()
empty()
unset()
26. • 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
27. • 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
28. • 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
29. • Start with Types.
• Explore some other features along the way.
What’s the Difference?
New Stuff
30. • 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
31. • 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
32. 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.
33. WHAT’S THE DIFFERENCE?
<?php
class DB
{
public function upsert(Array $record, Array $condition=[],$options=[])
{
//...
}
}
PHP 5 Example
36. 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
37. 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
38. 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 Aliasing Alias Example
39. 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
40. 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
{
//...
}
}
Hack Typed Properties Example
42. WHAT’S THE DIFFERENCE?
Hack Types
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.
43. • 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.
Hack Types
What’s the Difference?
44. • Hack doesn’t allow the “callable” type in strict mode.
• Instead, you need to express the shape of the callable.
Hack Types
What’s the Difference?
45. Hack Types
What’s the Difference?
function send
(
Map<arraykey,mixed> $payload,
(function(Map<arraykey,mixed>):bool) $callback
):this
{
//...
}
Callable Example
46. • Hack supports Tuples.
• Tuples are considered as arrays.
• But they have restrictions.
Hack Types
What’s the Difference?
47. • Tuples have a fixed size and fixed types.
• Values may be changed. But must be the same type.
Hack Types
What’s the Difference?
function findFirst(array<string> $arr, string $likeRegex):(string, int)
{
//...
}
Tuple Example
48. • Enum is another type supported by hack.
Hack Types
What’s the Difference?
enum Size:int
{
SMALL =0;
MEDIUM =1;
LARGE =2;
XLARGE =3;
}
Enum Example
49. • 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?
50. • Hack provides 4 types of collections.
Collections
What’s the Difference?
Map
Vector
Set
Pair
51. • 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?
52. • A collection of values which only supports integer indexed
keys.
Collections – Vector
What’s the Difference?
53. • A special collection.
• It is keyless.
• It only supports strings and integers as values.
Collections – Set
What’s the Difference?
54. • 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?
55. • Each type of collection has an immutable counterpart.
• Except Pair because it is already immutable.
Collections – Immutables
What’s the Difference?
ImmMap
ImmVector
ImmSet
56. • 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
57. • Attributes
• Allow you to apply metadata to things like classes and
methods.
• This is reflectable.
Many Other New Features
What’s the Difference?
58. Many Other New Features
What’s the Difference?
<<
command('encryptString'),
arguments
(
[
['--input','-i'],
'The string to encrypt.'
]
)
>>
public function encryptString(Command $command){}
Attributes
59. • 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 Old Way
$path =$this->getPath()
|>explode('',$$)
|>implode('/',$$);
The New Way
60. • Null Safe Operator: $x?->foo()
• Constructor Promotion
• Trait and Interface Requirements
• Cooperative Multitasking with Async
• Lambdas and Lambda Operator: ==>
• And many more…
Many Other New Features
What’s the Difference?
61. 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.
62. 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.
64. 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.
65. PITFALLS
• Sometimes HHVM forgives.
• This leads to head scratching
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.
66. PITFALLS
• Partial mode is NOT your friend.
• Don’t write your code against partial mode.
• There are many benefits to writing strict Hack.
67. 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.
68. 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.
69. • Can use pre-baked Images or bake scripts
Installation
Getting Started with HHVM & Hack
70. • 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
71. • Read The Manual!
– http://docs.hhvm.com/ - Everything you need in one place.
• A great series on getting started available on Engine Yard.
– https://blog.engineyard.com/2014/hhvm-hack
Learning
Getting Started with HHVM & Hack
72. • Not many pure Hack frameworks.
• Community is still growing.
Use a Framework
Getting Started with HHVM & Hack
73. • Zinios is one company trying to help.
• We’re releasing the core of our application platform.
Use a Framework
Getting Started with HHVM & Hack
74. • Nuclio is fully open source and will be available soon.
• You can request early access from me!
• http://nuclio.co
Use a Framework
Getting Started with HHVM & 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. Sometimes 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.