Matthias NobackIntroducing the SymfonyConsoleForm package (19.1.2017, 12:10 UTC)

About 2 years ago I created a package that combines the power of two famous Symfony components: the Form component and the Console component. In short: this package allows you to interactively fill in a form by typing in the answers at the CLI. When I started working on it, this seemed like a pretty far-fetched idea. However, it made a lot of sense to me in terms of a ports & adapters architecture that I was looking for back then (and still always am, by the way). We could (and often should) write the code in our application layer in such a way that it doesn't make a big difference whether we call applications services from a web controller or from a CLI "controller".

As described by Bernhard Schüssek (author of the Symfony Form component) in his article Symfony2 Form Architecture, the Form component strictly separates model and view responsibilities. It also makes a clear distinction between processing a form and rendering it (e.g. in an HTML template). If you're familiar with Symfony forms, you already know this. You first define the structure and behavior of a form, then you convert it to a view (which is basically a DTO). This simple data structure is used to render HTML.

This strict separation of concerns has brought us a well-designed, yet fairly complicated form component. In my quest for "console forms", this was a great gift: it was actually quite easy to render form fields to the terminal output, instead of to an HTTP response.

I decided to rely on the existing Question Helper which allows console commands to ask questions to the user. This basically left me with the need for "bridging the gap" between the Form and Console component. This is a quick list of things I needed to fix:

  • Different form fields require different console question types. A choice type form field matches more or less with a ChoiceQuestion. But since the mapping isn't one-to-one, I introduced the concept of a FormToQuestionResolver which configures a Question object in such a way that the user experience matches to that of a web form field. For example: a password type form field gets transformed into a Question with hidden output.
  • It's relatively easy to ask single questions (e.g. "Your name: "), but it was a bit harder to ask for "collections", like "Phone number 1: ", "Phone number 2: ", etc.). I fixed this by introducing something called a FormInteractor which gets asked to arrange any number of user interactions that are required to fill in the form.
  • CSRF tokens aren't needed for console commands, so CSRF protection will automatically be disabled.
  • In some places this package relies on behaviors of the Form and Console component that are not covered by the Symfony Backwards Compatibility Promise. This means that for every minor release the package is bound to break for some (often obscure) reason. I have kept up with Symfony 2.8, 3.0, 3.1 and 3.2, but if things get too hard to maintain, I will consider dropping some versions.

