Symfony CMFSymfony CMF 2.0.0 Stable Release (23.8.2017, 00:00 UTC)

Over the summer, we have been tagging the 2.0.0 releases of the Symfony CMF components and bundles. This week, we managed to wrap up the last bits and pieces and tagged 2.0.0 of all parts of the CMF.

CMF version 2 runs on PHP 5.6 and 7, and is compatible with Symfony 2.8 LTS and all maintained versions of Symfony 3. The sonata admin integration has been moved into its own separate bundle to not clutter up the bundles with an optional integration. We created a resource component inspired by puli. The tree browser bundle was rebuilt on top of the new resource infrastructure, and uses new Javascript libraries. Sonata PHPCR-ODM Admin has also been updated to use the new tree bundle and been released as version 2.0.0.

For a detailed list of changes, see the CMF 2 RC1 blogpost and the changelog of each component.

As already mentioned in the RC blogpost, we had to abandon some packages to focus our efforts. CreateBundle, MediaBundle, SearchBundle and SimpleCmsBundle are currently not maintained. If you want to help co-maintaining any of those packages, tell us in a GitHub issue or in #symfony_cmf of Symfony slack.

How to upgrade?

A lot of deprecated code was removed. Before upgrading, run your tests and check for deprecation warnings in the test log.

Each repository contains a UPGRADE-2.0.md file that should explain the breaking changes when migrating to version 2. The instructions can be incomplete at this point. If you have time to test the migration, please reach out to us on GitHub or Slack if you find inaccuracies or information is missing.

Next steps

We are happy with the current release, but there is of course always more that could be done. When Symfony 4 starts to take shape, we will have to make sure all components are compatible with it.

For CMF 2.1, there is a tentative roadmap in the CMF wiki. Another topic we discuss is whether to use a mono repository aproach or a tool to synchronize files into all our repositories, similar to the Sonata dev-kit.

If you want to get involved, comment on the github issues or join us at #symfony_cmf in the Symfony slack.

Link
Paul M. JonesSlim and Action-Domain-Responder (22.8.2017, 16:59 UTC)

I’ve had a warm place in my heart for Slim for a long time, and especially so since recognizing the Action-Domain-Responder pattern. In this post, I’ll show how to refactor the Slim tutorial application to ADR.

One nice thing about Slim (and most other HTTP user interface frameworks) is that they are already “action” oriented. That is, their routers do not presume a controller class with many action methods. Instead, they presume an action closure or a single-action invokable class. So the Action part of Action-Domain-Responder already exists for Slim. All that is needed is to pull extraneous bits out of the Actions, to more clearly separate their behaviors from Domain and the Responder behaviors.

I.

Let’s begin by extracting the Domain logic. In the original tutorial, the Actions use two data-source mappers directly, and embed some business logic as well. We can create a Service Layer class called TicketService and move those operations from the Actions into the Domain. Doing so gives us this class:

<?php
class TicketService
{
    protected $ticket_mapper;
    protected $component_mapper;

    public function __construct(
        TicketMapper $ticket_mapper,
        ComponentMapper $component_mapper
    ) {
        $this->ticket_mapper = $ticket_mapper;
        $this->component_mapper = $component_mapper;
    }

    public function getTickets()
    {
        return $this->ticket_mapper->getTickets();
    }

    public function getComponents()
    {
        return $this->component_mapper->getComponents();
    }

    public function getTicketById($ticket_id)
    {
        $ticket_id = (int) $ticket_id;
        return $this->ticket_mapper->getTicketById($ticket_id);
    }

    public function createTicket($data)
    {
        $component_id = (int) $data['component'];
        $component = $this->component_mapper->getComponentById($component_id);

        $ticket_data = [];
        $ticket_data['title'] = filter_var(
            $data['title'],
            FILTER_SANITIZE_STRING
        );
        $ticket_data['description'] = filter_var(
            $data['description'],
            FILTER_SANITIZE_STRING
        );
        $ticket_data['component'] = $component->getName();

        $ticket = new TicketEntity($ticket_data);
        $this->ticket_mapper->save($ticket);
        return $ticket;
    }
}
?>

We create a container object for it in index.php like so:

<?php
$container['ticket_service'] = function ($c) {
    return new TicketService(
        new TicketMapper($c['db']),
        new ComponentMapper($c['db'])
    );
};
?>

And now the Actions can use the TicketService instead of performing domain logic directly:

