Chris ShiflettSponsoring New Adventures (18.12.2018, 05:42 UTC)

The intro to Good Work starts with a simple statement:

We love the web.

This sentiment is core to the vision of Faculty. It is also a common thread that ties together most of the professional endeavors throughout my career.

My love of the web has led me to do something I’ve never done before. Faculty is sponsoring a conference. Not just any conference, of course. New Adventures.

For a new company, any expense (even a small token of support) is a big decision. Here are a few of the reasons we decided it was a good idea:

  • We share a similar ethos. The company you keep reflects who you are. It’s important for us to align ourselves with those who share our values.
  • Our friends deserve our support. When I started Faculty, it felt like starting over. Although my career spans more than two decades, Faculty itself is new. I’m sure bringing New Adventures back after all these years feels a bit like starting over. I have benefitted from the support of my friends. I want them to benefit from my support, too.
  • I miss it. I attended New Adventures all three years (2011, 2012, and 2013), during the heart of the Brooklyn Beta years (2010–2014). There’s heavy overlap between our communities. I’m confident the return of New Adventures can refresh our optimism and spirit.
  • We need this. We’re no longer standing on the shoulders of giants like we once were. We need to ground ourselves in the lessons of the past to reach new heights. By sharing our experiences, we can help newcomers get a head start and push the web forward.

There are many conferences I love. (I’m looking at you, Webstock.) It’s possible we’ll sponsor more conferences in the future. For now, we’re incredibly excited to be heading to Nottingham in January.

Grab your ticket, and we’ll see you there.

Until then, happy holidays!

Link
Matthias NobackPrinciples of Package Design, 2nd edition (17.12.2018, 09:41 UTC)

All of a sudden it became book-writing season. It began in August when I started revising my second book, "Principles of Package Design". Apress had contacted me about adopting it, and they didn't want to change a lot about it. However, the book was from 2015 and although I had aimed for it to be "timeless", some parts needed an update. Furthermore, I had happily pressed the "Release" button back then, but it's the same as with software development: the code you wrote last year, you wouldn't approve of today.

Book cover

Upgrades

Because Apress has their own pipeline for manuscript to book conversion, I had to take the original Leanpub-flavored Markdown manuscript, export it to HTML, then copy it into Mac Pages, and finally export it as a Word document. That was already a lot of work. Then I started reading the book and collected all the issues, creating post-its along the way. Having every little issue on display was a nice trick. It made progress visible, and made it feel like a project I could finish.

Re-reading my own book was a very interesting experience. I noticed how often I'd been lazy and skipped a proper argument for a piece of advice. I also noticed how some advice wasn't very clear and could easily be misinterpreted.

In that regard, it was very, very helpful to have Ross Tuck on board as a technical reviewer. He pointed out several issues where the reader, given this or that background, could have difficulty understanding a section, or take unintended advice from it. Ross put in a lot of time and effort, so from this place, thanks again!

Besides revising, I've also added several new sections, most notably about the following topics:

  • The reuse of code from the Domain layer, with a discussion about Domain-Driven Design.
  • Why "final" classes should be preferred, and how composing objects should be the preferred way of changing the behavior of existing objects.
  • When to introduce an interface for a (packaged) class.

Because there are many people who have read the first edition, who I don't want to "force" to buy the second edition as well, I've already published several articles that cover more or less the same ground:

Without further ado

So, here we are. The release of the second edition of Principles of Package Design! The book is available on Apress,com and Amazon, but it's also a "regular" book, so your book store should be able to order it as well.

Buy the e-book or soft cover via Apress

Buy the e-book or soft cover via Amazon

Pile of books

Do you want to review the book?

I'm very curious about your opinion. If you've read the book (first or second edition), please let me know what you think of it. It would be great if you could submit a customer review on Amazon.

If you'd be interested in writing a review on your website, blog, etc., send me an email at info@matthiasnoback.nl, so I can send you a review copy.

Also, if you see this book in a store somewhere, it'd be very cool if you could send me a picture!

Link
Rob AllenRoute specific configuration in Slim (12.12.2018, 11:02 UTC)

