Author: Cyril Ogana
Last month viewers: 4
Categories: PHP Tutorials, Sponsored
Read this part of the article to learn how to debug a framework based application, specifically using Symfony, combining the power of PHPEd debugger and common framework principles to debug code faster.
By Cyril Ogana
Symfony HTTP Kernel
Symfony Debug Component
As we all know, PHP was a built for building Web applications. These applications produce Web content for instance in form of HTML pages or responses to Web Service calls in JSON, XML or other formats.
For traditional Web application building, the top level design architecture known as MVC reigns, although there are some variants of it.
PHP supports direct access to HTTP headers of requests and responses enabling support for API protocols such as REST and SOAP. The need to handle requests and direct them to the appropriate resource, and with the requested parameters if they exist is handled well by MVC frameworks, with their router and controller components.
Frameworks also come with CLI toolkits that prove useful when installing or updating new modules into the framework. The fundamentals don't change much from framework to framework. Just like IDE's, their principles are similar but each one has its stronger points.
For this tutorial, we will be using the following
1) Symfony Framework (Using version 2.8 in this tutorial)
2) The Symfony Demo application
3) PHPEd - You may want to read the first part of this article for a tutorial on the installation of PHPEd
This tutorial will cover the following features of debuggers highlighted in the diagram:
Monitor Values of Variables and Items in Data Structures
2. Local and Global Variable Values
3. Conditional Breakpoint
Modify the values of data items while debugging
1. Modify Global Variables
2. Change values of variables at runtime
3. PHP Expressions
Symfony HTTP Kernel
When I first heard a mention about the Symfony HTTP Kernel I was having all sorts of impressions about what it might be all about. Why was it so special?
Symfony is a package based framework. This means the packages that make it up can be used as fully fledged components on their own. The Symfony framework itself is a package.
Now, request and response is a method computers use to communicate with each other. The client makes a request and server responds with appropriate response. This is the principle used in the HTTP protocol.
The request methods passed to the Web server (these are also known as verbs) indicate the desired action the client would like performed on the resource. The most common request methods users are familiar with are GET and POST; several more exist.
Symfony's Github page says that the purpose of the HTTP Kernel is to provide structured process for converting a request into a response. This component alone is flexible enough to use to create a full stack framework.
In my opinion, this is a noble goal, providing request and response objects that encapsulate HTTP and provide users with a clean interface to manipulate their HTTP requests and responses.
Here follows a simple illustration:
use Symfony\Component\HttpFoundation\Request; $request = Request::createFromGlobals(); //fetch cookie
$request->cookies->get( 'DBGSESSID' );
It is with the request and response objects that we will begin our debugging tutorial. To get started. fire up your PHPEd IDE and create your project. Assure yourself that the installation wizard completes successfully and confirms that the debugger is working. Part 1 of this tutorial series explains how to do this.
Front Controllers handle all requests in the Web application. In Symfony, this role is managed by the app.php and app_dev.php which are in the root of your project's Web directory.
When debugging, you might get a complaint from the IDE that the path cannot be executed. This is because the Wizard usually sets the root URL to http://localhost while we need to change this to your symfony_demo directory.
You may do this by clicking on Project >> Project Settings >> Run Target and updating this information.
Now that we are set up, we can dive in to a bit of debugging. Our first agenda will be to look at the structure of our request and response objects at runtime. These are both contained in the Front Controller. We are using app_dev.php and not app.php, which is configured for production settings, and will return a 403 error if you try to plug the debugger to it.
We open our app_dev.php file and add breakpoints to the lines containing the following code:
$request = Request::createFromGlobals(); $response = $kernel->handle( $request );
We also add the two variables above to the Watch list by right clicking the variable name and clicking "Add to Watch List".
While the cursor is in your app_dev.php file, click on Run >> Run In Debugger >> app_dev.php
You may then use the "Step Over" method to run through the process. The shortcut key for this in PHPEd is F8. Stepping over code and other debugging techniques are described in detail in Part 1 of the tutorial.
As we iterate over the code, we eventually reach the point where the Request and Response objects are set. The breakpoints ensure that the code execution halts so we can view the structure of the objects in the watch list.
Below is how the Request object looks for accessing the home of the Symfony Demo application.
The response object structure contains information to allow Symfony's event dispatcher to return a HTML or other format response to the client.
While we used an exploratory approach in Part 1 of this tutorial series, we take an interactive approach here. We manipulate variables at run time, and perform controlled monitoring of runtime values through conditional breakpoints, which we shall look at later.
Interactive debugging enables us monitor run time state of new code, test for edge case requests, and attempt to reproduce user errors by replicating requests they made.
Let us start with a simple example. Start a debug session on your front controller. Before stepping over the code, we make a simple runtime change by adjusting the value of the REQUEST_URI index of PHP's global variable $_SERVER. Right click the parameter name and click "Change Value" or double click on the parameter name to edit it. Here we change the request to point to the blog page.
You can change the value of any variable at runtime, depending on the objective of your debugging. Below, we see our updated REQUEST_URI
At the end of code execution, the internal PHPEd browser presents to us the HTML result.
The interactive approach provides very good opportunity to manipulate variables to monitor their effect on runtime state and logic.
Routes in Symfony are generally configured through PHP Doc block annotations. You may also use Yaml, XML or PHP configuration files to set up your routing . There is a whole chapter dedicated to Routing in the Symfony book.
Lets assume we wanted to add a new locale to the Demo application. We shall be adding Swahili.
As you can see from the blog URL of the Demo application, the route has been designed such that the path is prefixed with a locale.
Let us begin by configuring the app.locales variable the app/config.yml file of your project. We use a configurable service container parameter to provide a more flexible solution. The service container is the component that drives Symfony's Dependency injection logic.
Fire up your debug session on the app_dev.php file and edit the REQUEST_URI as previously illustrated. This time, set it to "/web/app_dev.php/sw/blog" and step over the code. We expect an exception to be thrown and the IDE should give us the chance to set a breakpoint and investigate further.
We fix this by adding the Kiswahili locale to the app.local parameter. Open the file app/config.yml and add the desired locale.
We still need to add a translations file, otherwise the Swahili presentation will still be presented in English. This files are saved in the app/Resources/translations directory. Copy the files messages.en.xlff and validators.en.xlff into messages.sw.xlff and validators.sw.xlff and edit accordingly.
You may use the locale of your choice that allows you to set accurate edits.
You may have to delete the content in the app/cache/dev directory for your changes to take effect.
On stepping over again, we now see our desired locale in the menu.
Our translations have been picked up as well.
The interactive process has allowed us to verify our new code changes. The watch we added on the Response object is a good option as well to verify our translations (especially if we are adding several locales) are being done correctly.
Controllers manage the task of taking user requests, processing them and returning the appropriate response. The logic in a controller involves a calls to business level components, which contain the logic that processes the resource required by a user e.g. database actions.
The Symfony Demo application contains a certain controller for adding comments. Let us assume we would like to make a small modification to the commentAction controller. We would like to add a Profanity detection filter that will prevent posting of any comment that may contain swear language. This is a necessary requirement in blogs nowadays.
We will connect to the API provided by http://www.purgomalum.com; formatting our request such that the Response Tyep of the API is the string "true" when profanity is detected, otherwise "false". On your PHPEd IDE, open the src/AppBundle/Controller/BlogController.php file. We make a small modification to run a users comment through the Purgomalum API which is public.
We add a watch to our Request object as well and also create a conditional breakpoint on our $containsProfanity variable. Should it return true, the breakpoint fires so we can observe the runtime state. To activate the Breakpoint window, click on View >> Debug Windows >> Breakpoints
To add a conditional expression to a breakpoint, right click the breakpoint in the breakpoint window and click on "Properties"
Check the expression true global attribute and add the expression that shall trigger the breakpoint. We add
$containsProfanity === "true"
If our API matches a profane comment, the breakpoint will be triggered.
Triggering conditional breakpoints at certain points may help as we continue to develop our application. At the moment the solution is incomplete e.g. throwing an Exception is a bit too heavy for such a situation. We should continue on and develop a custom Validator that will be used to validate the Comment entity and provide a neat error feedback to the naughty user.
So far, we have been using our Debugger with browser based applications. Symfony comes with a powerful console package that can be used to build Powerful command line applications. We shall look at debugging CLI applications in part 3 of this series, which will be discussing remote debugging, and shall be using the Symfony Console package for that purpose.
Symfony Debug Component
Symfony has several components in its tool-kit. One of them is the Debug component, which comes with several tools to ease PHP development. The debug component registers a special ErrorHandler, ExceptionHandler and ClassLoader when enabled. The code to enable this component is.
This Debug component will not clash with your be complemented by the PHPEd IDE's debugging toolkit as it can as well be monitored at runtime.
In this part of the tutorial it was presented a concrete case using PHPEd debugging capabilities to debug an applications that uses the various layers of a PHP Web framework. In this case it was Symfony 2.8 and its demo application, but could be any other framework implemented in a similary way
PHPEd debugger was used to conduct interactive debugging on the PHP Globals level, the front controller, router and controller components. Again the major benefit here is the productivity gain. We expect such debugging power in IDE's.
PHPEd is a popular commercial IDE but if you want to try what was demonstrated in this article, you can download PHPEd free trial version now.
In the next part of the tutorial it will covered the key benefit of PHPEd, which is remote debugging, i.e. debugging applications running in a remote server.
If you liked this tutorial article, please share it with your PHP developer friends. If you have a question post a comment here.
You need to be a registered user or login to post a comment
Login Immediately with your account on:
No comments were submitted yet.