<?php
$app->get('/tickets', function (Request $request, Response $response) {
    $this->logger->addInfo("Ticket list");
    $tickets = $this->ticket_service->getTickets();
    $response = $this->view->render(
        $response,
        "tickets.phtml",
        ["tickets" => $tickets, "router" => $this->router]
    );
    return $response;
});

$app->get('/ticket/new', function (Request $request, Response $response) {
    $components = $this->ticket_service->getComponents();
    $response = $this->view->render(
        $response,
        "ticketadd.phtml",
        ["components" => $components]
    );
    return $response;
});

$app->post('/ticket/new', function (Request $request, Response $response) {
    $data = $request->getParsedBody();
    $this->ticket_service->createTicket($data);
    $response = $response->withRedirect("/tickets");
    return $response;
});

$app->get('/ticket/{id}', function (Request $request, Response $response, $args) {
    $ticket = $this->ticket_service->getTicketById($args['id']);
    $response = $this->view->render(
        $response,
        "ticketdetail.phtml",
        ["ticket" => $ticket]
    );
    return $response;
})->setName('ticket-detail');
?>

One benefit here is that we can now test the domain activities separately from the actions. We can begin to do something more like integration testing, even unit testing, instead of end-to-end system testing.

II.

In the case of the tutorial application, the presentation work is so straightforward as to not require a separate Responder for each action. A relaxed variation of a Responder layer is perfectly suitable in this simple case, one where each Action uses a

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

Link
SitePoint PHPAre Bitwise Operators Still Relevant in Modern PHP? (21.8.2017, 16:00 UTC)

Many of you probably scratched your heads reading this title. "Bitwhat?"

In this article, we'll look at what bitwise operators are, and whether or not their use is still relevant in this modern age of computing.

></p> <h2 id=Example Use Case

I'd been trying to really understand bitwise operators for a long time, until an example made it click for me. So that's what we'll do - dive straight into an example.

Imagine you have a website on which a given user can have specific permissions. For example, a magazine like SitePoint:

  • a author can CRUD drafts, and and edit their profile.
  • an editor can, in addition to the above, CRUD drafts and finished posts, and CRUD author profiles.
  • an administrator can, in addition to the above, add administrator permissions.

Since a user can have multiple permissions, there are several ways of defining permissions in a database and the system using it.

The Double Join

Add roles, add permissions, attach permissions to roles in a join table, then create another join table and bind some roles to some users.

This approach creates four extra tables:

  • permissions
  • roles
  • permissions<->roles
  • roles<->users

Quite a bit of overhead. Imagine having to edit these or list them in the app regularly in some frequently visited lists. Only heavy caching would save this app from collapsing under heavy load.

One advantage, though, is that by defining roles really well with intricate permissions, you only have to stick users into roles and you're good - it keeps that join table light and fast.

The Single Join

Add permissions, add a join table, attach some permissions to some users

This approach creates two extra tables:

  • permissions
  • permissions<->users

Much less overhead than the previous example, but you have many more entries in the join table because a user can have a LOT of permissions (just the CRUD for drafting is 4 permissions on its own). With a lot of users and a lot of permissions, this table can get heavy quickly.

The Column Stampede

Add a column into the users table for each permission, then make its datatype a tinyint(1) (basically a boolean) to check the permission as "on" or "off".

Setting permissions for a user would then look something like this:

UPDATE `users` SET `editProfile` = 1, `deleteProfile` = 0, `createDraft` = 1, `publishDraft` = 0 ... WHERE `id` = 5

This approach adds no extra tables, but needlessly expands the table into gargantuan width, and requires a modification of the database every time a new permission is added. It's a fine approach for when you know you'll have at most two or three permissions for the foreseeable future, but shouldn't be used for anything more than that.

However, because the list of columns, when looked at from afar, resembles a binary number (1010), this approach is an excellent segway into another...

The Bitwise Approach

Before we dive deeper into this approach, let's have a crash course in binary.

Binary Numbers

All computers store data as binary: 0 or 1. So, the number 14 is actually stored as: 1110. How so?

Binary numbers are evaluated from right to left when calculating their value, just like real numbers. So the number 1337 means:

  • 1 x 7
    • 3 x 10
    • 3 x 100
    • 1 x 1000

Because each digit in the decimal system (base 10) gets multiplied by 10. The first one is 1, the next one is 10, the next after that 100, the next 1000, etc.

Continue reading %Are Bitwise Operators Still Relevant in Modern PHP?%

Link
Zeev SuraskiZendCon 2017 (21.8.2017, 11:01 UTC)
First of all, a big Thank You to everyone who sent their interesting, inspiring or peculiar PHP stories - I can't wait to share them with the world!  And if you still have an interesting PHP-related story to share - how it helped affect your life, how it helped you change other people's lives, how it helped you meet your spouse or how you've bumped into it in an unexpected location - there's still time to share!

Now, for those of you who haven't paying attention - we're approaching the end of summer and ZendCon 2017 is right around the corner!  If you want to be there - and you do - Early Bird is ending in just 10 days.  Not to mention that if you refer someone - you get a chance to win one of those:


To be clear, we're talking about the giant elePHPant, not my daughter!  Also note that it'll be the ZendCon 2017 edition, which may not necessarily be red, but I can say will be completely awesome.

See you there!


Link
Paul M. JonesWhy MVC doesn’t fit the web (18.8.2017, 14:49 UTC)

[MVC is] a particular way to break up the responsibilities of parts of a graphical user interface application. One of the prototypical examples is a CAD application: models are the objects being drawn, in the abstract: models of mechanical parts, architectural elevations, whatever the subject of the particular application and use is. The “Views” are windows, rendering a particular view of that object. There might be several views of a three-dimensional part from different angles while the user is working. What’s left is the controller, which is a central place to collect actions the user is performing: key input, the mouse clicks, commands entered.

The responsibility goes something like “controller updates model, model signals that it’s been updated, view re-renders”.

This leaves the model relatively unencumbered by the design of whatever system it’s being displayed on, and lets the part of the software revolving around the concepts the model involves stay relatively pure in that domain. Measurements of parts in millimeters, not pixels; cylinders and cogs, rather than lines and z-buffers for display.

The View stays unidirectional: it gets the signal to update, it reads the state from the model and displays the updated view.

The controller even is pretty disciplined and takes input and makes it into definite commands and updates to the models.

Now if you’re wondering how this fits into a web server, you’re probably wondering the same thing I wondered for a long time. The pattern doesn’t fit.

Read the rest at Why MVC doesn’t fit the web.

Link
Nomad PHPRefactoring Done Right (18.8.2017, 04:01 UTC)

November 2017 - US
Presented By

Brandon Savage
November 16, 2017
20:00 CST

The post Refactoring Done Right appeared first on Nomad PHP.

Link
Nomad PHPAPI Tips From the Frontline (18.8.2017, 04:01 UTC)

November 2017 - EU
Presented By

Anna Filina
November 16, 2017
20:00 CET

The post API Tips From the Frontline appeared first on Nomad PHP.

Link
SitePoint PHPHow to Master Your API Workflow with Postman (17.8.2017, 16:00 UTC)

Building good APIs is hard, and anyone who had the chance to do so can relate to this. A project can easily grow to become a mess. One can keep trying to adopt an approach to make it more enjoyable, like trying a documentation-first workflow, but something always feels clumsy.

I was trying out Postman lately, a tool we've briefly covered before, and I discovered that they're doing a great job by providing an integrated environment for different components of an API, like authorization, testing, documentation, versioning, etc.

Postman logo

In this article, we're going to walk through the different features that Postman provides and how we can organize them to make our API workflow less painful.

Making Requests

The first step to discovering Postman is making a simple API request and seeing the response.

Simple request

From the screenshot above we can see that the view incorporates different elements. The top bar contains the request method (in this case GET), and right next to it we specify the endpoint to make the request to. If the request has some params we can specify them by clicking the Params button, which will open a table for entering them. When ready, we can click the send button to initiate the request.

The next section contains five tabs:

  • Authorization: Specifies how to authorize the request. Like Basic Auth, OAuth2, etc.
  • Headers: Any header that should be sent with the request. Like content-type, Authorization, etc.
  • Body: Request body for request types like Post, PUT, etc.
  • Pre-request Script: JS code to be executed before performing the request. (More about this later)
  • Tests: JS code to validate the response payload.

The bottom section contains all the details about the response (status, time and size). The four tabs are self explanatory, except for Tests which contains the tests result if we have any (more about this later).

Authorization

Postman supports all types of authorization, as we saw above. We're going to focus on token authorization set via header. You can read more about authorization here.

The header format that Postman will use is:

Authorization: Bearer <TOKEN>

Authorization header

Now, we'll go ahead and get a token we can use for our future requests. I'm testing on an in-development application of mine, but you can use any application you have lying around, or set one up quickly with Laravel as described here.

Not familiar with Laravel? Try our premium course - it's a comprehensive introduction, and you'll get the upcoming newer version of it automatically if you grab it in its current iteration!

Get token

At this point, we have a token to be used for querying data from the API as an authenticated user. However, copying and pasting the token for every request is tedious!

Environment Variables

This nice feature alleviates the pain of copy/paste and groups our variables in one place. An environment is an execution context: we may have a local environment, testing, staging, etc.

Postman has different scopes for variables:

  • Global
  • Environment
  • Local
  • Data

The global variables are available everywhere, separately from the selected environment. You can read more in the documentation.

We need at least three variables for now:

  • domain: current active subdomain company1, company2, etc.
  • url: our app URL.
  • token: Token for future authentication.

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

Link
PHP: Hypertext PreprocessorPHP 7.2.0 Beta 3 Released (17.8.2017, 00:00 UTC)
The PHP development team announces the immediate availability of PHP 7.2.0 Beta 3. This release is the third and final beta for 7.2.0. All users of PHP are encouraged to test this version carefully, and report any bugs and incompatibilities in the bug tracking system. THIS IS A DEVELOPMENT PREVIEW - DO NOT USE IT IN PRODUCTION! For more information on the new features and other changes, you can read the NEWS file, or the UPGRADING file for a complete list of upgrading notes. These files can also be found in the release archive. For source downloads of PHP 7.2.0 Beta 3 please visit the download page, Windows sources and binaries can be found at windows.php.net/qa/. The first Relase Candidate will be released on the 31th of August. You can also read the full list of planned releases on our wiki. Thank you for helping us make PHP better.
Link
Matthias NobackPreparing a Leanpub book for print-on-demand (16.8.2017, 14:35 UTC)

During the last few days I've been finishing my latest book, Microservices for everyone. I've used the Leanpub self-publishing platform again. I wrote about the process before and still like it very much. Every now and then Leanpub adds a useful feature to their platform too, one of which is an export functionality for downloading a print-ready PDF.

Let Leanpub generate a print-ready PDF for you

Previously I had to cut up the normal book PDF manually, so this tool saved me a lot of work. Though it's a relatively smart tool, the resulting PDF isn't completely print-ready for all circumstances (to be honest, that would be a bit too much to ask from any tool of course!). For example, I wanted to use this PDF file to publish the book using Amazon's print-on-demand self-publishing service CreateSpace, but I also wanted to order some copies at a local print shop (preferably using the same source files). In this post I'd like to share some of the details of making the print-ready PDF even more print-ready, for whomever may be interested in this.

Preparing the inside of the book

I found that several things needed to be fixed before all layout issues were gone:

  • Some lines which contained inline, pre-formatted code, like AVeryLongClassName, would not auto-wrap to the next line. Where this is the case, it triggers a warning in Createspace's automatic review process: the margin becomes too small for print. I fixed these issues by cutting these long strings in multiple parts, adding soft hyphens (\-) in between them.
  • Some images appeared to be too large. This was because Leanpub shows all images with a 100% width. Vertically oriented images will appear to be much larger than horizontally oriented ones. I added some whitespace in the images source file to force a "horizontal" rendering, but I later found out that you can also specify image positioning options, like width, float, etc.
  • Some images had a resolution that's too low for printing. When I realized, I started adding images and illustrations with higher resolutions than required. Unfortunately I had to redraw some of the illustrations manually in order to get a higher resolution version... Something to keep in mind from the beginning of the writing process!

The result of Leanpub's print-ready PDF export is a PDF containing colored code snippets and images. In order to turn it into a grayscale PDF document, I googled a bit and found a good solution. I now use Ghostscript to do the PDF conversion, using the following options:

gs  \
    -o /print/book.pdf \
    -sDEVICE=pdfwrite \
    -dHaveTransparency=false \
    -dProcessColorModel=/DeviceGray \
    -dEmbedAllFonts=true \
    -dSubsetFonts=false \
    -sColorConversionStrategy=Gray \
    -r300 \
    /preprint/book.pdf

This takes the book.pdf document from the /preprint directory, removes transparency, includes all used fonts, converts it to grayscale, and stores the images with a 300DPI resolution (which is excellent for print). It then saves the resulting PDF file in /print.

Preparing the cover

I designed the cover image using Gimp. The size and layout of the cover image are based on the number of pages, the thickness of the paper I wanted to use, the size of the PDF ("Technical", i.e. 7 x 9.1 inches) and the cut margin for the book printer. I put all this information in one spreadsheet (allowing me to use constants, variables, and simple derivations):

Guidelines for the cover image

I always miss Photoshop when I'm working with Gimp. It can do most of what I want; except store CMYK images... That's very unfortunate and frustrating. I've been trying to overcome this issue in various ways (upload an RGB image to a website to let it be co

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

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