Matthias NobackIntroducing the ConvenientImmutability package (23.1.2017, 16:14 UTC)

As was the case with the SymfonyConsoleForm library, I realized I had not taken the time to properly introduce another library I created some time ago: ConvenientImmutability. This one is a lot simpler, but from a technical standpoint I think it might be interesting to at least talk a bit about the considerations that went into it.

For starters, it's important to keep in mind that I don't think you'll actually need to use this library. Of course, I'll explain why. But first: what is ConvenientImmutability about?

In early 2016 I took a Java programming course. At some point they explained the concept of a final property. As Wikipedia puts it:

A final variable can only be initialized once [...]. It does not need to be initialized at the point of declaration: this is called a "blank final" variable.

Marking a property as final is really useful. It shows that, after some initial value has been assigned to it, it is not going to change again. In smarter-sounding words: such a variable becomes immutable. As you may know, using immutable values (maybe we shouldn't call them variables anymore) leads to code that's easier to understand and has less state-related bugs. It also brings us closer to writing pure functions that never modify existing values, only return new ones. Such functions, too, are easier to work with than their imperative counterparts, which change the value of variables all over the place (possibly even global ones) whenever they feel like it.

Defining final properties in PHP

Anyway, this is not a post about the merits of a functional programming style, this is about achieving "final properties" in PHP.

Of course, in PHP we can change the value of any property:

class SomeClass
{
    public $property;
}

$object = new SomeClass();

$object->property = 'some value';

// Re-assignment is not a problem
$object->property = 'some other value';

In fact, the property doesn't even need to be defined as a class attribute, you can just set it if you like:

// This will create a property on-the-fly:
$object->undefinedProperty = '...';

The magic __set() method

We'd like to be able to inject some code, right before a re-assignment, that warns the user: "you can't reassign this property". If we don't want to rely on code generation and auto-loader hijacking, there's nothing we can do, except … implement a "magic" __set() method:

class SomeClass
{
    /**
     * @param string $name The name of the property to set
     * @param mixed $value The value to assign to that property
     */
    public function __set($name, $value) {
        // if property "$name" has been assigned already:
        //     throw an exception

        // else:
        //     store the value in some internal map
    }
}

$object->property = 'some value';

// Re-assignment throws an exception:
$object->property = 'some other value';

The main problem is: __set() will only be called when the user tries to set a property that hasn't been defined as a class attribute. But we really need to make this work for properties that have been defined as class attributes.

Unsetting class attributes

Searching for a solution, I remembered that it was indeed possible to make PHP ignore defined attributes by unset-ting object properties (don't know where I learned this by the way):

class SomeClass
{
    // We can first define the attribute:
    public $property;

    public function __construct() {
        // Then unset it:
        unset($this->property);
    }

    public function __set($name, $value) {
        // ...
    }
}

$object = new SomeClass();

// This will trigger __set()
$object->property = 'some value';

We have the key to the solution, but we need several more ingredients:

  • The value passed to __set() should be kept safe inside a map (which can be an associative array).
  • It should be possible to retrieve the value from the pseudo-property. This can be achieved by implementing __set()'s counterpart:

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

Link
PHP ClassesPHP and JavaScript Innovation Award Report January 2017 Edition - October 2016 nominees (23.1.2017, 07:37 UTC)
By Manuel Lemos
This is the January edition of the Innovation Award podcast hangout recorded by Manuel Lemos and Arturs Sosins to comment on the outstanding features of all the past month nominees and winners PHP and JavaScript packages, the prizes that the authors earned, starting with the nominees from the month of October 2016.

Listen to the podcast, or watch the hangout video to learn why the nominated packages were considered to be innovative, as well the current rankings of the Innovation Award Championship by author and by country.
Link
SitePoint PHPLaravel and Braintree: Middleware and Other Advanced Concepts (20.1.2017, 17:00 UTC)

Previously, we saw how to configure a Laravel app to handle Braintree subscriptions.

Braintree Logo

This time, we'll talk about how to:

  • Prevent users from signing up to the same plan twice
  • Add basic flash messaging to our application
  • Add the ability to swap plans
  • Create middleware to protect some routes based on the subscription status
  • Restrict users with basic subscriptions from accessing premium content
  • Cancel and resume subscriptions
  • Add Braintree notifications to the application's events via webhooks

Double Subscriptions

As it stands, if we visit the plans index page, we can still see the Choose Plan button for the plan we are currently subscribed to, and this shouldn't be the case. In the plans index view. let's add an if conditional to hide the button based on the user's subscription status:

[...]
@if (!Auth::user()->subscribedToPlan($plan->braintree_plan, 'main'))
    Choose Plan
@endif
[...]

But that's not to say users can't access the plan by typing in the URL pointing to the same plan in the address bar. To counter this, let's update the code in the show action of the PlansController to this:

[...]
public function show(Request $request, Plan $plan)
{
    if ($request->user()->subscribedToPlan($plan->braintree_plan, 'main')) {
        return redirect('home')->with('error', 'Unauthorised operation');
    }

    return view('plans.show')->with(['plan' => $plan]);
}
[...]

Here, we are getting the user from the request object; remember all our routes fall under the auth middleware and thus it's possible to get the authenticated user. Once we get the user, we check if they are already subscribed to the plan. If that's the case, we redirect them to the homepage and display a notification. We will implement basic flash messaging later.

One last precaution is preventing users from submitting the payment form with a different plan ID value. It's possible to inspect the DOM element and change the value for the hidden input. In our SubscriptionsController, let's update the store method to this:

[...]
public function store(Request $request)
{
    $plan = Plan::findOrFail($request->plan);

    if ($request->user()->subscribedToPlan($plan->braintree_plan, 'main')) {
        return redirect('home')->with('error', 'Unauthorised operation');
    }

    $request->user()->newSubscription('main', $plan->braintree_plan)->create($request->payment_method_nonce);

    // redirect to home after a successful subscription
    return redirect('home')->with('success', 'Subscribed to '.$plan->braintree_plan.' successfully');
}
[...]

Flash Messaging

Let's now implement some basic flash messaging to display notifications in the app in response certain operations. In the resources/views/layouts/app.blade.php file, let's insert this block right above our content since flash messages show up at the top before any other content:

Continue reading %Laravel and Braintree: Middleware and Other Advanced Concepts%

Link
SitePoint PHPScrum Rituals: Sprint Demo (20.1.2017, 11:47 UTC)

The following is an extract from our book, Scrum: Novice to Ninja, written by M. David Green. Copies are sold in stores worldwide, or you can buy it in ebook form here. At the end of the sprint, everything that was worked on for the current sprint is demonstrated for the team, the product owner, […]

Continue reading %Scrum Rituals: Sprint Demo%

Link
Nomad PHPDoes Your Code Measure Up? (20.1.2017, 05:01 UTC)

April 2017
Presented By

Adam Culp
April 20, 2017
20:00 CDT

The post Does Your Code Measure Up? appeared first on Nomad PHP.

Link
Nomad PHPSymfony Social Stats (19.1.2017, 19:16 UTC)

Recently my good friend Ryan Weaver of KNPLabs released a very interesting page of statistics for the Symfony framework. The page titled “Symfony Trends” shows pretty graphics of some of the non-traditional statistics. Most of the time when we look at framework stats they are things like page load time and pages per second, the …

The post Symfony Social Stats appeared first on Nomad PHP.

Link
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 5.6.30 Released (19.1.2017, 00:00 UTC)
The PHP development team announces the immediate availability of PHP 5.6.30. This is a security release. Several security bugs were fixed in this release. All PHP 5.6 users are encouraged to upgrade to this version. According to our release calendar, this PHP 5.6 version is the last planned release that contains regular bugfixes. All the consequent releases will contain only security-relevant fixes, for the term of two years. PHP 5.6 users that need further bugfixes are encouraged to upgrade to PHP 7. For source downloads of PHP 5.6.30 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 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
LinksRSS 0.92   RDF 1.
Atom Feed   100% Popoon
PHP5 powered   PEAR
ButtonsPlanet PHP   Planet PHP
Planet PHP