TKE – Excellent new Tcl/Tk Text Editor

If you are looking for an excellent new text editor, please check out TKE. It’s a new Tcl/Tk-based editor with many features similar to Sublime Text.

TKE has excellent documentation. However, it is a little bit tricky to install it on Ubuntu, because of some dependencies. To install the dependencies on Ubuntu, run:

sudo apt-get install tcl8.5 tk8.5 tclx8.4 tcllib tklib

Now, just follow the installation instructions in the TKE documentation. And remember to run the installation command with sudo. I installed to /usr/local without any problems.

Advertisements

Correct Laravel application directory structure for proper security

In our first tutorial about Laravel development on Ubuntu, I had recommended moving the contents of the public folder in the Laravel installation up to the Laravel “root” directory. As I’ve been working on my application and these tutorials, I’ve realized that this was a short-sighted approach in the interest of expediency for development, which will cause difficulty when we want to deploy our application later. In particular, we want to apply the principle of least privilege and, accordingly, only make the necessary files available to our users. In general, this would be the contents of the public folder of our Laravel project.

For this example, we are going to consider the common scenario where we are using shared hosting. In this situation, on the hosting provider server, we typically have a “public” directory, often named www or public_html or similar, and other folders which are “private”. We will configure our development environment similarly by putting the contents of the Laravel public folder in the Ubuntu standard Apache “public” site folder (/var/www/html) and the remainder of the Laravel application files in a folder (sub-directory) under our projects folder.

Let’s begin by assuming that we have a standard “clean” Laravel installation in ~/projects/laravel-project. By “clean”, we mean that the public folder is unchanged from the installation using composer create-project laravel/laravel laravel-project --prefer-dist. In the Terminal, run:

sudo mkdir /var/www/html/project
sudo chown -hR username:username /var/www/html/project
cp -R ~/projects/laravel-project/public/* /var/www/html/project
sudo chown www-data:www-data /var/www/html/project/.htaccess
rm -rf ~/projects/laravel-project/public

where username is your Linux user ID. We are simply copying the contents of the Laravel public folder to the new directory for this particular application (project) in the standard Apache “public” directory. I recommend using similar naming between the main (base) Laravel directory and the “public” directory with laravel in the name for the application directory and the “simple” name (without laravel) for the “public” directory. For example, in this case we have laravel-project and project, respectively. Also, note that we must set the ownership of the .htaccess file to the Apache account (www-data).

Next, we’ll set up a specific Apache named virtual host for this directory (/var/www/html/project), which we’ll call project.dev. Create (using sudo!) a new configuration file named /etc/apache2/sites-available/project.dev.conf and add the following to the file:

<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	ServerName project.dev
	DocumentRoot /var/www/html/project

	<Directory "/var/www/html/project/">
		Options Indexes FollowSymLinks MultiViews
		AllowOverride All
		Order allow,deny
		allow from all
	</Directory>

	LogLevel warn
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Also, add project.dev as an alias for 127.0.0.1 to /etc/hosts so that we can use URL http://project.dev/ in the web browser. Finally, activate the new named virtual host and restart Apache server:

sudo a2ensite project.dev.conf
sudo service apache2 restart

Now, we need to update the paths in two of the files that are part of application:

  • ~/projects/laravel-project/bootstrap/paths.php
  • /var/www/html/project/index.php

In each of these files, we are going to set the fully-qualified path names for the relevant files. You can certainly use the __DIR__ PHP “magic” constant and relative path names, but it often gets tricky about the number of levels that you need to move.

In ~/projects/laravel-project/bootstrap/paths.php, change these attributes in the array to:

'app' => '/home/username/projects/laravel-project/app',
'public' => '/var/www/html/project',
'base' => '/home/username/projects/laravel-project',
'storage' => '/home/username/projects/laravel-project/app/storage',

Again, change username in these to your Linux user ID.

Similarly, in /var/www/html/project/index.php, change the require and require_once directives to:

require '/home/username/projects/laravel-project/bootstrap/autoload.php'; 
$app = require_once '/home/username/projects/laravel-project/bootstrap/start.php';

After you have made these changes, you should be able to successfully run the application by going to http://project.dev/ in the web browser. This should display the standard “You have arrived” Laravel page. It should NOT be necessary to include /index.php in the URL, since the .htaccess file in /var/www/html/project removes it.

If you have trouble, make sure that the Apache mod_rewrite extension is enabled:

sudo a2enmod rewrite
sudo service apache2 restart

Likewise, ensure that you have AllowOverall All set in your virtual host configuration (or globally via the /etc/apache2/apache.conf file in the <Directory /var/www/> section).

With these changes, you should now be able to update your Laravel application files in ~/projects/laravel-project and changes to the “public” files in /var/www/html/project should not be necessary. Each time you make a change to the application, just refresh http://project.dev/ in your browser to observe the change.

To confirm this, open the app/routes.php file and add a new route to the end of the file:

Route::get('test', function()
{
	echo 'This is the "test" route!';
});

In the web browser, enter the URL http://project.dev/test (without index.php or trailing slash). The browser should simply display the text This is the “test” route!.

In addition, you will need to update the debugging configuration in Aptana (or Eclipse) to reference the appropriate URL (http://project.dev/). You will probably want to create a new External Web Server Configuration and set the Base URL to http://project.dev and the Document Root to /home/username/projects/laravel-project. In your Debug Configuration, set the Initial Script to bootstrap/start.php. Likewise, you will want to uncheck (disable) URL Auto Generate and leave the URL with just the base URL of http://project.dev/.

References

Setup Laravel 4 in Shared Hosting While Securing Laravel base files
Ubuntu 12.04 Laravel and mod rewrite

Create database tables for Laravel e-commerce application

Now that we have our requirements for our Laravel e-commerce application, we are ready to get started with actually developing the application. (Finally!)

We will use the powerful Laravel “migrations” feature to create our database tables and relationships. Migrations may seem like an odd name, but essentially it allows us to have some version control for the changes that we make to our database over the lifecycle of the project. Likewise, it is helpful for allowing others to take our source code and get their database up and running quickly, even if they are using a completely different database engine, since the migrations files are independent of the database platform that you are using.

In general, I like to use the migrations tool to create a template file and then manually customize the details to fit my preferences. In particular, I prefer to include the table name as part of the primary key column in the tables, whereas Laravel simply names the column ‘id’. Likewise, if you have some “boilerplate” columns that you like to include in all of your tables, using the template helps to ensure consistency of these column names.

  1. To begin, we need to create a database for our application. Since we are using the LAMP stack, we’ll create the database in MySQL. You can create the database in the Terminal (see below) or, if you prefer, you can use other tools, such as phpMyAdmin.

    For this example, we’ll name the database ‘laravel’ and simply use the MySQL ‘root’ user account. Likewise, I’m assuming that the MySQL ‘root’ account does not have a password. Obviously, this is VERY insecure, but it is fine for your local development environment. In a production scenario, you would want to create a specific user and grant that user limited permissions to the database.

    To log into MySQL, run:

    mysql -u root
    

    If the MySQL ‘root’ user has a password, you can simply append -p to the command and you’ll be prompted to enter the password.

    At the mysql> prompt, we will create our database and add a new user, with a password of ‘password’, with full privileges to the database.

    CREATE DATABASE laravel DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;
    CREATE USER 'laravel_crud'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL PRIVILEGES ON laravel.* TO 'laravel_crud'@'localhost';
    

    After each command, MySQL should respond with Query OK and some other relevant information. In the last statement, laravel.* limits the command to the laravel database, but to all tables in that database.

    We chose the user name ‘laravel_crud’ to indicate that this user will have full privileges on this database. ‘CRUD’ is an acronym for ‘Create-Read-Update-Delete’, which are all of the typical operations on database tables.

    That’s all we need for the database for now! Simply log out of MySQL by entering exit;.

  2. Now that we have our database, we need to configure Laravel to access the database. In Aptana (or another text editor), open the app/config/database.php file and locate the 'connections' array. In the 'connections' array, update the 'mysql' element array:

    'mysql' => array(
       'driver'    => 'mysql',
       'host'      => 'localhost',
       'database'  => 'laravel',
       'username'  => 'laravel_crud',
       'password'  => 'password',
       'charset'   => 'utf8',
       'collation' => 'utf8_unicode_ci',
       'prefix'    => '',
    ),
    

    You can quickly confirm that the configuration is valid by displaying the site in your web browser (e.g., http://projects.local/laravel/). As long as the configuration is correct, the page should display correctly. If there is a configuration error, you’ll get a nice Laravel error message.

  3. Laravel’s built-in migration functionality will simply create a “shell” of the class for us. We will supplement this with the excellent Laravel 4 Generators package by Jeffrey Way. To add this (or any third-party) package, in the Terminal, navigate to the root of the Laravel project (e.g., ~/projects/laravel) and run:

    composer require "way/generators":"2.*" --prefer-dist
    

    This will add the package to your composer.json file. Now we just need to run a Composer update to install the new package and its dependencies, if any.

    composer update
    

    To activate the new Generators package, open the app/config/app.php file and add this line to the end of the providers array:

    'Way\Generators\GeneratorsServiceProvider',
    

    If you like, you can also add an alias, such as Generator to the aliases array. Having an alias makes it simple to reference the classes by the short name, instead of the fully-qualified name.

  4. Based on our requirements, we need the following tables (and associated Laravel models):

    • account
    • product
    • order
    • order_item

    Let’s start by creating a migration for the account table. We’ll then use this migration class as a template for the other tables.

    First, we need to create the migrations table in our database. This table simply keeps track of the various changes that we’ve made to the actual tables used by our application. To create the table, run:

    php artisan migrate:install
    

    To generate (using the Generators package which we added above) the migration for the account table, in the Terminal, from the project root directory, run:

    php artisan generate:migration create_account_table --fields="email_addr:string, password:string"
    

    This will create a migration file in the app/database/migrations with the name YYYY_MM_DD_HHMMSS_CreateAccountTable.php where YYYY is the 4-digit year, MM is the month, DD is the day and HHMMSS is the hour/minute/second that the migration was created. (Note that the HHMMSS is the UTC time, based on your system’s time zone setting.) For example, 2014_08_05_203018_CreateAccountTable.php. Open this file in your editor (Aptana, etc.). The generated file will look like:

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    
    class CreateAccountTable extends Migration {
    
    	/**
    	 * Run the migrations.
    	 *
    	 * @return void
    	 */
    	public function up()
    	{
    		Schema::create('account', function(Blueprint $table)
    		{
    			$table->increments('id');
    			$table->string('email_addr');
    			$table->string('password');
    			$table->timestamps();
    		});
    	}
    
    
    	/**
    	 * Reverse the migrations.
    	 *
    	 * @return void
    	 */
    	public function down()
    	{
    		Schema::drop('account');
    	}
    
    }
    

    As you can see, this class essentially consists of the up() method, which creates the table in the database, and the down() method, which drops the table. When you apply the migration (see below), the up() method will create the account table in the database.

    We want to make a few customizations to the class for our specific needs. The only changes that are required are to the up(). Change this method as follows.

    	public function up()
    	{
    		Schema::create('account', function(Blueprint $table)
    		{
    			$table->increments('account_id');
    			$table->string('email_addr', 50);
    			$table->string('password', 30);
    			$table->boolean('admin_ind')->default(0);			
    			$table->string('address1', 50)->nullable();
    			$table->string('address2', 50)->nullable();
    			$table->string('city', 20)->nullable();
    			$table->string('state', 2)->nullable();
    			$table->string('postal_code', 20)->nullable();
    			$table->dateTime('created');
    			$table->integer('created_by_account_id');
    			$table->dateTime('last_modified');
    			$table->integer('last_modified_by_account_id');
    		});
    	}
    

    Now that we have a basic template for our migrations, we can use it for the other tables that we need for our database. Here are the details for each of the other classes. Again, we’ll only show the up() method, but you need to update the class name and the down() method for each, appropriately. Likewise, each class should be saved in it’s own file.

    product table

    	public function up()
    	{
    		Schema::create('product', function(Blueprint $table)
    		{
    			$table->increments('product_id');
    			$table->string('product_code', 20);
    			$table->string('product_name', 50);
    			$table->string('product_description');
    			$table->string('media_type', 10);
    			$table->integer('unit_qty');
    			$table->float('unit_price');
    			$table->string('download_directory', 100)->nullable();
    			$table->boolean('available_ind')->default(1);
    			$table->dateTime('created');
    			$table->integer('created_by_account_id');
    			$table->dateTime('last_modified');
    			$table->integer('last_modified_by_account_id');
    		});
    	}
    

    order table

    	public function up()
    	{
    		Schema::create('order', function(Blueprint $table)
    		{
    			$table->increments('order_id');
    			$table->integer('account_id')->unsigned();  // FK to account table
    			$table->string('order_status');
    			$table->float('order_gross')->nullable();
    			$table->float('order_net')->nullable();
    			$table->float('discount')->nullable();
    			$table->float('transaction_fee')->nullable();
    			$table->string('payment_gateway_txn_id', 30)->nullable();
    			$table->string('payment_gateway_order_id', 30)->nullable();
    			$table->dateTime('created');
    			$table->integer('created_by_account_id');
    			$table->dateTime('last_modified');
    			$table->integer('last_modified_by_account_id');
    		});
    	}
    

    order_item table

    	public function up()
    	{
    		Schema::create('order_item', function(Blueprint $table)
    		{
    			$table->increments('order_item_id');
    			$table->integer('order_id')->unsigned();  // FK to order table
    			$table->integer('product_id')->unsigned();  // FK to product table
    			$table->integer('qty');
    			$table->float('extended_price');
    			$table->dateTime('created');
    			$table->integer('created_by_account_id');
    			$table->dateTime('last_modified');
    			$table->integer('last_modified_by_account_id');
    		});
    	}
    
  5. Once we have all of the migrations classes created for our tables, we are ready to apply the migrations to create the tables in our database. Actually, running the migrations is very simple:

    php artisan migrate
    

    Laravel will list the migrations that are executed in the terminal. Likewise, you can check the migrations table in the database to see them. The batch column in the migrations table gets incremented for each run.

    If you need to revert any updates made via the migration, you run the migrate:rollback command which reverts only the last migration. If you want to start over completely, use the migrate:reset command. In addition, migrate:refresh will do a reset and then load the current migrations.

    To get a list of all of the migrations commands run php artisan list command. Most of the migrations commands start with ‘migrate’.

    To learn more about Laravel migrations, I highly recommend the article “Managing Databases with Migrations”.

That’s it for this topic. Next time, we’ll start creating the Laravel models corresponding to our database tables.

Configure PHP development environment using Aptana (or Eclipse) and XDebug on Ubuntu/Linux Mint

Before we actually start working on our new Laravel application, let’s set up our PHP development environment in Ubuntu/Linux Mint. We’ll develop using the Aptana IDE (integrated development environment), which is a web development-specific version of the popular open-source Eclipse IDE. Likewise, we’ll set up the excellent XDebug debugger to help us develop more effectively.

  1. To use Aptana (or Eclipse), we must have Java installed on our system. In most cases, Java will already be installed, but just to confirm that you have it, run this command in the Terminal:
    java -version
    

    You should see something similar to this in response to the command:

    java version "1.7.0_55"
    OpenJDK Runtime Environment (IcedTea 2.4.7) (7u55-2.4.7-1ubuntu1)
    OpenJDK Client VM (build 24.51-b03, mixed mode, sharing)
    

    The actual version of Java is not too important, as long as it is 1.6 or greater. (Java’s numbering scheme is a bit confusing and the value after the first decimal is actually the version. For example, “1.6” really means Java 6!)

    If you don’t have Java installed (i.e., an error occurs when you check the version), you can install it with this command:

    sudo apt-get -y install openjdk-7-jdk
    

    This installs Java 7.

    Alternately, you can install Java 6 from the Ubuntu repository, but I recommend using the latest version unless you have a specific need for an earlier version, such as application compatibility. (Note that Ubuntu can support multiple Java JDK/JRE versions, but only one can be active at a time. See the man page for the update-alternatives command.)

    After Java is installed, run java -version in the Terminal again to make sure it is working correctly.

  2. Now we need to install the XDebug PHP extension to help us with debugging and troubleshooting when we are developing our application with Laravel. XDebug allows you to pause the execution of your code to check the internal values of variables (and even change them!) using breakpoints and to step through individual lines of code to examine what PHP is doing with the data.
    Ubuntu has relatively recent versions of XDebug, so we can simply install from the repositories:

    sudo apt-get -y install php5-xdebug
    sudo service apache2 restart
    

    After it has installed, open your “phpinfo” page to ensure that XDebug is referenced as one of the loaded modules/extensions (it will be listed toward the bottom). You should see something like:
    XDebug_configuration

    To avoid conflicts with other debuggers, such as for Java, on our system, we are going to change the TCP port that XDebug “listens” on to 9008 (from the default of 9000). First, we need to find the XDebug configuration file: On the “phpinfo” page, look for the Additional .ini files parsed section at the top and find the name of a file which contains “xdebug”, such as /etc/php5/apache2/conf.d/20-xdebug.ini. Open the XDebug configuration file in a text editor (you will need to use sudo, since this file is “owned” by the system root user!) and add the following lines.

    xdebug.remote_enable = on
    xdebug.remote_port = 9008
    xdebug.remote_host = localhost
    xdebug.remote_handler = dbgp
    

    Note: We are only changing the remote_port setting from its default (9000). However, for some reason, Aptana (Eclipse) does not recognize the default values of the other settings, so we must set them explicitly.

    Of course, you can add other configuration settings, as necessary, such as if you are trying to debug on a different machine (by default, XDebug assumes that the “host” to use for debugging is “localhost”, which the name of the machine itself). See the XDebug settings documentation for details.

    Restart the Apache web server (sudo service apache2 restart) and check the “phpinfo” page to ensure that the xdebug.remote_port value is now 9008.
    XDebug_Port_Details

  3. After these preliminaries, we are ready to install the Aptana IDE. From the Aptana web site, download the Linux installation package. Make sure that you download the correct version (32-bit or 64-bit) for your Linux distribution. Extract the archive file and install the application. (I use the handy dtrx utility, which is available in the Ubuntu repositories, to extract the file, since it automatically handles a variety of archive types without remembering all of the different commands and parameters!)
    cd ~/Downloads
    dtrx Aptana_Studio_3_Setup_Linux_x86_3.6.0.zip
    mv Aptana_Studio_3 aptana
    sudo mv aptana /opt
    sudo ln -s /opt/aptana/AptanaStudio3 /usr/local/bin/aptana
    sudo chmod +x /usr/local/bin/aptana
    

    I won’t go into all of the details of these actions, but essentially we are moving the extracted (unzipped) Aptana files to the /opt directory and creating a exectuable symbolic (“soft”) link to the Aptana executable file in /usr/local/bin, so that we can launch Aptana from most any directory. We can now run Aptana IDE, either from the Terminal or the Run Application window (<Alt>+<F2>) by simply entering aptana.

    So let’s start it up! You’ll be prompted to create (or choose) a “workspace”; just choose the default and check (enable) the Use this as the default and do not ask again option. When Aptana IDE opens, it will display the “Start Page” with some other windows and tabs.

    By default, Aptana uses its internal web browser, but I prefer to use Firefox. (You may prefer Chromium or another browser; if so, just adjust these instructions accordingly.) To make this change, choose Window | Preferences from the menus and navigate to General –> Web Browser in the Preferences window. Select the Use external web browser option and then click on Firefox (or your preferred browser!) in the list. You can click on Edit… button to confirm that it is the brower that you expect and enter any command line parameters, such as a specific Firefox configuration, if desired.
    Aptana_Preferences_Web_Browser

    While in the Preferences window, navigate to Aptana Studio –> Editors –> PHP –> Debug. In the Installed Debuggers list, select XDebug and press Configure and change Debug Port to 9008 and Accept remote session (JIT) to any in the XDebug/DBGp Settings window. (You can leave the other settings with their defaults.)
    Aptana_Preferences_XDebug_DBGp_Settings

    Move to Aptana Studio –> Editors –> PHP –> PHP Interpreters and press Add…. In the Add new PHP Executable window, enter these values/settings:

    • Name: PHP5.5
    • Executable path: /usr/bin/php
    • PHP ini file: /etc/php5/apache2/php.ini
    • PHP debugger: XDebug

    Aptana_Preferences_Add_New_PHP_Executable

    You may get an error that you don’t have permissions to save the php.ini file. That’s fine, since we aren’t actually changing it from within Aptana.

    Of course, this only scratches the surface of the power and capabilities of Aptana (and Eclipse). I recommend looking for other resources on the Internet. Most any article or utility that you find for Eclipse will apply equally to Aptana. Aptana is simply a customized configuration of Eclipse which focuses on web development. (Eclipse was originally created as an IDE for Java development and programming.) For example, most of the plugins on the Eclipse Marketplace (and especially those in the Web category) will work just fine in Aptana. The Eclipse site has has good information about how to install plugins, both from the Marketplace and other third-party sources.

    While I (obviously) can’t go into all of details about Aptana (and Eclipse), here are a few plugins that you may want to check out:

    • Eclipse Color Themes – Directory of themes (editor color schemes)
    • DBeaver – Open-source universal database editor plugin, includes support for MySQL (stand-alone version available, as well)
    • Markdown Editor – Free editor plugin for Markdown format, which is often used for documentation
  4. To test out Aptana and XDebug, let’s create a simple (non-Laravel-based) PHP project.
    In Aptana, choose File | New –> PHP Project and:

    • Enter “Project1” as the name;
    • Uncheck Use default location and set the Location as the Project1 directory in your projects folder (e.g., /home/username/projects/Project1; and
    • Press Finish.

    The Project Explorer on the left of the Aptana screen will now list Project1. Right-click on Project1 and choose New From Template –> PHP –> PHP Template from the context menu. When prompted, name the file TestFile1.php and press Finish. This will give you a “shell” PHP script file. Change the contents of the file to:

    <?php
    	echo "<h3>";
    	echo "My first Aptana PHP script!";
    	echo "</h3>";
    	echo "<p>What do you think?</p>";
    ?>
    

    After you save the file, choose Run | Debug Configurations… from the menus. In the Debug Configurations window, double-click on PHP Web Page, which will create a new configuration named “New_configuration”. Rename this configuration to “PHP XDebug” for clarity. Choose XDebug for the Server Debugger. For Initial Script, browse for the TestFile1.php which you created. Click on the New button (a green ‘+’) next to PHP Server and enter the following details for this debug configuration:

    • Name: projects.local
    • Base URL: http://projects.local
    • Document Root: /home/username/projects, where username is your Linux user ID

    Aptana_Edit_External_Web_Server_Configuration

    Check (enable) both the Break at First Line and Auto Generate options. For convenience, I like to show the debug configurations in the Aptana menus, so navigate to the Common tab and check (enable) Debug in the Display in favorites menu section. Press Apply to save this debug configuration.
    Aptana_Debug_Configurations

    We can now actually run the debugger to ensure that it is working. Press Debug button in Debug Configurations window. You will probably receive a warning that XDebug client is listening on a “non-standard” port. This is fine, since we intentionally choose to use port 9008 (instead of 9000), so you can check (enable) Do not warn me again and press Proceed.

    In a moment, Firefox (or whatever external web browser you chose above) will launch (or open a new tab, if it’s already open). Simultaneously, Aptana (Eclipse) will prompt you about changing the “perspective” (the display configuration defining what windows and tabs are shown). Press Yes and Aptana will modify the display to show a Debug tab and some variables windows (more about those later!) at the top with your source code window for TestFile1.php in the middle.
    Aptana_Debugger_Output

    You will notice a (very) small blue arrow on line #2 and that this line is highlighted. Likewise, in the Debug tab, it will show TestFile1.php.{main} : lineno 2, indicating where the execution paused. This indicates that the debugger has stopped (or “hit a breakpoint” in programming parlance). Even though you did not explicitly set a breakpoint, you will recall that above we checked (enabled) the Break at First Line option. This is a nice way to ensure that the debugger properly launches. We can now let the script continue (“play through”) or execute the script one line at a time (“step through”). Also, you will observe that the web browser appears “stuck” loading the page. This is normal, since the Aptana debugger has paused the execution of the script on the breakpoint.

    For now, we’ll simply let the script continue (“play through”), since we’ve accomplished our objective of confirming that the debugging is configured properly. Choose Run | Resume from the menus or use the keyboard (<F8>) or toolbar (DVD player ‘Play’ button) equivalents. The Debug tab will show that the session terminated, which is normal, since the script completed successfully. Likewise, the output of the script will be written to the web browser window. Aptana will leave you in the Debug perspective. To return to the “normal” Web perspective, choose Windows | Open Perspective… | Web from the menu (or click on the Web perspective button in the upper right corner).

    If you have a problem with your configuration, the web browser will likely display your TestFile.php page (hopefully, correctly!), but Aptana will appear “stuck” (or “hung”). In the lower right corner of Aptana on the status line, you should see a message Launching PHP XDebug with a percentage and a progress indicator. Next to it will be a button that looks like a stack of windows with the tool tip Show background operations in Progress view. Click this button and wait for the Progress tab to be shown. The Progress tab should have a single progress indicator that shows “Launching: waiting for XDebug session”. Press the red square button (Cancel Operation) to the right of it to abort the launch of the debugger. Check your LAMP set up and Aptana debugger configuration settings to ensure that they are correct and then try again.

And that’s it! We’ve accomplished a lot in this session. Next time, we’ll start work on our Laravel application itself. See you then!