A short list of changes in external libraries that have been causing trouble so far (I'm by no means criticizing the Symfony development team for this, it just might be interesting to share this with you):

  • The behavior of a ChoiceQuestion changed at some point, switching what was returned as the selected value (instead of the selected "key" at some point it started returning the selected "label" of a choice). See also my custom solution, AlwaysReturnKeyOfChoiceQuestion. Furthermore, around the same time the Form component switched the behavior of its ChoiceType form type, accepting an array of "label" => "data" value pairs, where I was used to providing the exact opposite (an array of "data" => "label" pairs).
  • Of course, there was the major overhaul of the form type system, where form types changed to being fully-qualified class names instead of simple names. I wanted to keep supporting both styles, so this took some time to get right. At some point, t

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

Link
Nomad PHPFramework Porn (19.1.2017, 11:00 UTC)

(No, not really porn. Totally SFW)  Today Taylor Ottwell, creator of the Laravel framework, posted the Framework Code Complexity Comparison. For those not familiar with “Cyclomatic Complexity” here’s the Wikipedia page Cyclomatic Complexity. Briefly, “Cyclomatic Complexity is a software metric (measurement), used to indicate the complexity of a program.” While Taylor’s post gives you the …

The post Framework Porn appeared first on Nomad PHP.

Link
PHP: Hypertext PreprocessorPHP 7.1.1 Released (19.1.2017, 00:00 UTC)
The PHP development team announces the immediate availability of PHP 7.1.1. Several bugs have been fixed. All PHP 7.1 users are encouraged to upgrade to this version. For source downloads of PHP 7.1.1 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
Rob AllenHomestead per-project crib sheet (18.1.2017, 12:33 UTC)

I wanted a drop-dead simple way to try and replicate a problem someone was having on the Slim forums. I couldn't reproduce with php -S which is my go-to for this sort of thing, so I thought I'd try Homestead.

I had recently listend to a Voices of the Elephpant episode with Taylor Otwell & Joe Ferguson where Joe mentioned that Homestead worked on a per-project basis too. I didn't know this, so tried it out. The docs are fine, but there's a lot there that covers the global installation option when I just want to get up and running on a per-project basis.This is my crib sheet:

1. Create project

$ composer create-project slim/slim-skeleton skelly
$ cd skelly

We just need a project that uses Composer. You probably have one already. If not, Slim Framework is a good choice!

2. Add Homestead to the project

$ composer require laravel/homestead --dev
$ php vendor/bin/homestead make

The make command creates VagrantFile and a Homestead.yaml for configuration.

3. Deal with IP address and hostname

By default, the Homestead vagrant box is set up on 192.168.10.10 with the hostname homestead.app. You can change this in Homestead.yaml.

Add the IP address to /etc/hosts. This only needs to be done once if you don't change the defaults.

$ echo "192.168.10.10 homestead.app" | sudo tee -a /etc/hosts

All done

We're all done, so we can use vagrant up to run our new website Go to homestead.app in a browser to see it. To shut down, use vagrant halt or vagrant destroy.

Slim home page

Link
Voices of the ElePHPantInterview with Shawn Mayzes (18.1.2017, 10:00 UTC) Link
PHP ClassesSimple Tutorial on using MySQL with PDO that works with PHP 7 (18.1.2017, 09:11 UTC)
By mohammad anzawi
Most PHP applications use MySQL databases but since PHP 7 was introduced the old MySQL extension was discontinued. Developers need to migrate either to using MySQLi or PDO.

Using PDO makes your code usable also with other types of databases besides MySQL.

Read this tutorial to learn how to perform simple common database queries as well perform table schema management operations using the PHP PDO database class.
Link
Christian WeiskeCrate: Eventual consistency (18.1.2017, 06:28 UTC)

Some projects at work use a Crate database as kind of caching layer for aggregated, unnormalized data that helps reducing requests from frontend servers. Because of its eventual consistency model, filling data into it has some issues.

Eventual consistency means that at some point in the future - not now - data will be consistent. You write into Crate, but it is not guranteed that the next read will contain the data written earlier, as described in its documentation.

The following PHP code uses Laravel's Eloquent with the Crate adapter, and is pretty standard in the sloppy and inefficient world of nice-to-look-at ORMs:

$obj = Model::firstOrCreate(['id' => $id]);
$obj->fill($transformer->transform($data));
$obj->save();

That code handles both fresh inserts and updates in only three lines, which is nice. But it makes three SQL queries for new data:

  1. SELECT for checking if the row exists
  2. INSERT to create the row (saving the ID only)
  3. UPDATE to actually write the new data

With Crate, the UPDATE will fail because the row inserted in step 2 is not available in step 3.

Eloquent's firstOrCreate method fortunately supports a second parameter that may contain additional data to be inserted:

$newdata = $transformer->transform($data);
$obj = Model::firstOrCreate(['id' => $id], $newdata);
$obj->fill($newdata);
$obj->save();

This code works with Crate, even if it is terrible inefficient - when inserting a new row, it sends the same data again in the UPDATE.

Eventual consistency will also bite you when using TRUNCATE and then immediately inserting data. Create has a REFRESH TABLE command that ought to support you with such cases, but in Crate 1.0.1 we had issues with that, and had to resort to a sleep(1) call in our import script :/

Link
Anna FilinaConFoo Montreal Early Bird + Vancouver Dates (17.1.2017, 21:20 UTC)

confoo-yvr2016-yul2017

You can save on ConFoo Montreal tickets until January 20, 2017. This huge conference will be held on March 8-10, 2017 and will feature over 150 presentations.

There is a great range of topics, including PHP, many other programming languages, databases, security, performance, machine learning and project management.

We also just confirmed the dates for the next ConFoo Vancouver, which is scheduled for December 4-6, 2017.

Link
Paul M. JonesHow Many PSR-7 Implementations Exist? (17.1.2017, 18:23 UTC)

More specifically, how many implementations of PSR-7 ServerRequestInterface exist?

Initially, it appears the answer might be as many as three dozen.

But increasingly it looks like the real answer, to a first approximation, is “zero.”

To implement ServerRequestInterface, the methods withAttribute() and withParsedBody() MUST maintain the immutability of the message object. However, none of the existing implementations do that.

To see for yourself, clone my PSR-7 Immutability Testing repository and run the tests, which cover the three most popular PSR-7 implementations.

Immutability is very difficult to implement – at least, not without some serious restrictions, none of which are specified by PSR-7 ServerRequestInterface.The more I work with it, the more I begin to think that it is not fully implementable-as-specified in the first place.

UPDATE: Apparently I was on to something when I suggested that PSR-7 cannot be implemented as written. Sara Golemon (who has forgotten more about PHP internals than I will ever know) points out, “It is not technically implementable. And thus you’re technically correct, the best kind of correct.” (Archived for posterity at https://archive.is/BnkGb .)

Link
SitePoint PHPLaravel and Braintree, Sitting in a Tree… (17.1.2017, 17:00 UTC)

Subscriptions to services online are something extremely common - from subscribing to music streaming services to tutorial sites to access premium content.

With Laravel 5, we saw the introduction of Laravel Cashier, an official Laravel package to help developers manage Stripe's and Braintree's subscription billing services without writing most of the boilerplate subscription billing code.

Stripe and Braintree are payment platforms that make it easy to accept payments in your app or website.

In this tutorial, we will be building a dummy Courses site with Braintree subscriptions. In the process, we will learn how to use the various methods offered by Cashier.

Braintree Logo

In the first part of this extensive two-part series, we are going to:

  • Set up Laravel Cashier
  • Sign up to the Braintree sandbox (For production apps we use the main Braintree service)
  • Create plans on Braintree
  • Create an artisan command to sync the online plans with our database
  • Allow users to subscribe to a plan

In part two, we will:

  • Add the ability to swap plans
  • Create middleware to protect some routes based on the subscription status
  • Protect premium courses from users with basic subscription
  • Learn how to cancel and resume subscriptions
  • Add Braintree notifications to a variety of the application's events via webhooks

The complete code for part one can be found here.

Creating the Application

We will start with a fresh Laravel installation.

composer create-project laravel/laravel lara-billable

Preparing the Database

Next, we have to set up the database before running any migrations. Let's use MySQL - it's easy to use, easy to configure, and included in a well-built development environment like Homestead Improved. After setting up the database, I have my .env file looking like this:

DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

Scaffolding Auth

The next step is adding authentication to our application.

Continue reading %Laravel and Braintree, Sitting in a Tree…%

Link
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP