vue.js: Using vue with a Symfony Form

One of our new projects here at Setfive is a service that will allow people to create a subscription that will condense AWS product updates into a single email notification with the user’s chosen frequency. An important aspect to a product like this is a captivating sign up — we wanted to include a clean and dynamic sign up section on the website that would help to entice people to sign up and use the product.

This sign up form involves two side by side lists of ‘sources’ you would like updates about (i.e. Amazon EC2, Amazon Lambda, Amazon SNS), a textbox for your email, and a button to submit. The left side Sources are your options, which you can be adjusted via search or selecting different categories. The right side shows your selected sources — clicking a source will select it and move it to the right side, and vice versa to deselect one of your choices:

The majority of the project is handled by Symfony — Symfony is perfect for creating rather generic data entry forms made up of different input types such as textboxes, radio buttons, and select boxes. However, we wanted our sign up section to be far more dynamic than what would be easily built through Symfony’s FormBuilder.

Enter Vue.js: a JavaScript framework that can be easily integrated within a traditional web app. If you keep up to date with our Setfive blog posts, you may have seen my last blog about getting started with Vue.js. One of the key benefits of Vue.js is the ability to reuse/combine Vue components with each other and with Symfony’s forms — this allows us to reap the benefits of a dynamic/reactive Vue component as well as the automatic data validation and creation of Symfony.

The Goal:

We at Setfive love Symfony and to stay consistent, we try to use Symfony wherever possible. We wanted to reuse the ‘source select’ portion of the sign up section to allow existing users to edit their subscriptions and create new ones. However, for a registered user the create and edit subscription forms don’t require an email field and we’d instead want to immediately present ‘name’ and ‘frequency’ fields. his being the case, we knew combining our ‘source select’ Vue component with a Symfony form would be our best option — Symfony forms allow for much simpler data validation and can be displayed simply using Twig helpers.

With a combination of Symfony and Vue, we were able to build a dynamic source selecting component with Vue and allow Symfony to validate the selected sources, the name, and the frequency automatically without any extra work.

The Solution:

The first thing we needed to do was split our existing ‘source select’ component up so that the double list selector is independent from the other fields on the sign up form. Fortunately, it is simple to create parent and child Vue components and pass data from child to parent. This is done through Event Emitting: when a source is selected in the child component (source select), that ‘event’ and its data is emitted to the parent component (form composed of source select + email field and submit button).

It is a bit more complicated to synchronize this data with a Symfony form. To solve this problem, a few steps were needed.

First, we had to see what a form would look like if we did this without Vue — in other words, if we created a form and allowed you to use checkboxes to select your sources, what would the HTML elements of the individual sources look like when selected/not selected?

<input type="checkbox" id="subscription_edit_sources_5" name="subscription_edit[sources][]" class="form-check-input" value="5" checked="checked">

Our Symfony Form type ended up looking like:

Next, our Subscription form needs to include that form element (sources), but not actually render it on screen. Via Twig:

{% do form.sources.setRendered %}

This way, ‘sources’ is a form element whose data will be submitted, but not displayed via Twig.

Finally, we need to handle the logic of sources being selected and deselected. By tracking the ID of each source, we can create hidden HTML elements containing the exact same data that would be present if we were rendering the form entirely with Symfony and Twig.

When a source is selected, our parent component receives that data and we create the corresponding element, without displaying it (class=”d-none”):

$("#subscription-form")
.append($('<input id="source_'+source.id+'" type=text class="d-none"/>')
.attr('name', 'subscription_edit[sources][]')
.val(source.id)
.prop('checked', true));

When a source is deselected, we simply delete that element:

$("#source_"+source.id).remove();

Once a user hits submit, the form data containing those hidden input elements is compiled and the ‘sources’ form element mentioned above will now contain a list of the source IDs. Behind the scenes, Symfony converts those IDs to their corresponding Source object and Voila! Your subscription now contains the sources you chose!

Have any questions or feedback? Let me know in the comments!

Quora: Why use PHP?

I’ll be the first to criticize PHP from a language design perspective. But, PHP does possess compelling aspects that have contributed to its popularity today.

  • “Hit refresh workflow” – When using PHP, you can make a change to a source file, and hit refresh, and your changes are immediately available. This function prevents compiling and transpiling, fiddling around with “hot reloads,” and bouncing servers. Having a tight feedback loop is hugely productive when you’re building a CRUD app. Interestingly, Play Framework is now touting this as a feature, Build Modern & Scalable Web Apps with Java and Scala
  • Isolated HTTP request handling – If you’re deploying PHP via mod_php or php-fpm, every HTTP request is handled effectively through a separate PHP process. In practice, this means your code can’t store any state between requests, or accidentally retain information from a previous request. Typically, this makes PHP apps easier to scale at the app level since the stateless nature enables horizontal scaling without any app changes.
  • Composer with Packagist – Composer and Packagist work pretty well together for dependency management. Composer is easier to work with than Maven, arguably more “sane” than npm, and usually does a good job at staying out of the way. Packagist has a critical mass of useful, popular packages and works well with Composer.
Posted in PHP

Symfony: Symfony Live 2019

Last week, a Symfony Live event was held in Paris. For those of you that are not familiar with Symfony, Symfony is a PHP framework which provides the tools to build an application. Symfony powers numerous popular applications such as the Drupal CMS, the leading open-source CMS, and serves billions of impressions per month.

What differentiates Symfony from other software creation templates is that Symfony is a community. The Symfony community emerged as an open source project where web application was developed to fit user’s needs. This community has since evolved as international conferences are being held to discuss the latest web application developments. The most recent Symfony conference, know as “Symfony Live,” was held in Paris. This conference included talks and workshops, as well as announcements on the latest Symfony updates and tools.

Some of the major updates announced at the conference were the new mailer and HTTPClient. We are excited about both of these components, as they will bring welcomed benefits in terms of not only developer experience (DX) but also efficiency.

Other talks and updates given at the conference included:

*most slides are written in French*

An Edge Case of Time in AWS PHP SDK

When Amazon Web Services rolled out their version 4 signature we started seeing sporadic errors on a few projects when we created pre-authenticated link to S3 resources with a relative timestamp. Trying to track down the errors wasn’t easy. It seemed that it would occur rarely while executing the same exact code. Our code was simply to get a pre-authenticated URL that would expire in 7 days, the max duration V4 signatures are allowed to be valid. The error we’d get was “The expiration date of a signature version 4 presigned URL must be less than one week”. Weird, we kept passing in “7 days” as the expiration time. After the error occurred a couple of times over a few weeks I decided to look into it.

The code throwing the error was located right in the SignatureV4 class. The error is thrown when the end timestamp minus the start timestamp for the signature was greater than a week. Looking through the way the timestamps were generated it went something like this:

  1. Generate the start timestamp as current time for the signature assuming one is not passed.
  2. Do a few other quick things not related to this problem.
  3. Do a check to insure that the end minus start timestamp is less than a week in seconds.

So a rough example with straight PHP could of the above steps for a ‘7 days’ expiration would be as follows:

Straight forward enough, right? the problem lies when a second “rolls” between generating the `$start` and the end timestamp check. For example, if you generate the `$start` at `2017-08-20 12:01:01.999999`. Let’s say this gets assigned the timestamp of `2017-08-20 12:01:01`. Then the check for the 7 weeks occurs at `2017-08-27 12:01:02.0000` it’ll throw an exception as duration between the start and end it’s actually now for 86,401 seconds total. It turns outs triggering this error is easier than you’d think. Run this script locally:

That will throw an exception within a few seconds of running most likely.

After I figured out the error, the next step was to submit a issue to make sure I’m not misunderstanding how the library should be used. The simplest fix for me was to generate the end expiration timestamp before generating the start timestamp. After I made the PR, Kevin S. from AWS pointed out that while this fixed the problem, the duration still wasn’t guaranteed to always be the same for the same relative time period. For example, if you created 1000 presigned URLs all with ‘+7 days’ as the valid period, some may be 86400 in duration others may be 86399. This isn’t a huge problem, but Kevin made a great point that we could solve the problem by locking the relative timestamp for the end based on the start timestamp. After adding that to the PR it was accepted. As of release 3.32.4 the fix is now included in the SDK.

Doctrine2 QueryBuilder Executable SQL Without Running The Query

On one of our projects that I am working on I had the following problem: I needed to create an aggregate temporary table in the database from a few different queries while still using Doctrine2. I needed to aggregate the results in the database rather than memory as the result set could be very large causing the PHP process to run out of memory. The reason I wanted to still use Doctrine to get the base queries was the application passes around a QueryBuilder object to add restrictions to the query which may be defined outside of the current function, every query in the application goes through this process for security purposes.

After looking around a bit, it was clear that Doctrine did not support (and shouldn’t support) what I was trying to do. My next step was to figure out how to get an executable query from Doctrine2 without ever running it. Doctrine2 has a built in SQL logger interface which basically lets you to listen for executed queries and to see what the actual SQL and parameters were for the executed query.  The problem I had was I didn’t want to actually execute the query I had built in Doctrine, I just wanted the SQL that would be executed via PDO.  After digging through the code a bit further I found the routines that Doctrine used to actually build the query and parameters for PDO to execute, however, the methods were all private and internalized.  I came up with the following class to take a Doctrine Query and return a SQL statement, parameters, and parameter types that can be used to execute it via PDO.

In the ExampleUsage.php file above I take a query builder, get the runnable query, and then insert it into my temporary table. In my circumstance I had about 3-4 of these types of statements.

If you look at the QueryUtils::getRunnableQueryAndParametersForQuery function, it does a number of things.

  • First, it uses Reflection Classes to be able to access private member of the Query.  This breaks a lot of programming principles and Doctrine could change the interworkings of the Query class and break this class.  It’s not a good programming practice to be flipping private variables public, as generally they are private for a reason.
  • Second, Doctrine aliases any alias you give it in your select.  For example if you do “SELECT u.myField as my_field” Doctrine may realias that to “my_field_0”.  This make it difficult if you want to read out specific columns from the query without going back through Doctrine.  This class flips the aliases back to your original alias, so you can reference ‘my_field’ for example.
  • Third, it returns an array of parameters and their types.  The Doctrine Connection class uses these arrays to execute the query via PDO.  I did not want to reimplement some of the actual parameters and types to PDO, so I opted to pass it through the Doctrine Connection class.

Overall this was the best solution I could find at the time for what I was trying to do.  If I was ok with running the query first, capturing the actual SQL via an SQL Logger would have been the proper and best route to go, however I did not want to run the query.

Hope this helps if you find yourself in a similar situation!