A friend emailed me recently asking about route specific configuration in Slim. He wants to be able to set properties when creating the route that he can pick up when the route is matched. The way to do this is using route arguments. I've written about route arguments before in the context of setting default values for a route parameter, but you can also use them to set new data for use later.

In this post, I'm going to look at how to use them for configuration data, such as setting required ACL permissions for routes.

Setting per-route data

To recap, we set an argument on a route using setArgument() and like this:

$app->get('/widgets/{id}', HelloAction::class)
    ->setArgument('permission', 'canReadWidgets');

We have added a new argument, permission, to the route's arguments and given it a value of canReadWidgets. As the name "permission" is not in the path arguments, it cannot be overridden.

Access the per-route configuration data

We want to access the value of the permission in middleware, so let's use group middleware:

$app->group('', function ($app) {
    $app->get('/widgets/{id}', HelloAction::class)
        ->setArgument('permission', 'canReadWidgets');

    // other routes that need an ACL check here

})->setMiddleware(AclCheckMiddleware::class);

We can now use getArgument() to retrieve the permission and see if the user is allowed to continue.

$route = $request->getAttribute('route');
$permission = $route->getArgument('permission', 'canDoNothing');

That is, we retrieve the Route object from the Request and then grab the argument. The second parameter to getArgument() is the default value to return if there is no argument set on the route.

To see it in context, the bare-bones AclCheckMiddleware code might look something like this:

class AclCheckMiddleware
{
    public function __invoke($request, $response, $next)
    {
        $user = $request->getAttribute('user'); // set in an earlier middleware

                // retrieve the configured permission value
        $route = $request->getAttribute('route');
        $permission = $route->getArgument('permission', 'canDoNothing');

        if ($this->user->isAllowed($permission) === false) {
            return new Response(StatusCode::HTTP_FORBIDDEN);
        }

        return $next($request, $response);
    }
}

Note that for group or per-route middleware this works out-of-the-box. If the middleware is added using $app->add(), then you'll need to set the configuration setting determineRouteBeforeAppMiddleware to true so that the route attribute exists when the middleware is run.

That’s it

There you have it. The same mechanism used for setting a default route argument can also be used for per-route settings. This is incredibility useful for situations like ACL permissions checks and I'm confident that there are many more equally useful things that can be done.

Link
Stefan KoopmanschapGit hooks on Windows (12.12.2018, 00:00 UTC)

