Presented by Larry Garfield (@Crell)
We're a group of established PHP projects whose goal is to talk about commonalities between our projects and find ways we can work better together.
—PHP-FIG website
We're going to have these namespace things,
let's use them the same way for a change!
(Smoke not guaranteed)
<vendor>\Package\Whatever
new \Some\Class\Name_Here();
include_once $some_root . '/Some/Class/Name/Here.php';
new Guzzle\Http\Client();
// require('/some/root/path/Guzzle/Http/Client.php');
Thrown off lists.php.net, moved to Google Groups
Admitted a few new projects
Slept through 2010
Debated a lot in 2011
Renamed to Framework Interoperability Group
FIG
Actually became useful!
A real process!
Only took until 2013...
Projects, not people
Voted in by current voting reps
42 projects and one community busybody
Voting representatives vote
Everything else is open to all
PHP Standard Recommendation
Scope: Any definable standard or convention that improves collaboration and interoperability.
Random idea
PSR number assigned
Iterate and collaborate
Release Candidate
Profit!!1!
new \Crell\HtmlModel\Head\Link_Element();
// Results in:
include_once $some_root . '/Crell/HtmlModel/Head/Link/Element.php';
new \Crell\HtmlModel\Head\Link_Element();
// Results in:
include_once $some_root . '/Head/Link_Element.php';
The prefix is externally configured
{
"name": "crell/htmlmodel",
"autoload": {
"psr-4": {
"Crell\\HtmlModel\\": "src"
}
}
}
Always use PSR-4, not PSR-0
namespace Psr\Log;
interface LoggerInterface {
public function log($level, $message, array $context = array());
public function emergency($message, array $context = array());
public function alert($message, array $context = array());
public function critical($message, array $context = array());
public function error($message, array $context = array());
public function warning($message, array $context = array());
public function notice($message, array $context = array());
public function info($message, array $context = array());
public function debug($message, array $context = array());
}
namespace Psr\Log;
class LogLevel
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
}
Based on RFC 5424
namespace Psr\Log;
interface LoggerAwareInterface
{
public function setLogger(LoggerInterface $logger);
}
Extra metadata, including placeholders
$logger->notice("User {$username} failed to login. Hacker, maybe?");
$username = "'; DROP TABLE students; --";
$username = "<script>alert('Bobby Tables is so cute.');</script>";
Can't know output target in advance
$logger->notice("User {username} failed to login. Hacker, maybe?", [
'username' => $username,
]);
Inspired by Drupal watchdog()/t()
try {
do_something_dangerous();
}
catch (\Exception $e) {
$logger->error("Well that escalated quickly.", ['exception' => $e]);
}
Go to Beau's section next!
$_SERVER
HTTP Messages should be objects!
(Message passing, yo.)
$response = new Response();
$response = $response->withStatusCode(200);
$response = $response->withHeader('Content-Type', 'application/json');
$response = $response
->withHeader('Cache-Control', 'public')
->withAddedHeader('Cache-Control', 'max-age=300');
$body = new PsrFileStream('secret_plans.odt');
$response = $response->withBody($body);
$body = new StringStream($htmlData);
$response = $response->withBody($body);
$callback = function() use ($data) {
foreach ($data as $record) {
return implode(', ', $record);
}
};
$body = new CallbackStream($callback);
$response = $response->withBody($body);
URIs are way more complicated than you think
More portable and predictable than parse_url()
The most needlessly controversial specs ever
Runtime-important standards
ClassName::methodName
and ClassName::CONSTANT
You're probably doing this already.
Stylistic standards
That there is a standard matters more than what it is
PHP 7 updates coming in PSR-12...
(Eventually)
Similar goal as Logging
Repository model
class MyService {
protected $pool;
public function __construct(CacheItemPoolInterface $pool) {
$this->pool = $pool;
}
public function getWidgetList() {
$item = $this->pool->getItem('widget_list');
if (!$item->isHit()) {
$value = $this->computeExpensiveWidgetList();
$item
->set($value)
->expiresAt(new DateTime('now +1 hour'));
$this->pool->save($item);
}
return $item->get();
}
}
class MyService {
protected $pool;
// ...
public function warmCache() {
foreach ($this->widgets as $widget) {
$item = $this->pool->getItem('widget-' . $widget->id());
$item->set($this->computeExpensiveValue($widget));
$this->pool->saveDeferred($item);
}
$this->pool->commit();
}
public function getWidgetInfo(array $ids) {
$list = array_map(function($id) {return 'widget-' . $id; }, $ids);
return $this->pool->getMultiple($list);
}
}
interface ImportantInterface {
public function doExpensiveStuff($param);
}
class Important implements ImportantInterface {
public function doExpensiveStuff($param) {
// ...
}
}
class CacheWrapper implements ImportantInterface {
public function __construct(CacheItemPoolInterface $pool, ImportantInterface $wrapped) {
$this->pool = $pool;
$this->wrapped = $wrapped;
}
public function doExpensiveStuff($param) {
$item = $this->pool->getItem(__CLASS__ . __METHOD__);
if (!$item->isHit()) {
$item->set($this->wrapped->doExpensiveStuff($param));
$this->pool->save($item);
}
return $item->get();
}
}
Open alternative to Sensio Labs Security Advisory Checker
Am I vulnerable?
Yep Nope
namespace Psr\Container;
interface ContainerInterface
{
public function get(string $id);
public function has(string $id);
}
(So far)
For factories and other edge cases
And delegation
The goal of FIG is to encourage collaboration
Collaboration builds interoperability
... and community
(Source, Packagist.org, November 2015)
Our biggest success...
namespace Psr\Hug;
interface Huggable
{
public function hug(Huggable $h);
}
interface GroupHuggable extends Huggable
{
public function groupHug($huggables);
}
Senior Architect, Palantir.net
Let's Make Something Good Together.
Keep tabs on our work at @Palantir