I recently was asked to add a git hook to our main repository to add the Jira issue number to the commit message in an automated way. We were so far handling this really inconsistently, with many commits not having the ticket number at all, while others would have them either at the start or the end of the commit message. Since our branches all contain the ticket number (naming is like `feature/APP-123-this-new-feature) this should be easy, right?

Searching around I found that Andy Carter has already published a hook written in Python to do just this. I copied the script and put it in the prepare-commit-msg file. Because I work on Windows these days I expected #!/usr/bin/env python not to work so I updated it to be #!C:\Program Files\Python\Python.exe.

I started testing my new hook, but it wouldn't work. I would constantly run into an error when committing: error: cannot spawn .git/hooks/prepare-commit-msg: No such file or directory.

After trying many different things including adding quotes to the shebang, just using python.exe (since Python was added to the PATH) and a few other things, I found out that I had simply been too excited to change the script. It turns out Windows does support #!/usr/bin/env python. So after simply changing the shebang back to it's original value the commit hook worked like a charm!

Link
Voices of the ElePHPantInterview with Brandon Savage (11.12.2018, 20:45 UTC)

Video

Show Notes

Sunshine PHP
Day Camp 4 Developers

The post Interview with Brandon Savage appeared first on Voices of the ElePHPant.

Link
Evert Pot404 Not Found (11.12.2018, 15:00 UTC)

404 Not Found hardly needs an introduction. It’s by far the most seen status by developers and non-developers alike. 404 is emitted when a resource doesn’t exist, never existed or if the server doesn’t want a client to know that a resource exist.

If the server knows the resource doesn’t and will never exist again, 410 Gone might be more appropriate.

Sometimes the 404 response is incorrectly used as a successful response to a DELETE request. The logic behind this is that the resource no longer exists after deleting, so the server should report this state.

However, this is technically wrong. Any response in the 400-499 series always means that there was a (client) error. Even successful DELETE requests should get a 200 Ok or 204 No Content response.

Example

HTTP/1.1 404 Not Found
Content-Type: text/html

<h1>404 Not found</h1>

References

Link
Remi ColletInstall PHP 7.3 on CentOS, RHEL or Fedora (10.12.2018, 13:43 UTC)

Here is a quick howto upgrade default PHP version provided on Fedora, RHEL or CentOS with latest version 7.3.

 

Repositories configuration:

On Fedora, standards repositories are enough, on Enterprise Linux (RHEL, CentOS) the Extra Packages for Enterprise Linux (EPEL) repository must be configured, and on RHEL the optional channel must be enabled.

Fedora 29

wget http://rpms.remirepo.net/fedora/remi-release-29.rpm
dnf install remi-release-29.rpm

Fedora 28

wget http://rpms.remirepo.net/fedora/remi-release-28.rpm
dnf install remi-release-28.rpm

RHEL version 8.0 Beta

wget http://rpms.remirepo.net/enterprise/remi-release-8.rpm
rpm -Uvh remi-release-8.rpm

RHEL version 7.6

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
rpm -Uvh remi-release-7.rpm epel-release-latest-7.noarch.rpm
subscription-manager repos --enable=rhel-7-server-optional-rpms

RHEL version 6.10

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
wget http://rpms.remirepo.net/enterprise/remi-release-6.rpm
rpm -Uvh remi-release-6.rpm epel-release-latest-6.noarch.rpm
rhn-channel --add --channel=rhel-$(uname -i)-server-optional-6

CentOS version 7.6

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
rpm -Uvh remi-release-7.rpm epel-release-latest-7.noarch.rpm

CentOS version 6.10

wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
wget http://rpms.remirepo.net/enterprise/remi-release-6.rpm
rpm -Uvh remi-release-6.rpm epel-release-latest-6.noarch.rpm

 

php module usage

Since Fedora 29 and RHEL-8 beta, you can simply use the remi-7.3 stream of the php module

dnf module install php:remi-7.3

 

remi-php73 repository activation

Needed packages are in the remi-safe (enabled by default) and remi-php73 repositories, the latest is not enabled by default (administrator choice according to the desired PHP version).

RHEL or CentOS

yum install yum-utils
yum-config-manager --enable remi-php73

Fedora

dnf install dnf-plugins-core
dnf config-manager --set-enabled remi-php73

 

PHP upgrade

By choice, the packages have the same name than in the distribution, so a simple update is enough:

yum update

That's all :)

$ php -v
PHP 7.3.0 (cli) (built: Dec  4 2018 16:12:20) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.0-dev, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.0, Copyright (c) 1999-2018, by Zend Technologies

 

Known issues

The upgrade can fail (by design) when some installed extensions are not yet compatible with  PHP 7.3.

See the compatibility tracking list: PECL extensions RPM status

If these extensions are not mandatory, you can remove them before the upgrade, else, you will have to be patient.

Warning: some extensions are still under development (xdebug...), but it seems useful to provide them to allow upgrade to more people, and to allow user to give feedback to the authors.

 

More d'information

If you prefer to install PHP 7.3 beside default PHP version, this can be achieved using the php73 prefixed packages, see the PHP 7.3 as Software Collection post.

You can also try the configuration wizard.

The packages available in the repository was used as source for Fedora 30 (self contained change proposal, is already accepted and testable).

By providing a full feature PHP stack, with about 130 available extensions, 5 PHP versions, as base and SCL packages, for Fedora and Enterprise Linux, and with 200 000 download per day, remi repository became in the last

Truncated by Planet PHP, read more at the original (another 1216 bytes)

Link
Evert PotFloats and money (6.12.2018, 19:24 UTC)

A very common and oft-repeated programmer’s wisdom is “Don’t use floats for currency”. This always made a lot of sense to me. The idea is that floats are imprecise, due to the way they are stored.

Effectively floats are stored not by just their digits, but by a formula. This formula can’t accurately represent every fraction. The most popular way to demonstrate this is by firing up your Javascript developer console and run:

> 0.3 - 0.2
0.09999999999999998

The answer you’ll get is not 0.1, it’s 0.09999999999999998. According to many, this is easy proof why floats are bad for money.

It’s also not really something you want to put on an invoice. Some suggestions to avoid floats include:

  • Generally when dealing with money, use specialized data stores. MySQL for example has the DECIMAL field type.
  • When serializing currency values, in for example JSON, pass them around as a string, not a number.

Another very common advice is, when doing math based on currency values just forget about the floating point and count cents instead of Euros, Yen or Dollarydoos.

So instead of $ 5.00, you would simply multiply by 100 and use 500, which fits in an integer.

This is a pretty good way to deal with simple invoicing, where for the most part you’re just adding numbers.

Fractions

With these wisdoms in hand I stepped into a problem that is a bit more complex. I needed to do calculations with fractions for financial analysis.

I’ll keep my example simple, but lets say that I needed to find out what 31% of $498.09 is.

The result of this can’t be expressed as a decimal number. On your JS console it might look something like this:

154.40789999999998

This is not just due to the fact that this is a floating point number, the other is simply that this number can’t be expressed without a fraction at all. The 9’s repeat infinitely.

But this led me to think, why do I really care about this really precise number. The part I’m really interested in is $154.41, so I can just round the result and get a string:

> (input * 0.31).toFixed(2);
'154.41'

For my purposes, this was the right answer. Money isn’t expressed as fractions (beyond cents), and it’s rounded in a lot of situations.

This led me to my next realization. The 0.3 - 0.2 example was really a strawman. I can just round it to get the number I really wanted:

> (0.3 - 0.2).toFixed(2);
'0.10'

This was the correct answer all along. The fact that we needed to first get 0.09999999999999998 as an intermediate answer is kind of irrelevant, because the difference is so little, and we would have to round anyway before display.

A better example

This last exercise just made me realize a few things:

  • 0.3 - 0.2 is not a good example of why using floating points are bad. $0.00000000000000002 is not a significant difference.
  • Unless you are comfortable writing your financial reports with formulas instead of numbers, rounding is unavoidable.
  • Everybody rounds, regardless of the number system. If you use floating point math or fixed point math, you actually suffer from the exact same problem.

So I wanted to find out if there are examples where using floating-point math does become an issue. Where are its limits?

One way I thought of thinking about this, is by trying to come up with a formula where this $0.00000000000000002 difference compound into a dollar. Just multiplying it by $10,000,000,000,000,000 doesn’t seem reasonable, because that number is (currently) too high to show up in a financial calculation.

I had trouble finding good examples to demonstrate this issue, and I’m not really smart enough to come up with an idea of my own. But even

Truncated by Planet PHP, read more at the original (another 9690 bytes)

Link
PHP: Hypertext PreprocessorPHP 7.1.25 Released (6.12.2018, 00:00 UTC)
The PHP development team announces the immediate availability of PHP 7.1.25. This is a security release.All PHP 7.1 users are encouraged to upgrade to this version.For source downloads of PHP 7.1.25 please visit our downloads page, Windows source and binaries can be found on windows.php.net/download/. The list of changes is recorded in the ChangeLog.
Link
PHP: Hypertext PreprocessorPHP 5.6.39 Released (6.12.2018, 00:00 UTC)
The PHP development team announces the immediate availability of PHP 5.6.39. This is a security release. Several security bugs have been fixed in this release. All PHP 5.6 users are encouraged to upgrade to this version. For source downloads of PHP 5.6.39 please visit our downloads page, Windows source and binaries can be found on windows.php.net/download/. The list of changes is recorded in the ChangeLog. Please note that according to the PHP version support timelines, PHP 5.6.39 is the last scheduled release of PHP 5.6 branch. There may be additional release if we discover important security issues that warrant it, otherwise this release will be the final one in the PHP 5.6 branch. If your PHP installation is based on PHP 5.6, it may be a good time to start making the plans for the upgrade to PHP 7.1, PHP 7.2 or PHP 7.3.
Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP