By bootstrapping a Symfony project I am referring to creating a ready-to-go basic software package from which to build any projects from.  This also does include Twitter’s awesome Bootstrap libraries as well.

New project requires a well-designed database first

The first thing I usually do with a new Symfony project is design the database.  I use Oracle’s free tool called MySQL Workbench.  Here is a screenshot of a basic database design.  Once I go through the database and document how it will work, I then migrate the table model to the database where it creates the actual tables.

While it may take days to design the database first, this is by far the most critical step because your Symfony project, like most websites, depends on the database to perform properly.

Copying an existing Symfony project or phase of project or start from scratch?

So while this is going on I then would set up a new instance of Symfony on the website.  For first-timers, you need to do it a few times and get used to being able to have the framework’s tools write a bunch of code already for you!  Simply follow the instructions in the Cookbook on Sensio Lab’s Symfony website — a newest feature now is the Symfony installer which you will now need to install first before executing the few other command line prompts.

It’s fast and easy and all the Symfony files will be loaded on your website in the standard folder structure ready to go.  You can move folders around later and if you already did this on a local dev, you can just copy the entire folder to another site.  As an alternative, before you dev’d that project, you could use the .git repository and use the first commit as your bootstrap as well and simply check out those files from the repository.

There are many ways to deploy Symfony and since Symfony’s meant to be modular, Sensio claims it’s flexible and easy to deploy and I find it is most the time.

Essentially any already deployed Symfony project can serve as your next bootstrapped project.  Just don’t copy over anything dealing with “cache” folders or “cache” in the file names.

During initial Symfony set ups, depending on your host and server machine on occasion I would run into some file permission issues or directives in the php.ini or .htaccess files that are prohibited with certain hosts, but this is the exception and not the rule.

Composer – get to know your new friend

You’re not going to get very far if you don’t learn Composer.  It’s pretty easy how it works but it helps you keep all your software dependencies in line so things don’t break later.  Composer is your friend so take 10 minutes and learn up on what it is and does!

In case you were wondering, you can install it on your server through the command line, it’s usually better if you are logged in as the root user:

$ curl -sS https://getcomposer.org/installer | php

Bootstrapping your Bootstrap Symfony Project

Besides the FOSUserBundle, which now looks like it comes with the newest Symfony package, I usually install Braincrafted’s Bootstrap Bundle automatically since I use it for so many projects.  You can always not use a bundle from a vendor, but it’s usually a foregone conclusion I will be needing it.  So follow the instructions how to install the Bootstrap Bundle or simply go to your Symfony folder and add these three requirements to your composer.json file:

"require": { ...
  "braincrafted/bootstrap-bundle": "dev-master",
  "twbs/bootstrap" : "dev-master"
  "jquery/jquery":  "1.11.*"
}

By the way, jQuery’s pretty common and works well with Bootstrap themes, so you need to throw this into the composer.json file after your “requires” list:

 "repositories": [
        {
            "type": "package",
            "package": {
                "name": "jquery/jquery",
                "version": "1.11.1",
                "dist": {
                    "url": "http://code.jquery.com/jquery-1.11.1.js",
                    "type": "file"
                }
            }
        }
    ],

Then on the command line update all your Composer dependencies by typing in:

php composer.phar update

It also just updated my Symfony from 2.6.3 to 2.6.9, so I’m curious if I’ll run into any issues.  You’ll know if you do usually right away you will see 500 errors blowing up or blank pages (yikes) and what you need to do is Google frantically or roll back version in your composer.json file until the errors go away.  Lesson here?

Never ever ever run Composer updates on a live site, always do it on a staging server and test it, then test it again, then ask end users to test your staging again before going live!

Everytime you update your Composer dependencies, you must CLEAR YOUR SYMFONY CACHE!

Do save yourself the frustration and navigate to your Symfony install on your site, usually inside “public_html” and automatically type in  “app/console  ca:cl”  then “app/console ca:cl –env” in that order on your server.  This will clear the cache, sometimes it doesn’t make sense, but do it.  This is just the abbreviated commands for “cache:clear”.

Commit your Barebones Symfony so you have a snapshot

Now, since you’re using a local computer as a dev server and hopefully not the one you’re coding on because running VM on the same machine is asking for performance frustration later — you can just grab the entire site, pull it down, it’ll take 3 minutes.  I use PHP Storm for my IDE and already have it connected to my BitBucket account so after grabbing it all, I commit it and push the code to BitBucket and mark it with “INITIAL COMMIT” and I usually leave a note like “Bootstrap template” so I know it’s a quick way I can have Symfony-ready site to dev later.

Need help?  Feel free to contact me!

 

– Aaron Belchamber

www.AaronBelchamber.com

 


A strange Symfony Doctrine issue got me the other day.  I guess it’s a lack of clear understanding of how Doctrine hydrates database query results when using getArrayResult() instead of getArray().  It seems that getArrayResult() returns just the first record from your query, no matter how many records the query actually returns but getArray() returns an multi-dimensional array containing all results from the same query.

So, I needed a list of all records to display on screen, not just the first one.  All I did was change getArrayResult() to getArray() and this fixed my problem.

But why?!!  Can anyone please provide the answer?!  It’s not on Doctrine’s website, it’s not on stack.  I’ve Googled it I’ve Binged it, if I had nothing better to do maybe I’ll Duckduckgo it.  I’m afraid when I find the answer it will be so obvious that’s why I don’t get it.  I’ve read some users say it depends on what you are selecting in the query, if it’s the record index or some other value or combination of values but have not found any documentation explaining the differences clearly.  Doctrine’s horribly convoluted documentation  says this about getArrayResults():

Query#getArrayResult(): Retrieves an array graph (a nested array) that is largely interchangeable with the object graph generated by Query#getResult() for read-only purposes.

There’s money to be made — make an ORM that’s straightforward and intuitive.


Let’s say your website uses Symfony’s “Friends of Symfony” FOS User Bundle but you also have different internal systems and other ways users can authenticate.  You don’t want to keep pestering the user to log back in, the better solution is to get your authentication system that’s outside the FOS User Bundle to talk to it.

You take extra security precautions, perhaps white list their IP and use some other encrypted cookies values.  Here’s one way you can “refresh” their login if you send the user back to a Symfony controller that falls under the FOS User Bundle’s firewall, which you’ve defined in your Symfony’s security.yml settings file.

So if you can extract the user’s email address from the cookies already set, hopefully through encrypted means, of course, you can essentially log them back in automatically by defining the $user as the object you actually get from the userManager object.

$userManager = $this->container->get('fos_user.user_manager');
$user=$userManager>findUserByEmail($userEmail);

if($user){
   $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
   $this->get('security.context')->setToken($token);
   $this->get('session')->set('_security_main',serialize($token));
}

 

Be sure to add at the top of the controller the use of the the object:  use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

Learn more from Symfony’s documentation about Authentication.  The above is only one solution, I found the FOS User Bundle is pretty simple and flexible to work with.

Are you looking for experienced PHP, Symfony, WordPress, MySQL, LAMP, or Magento developers?  Perhaps you are looking to modernize your company’s systems, considering going open source, or launching a new e-commerce site?  Contact us and we can connect you to a network of flexible web developer freelancers that matches your organization’s needs and budget.


Setting up in Symfony requires setting time zone, of all things, before you can continue with your new website masterpiece.  This is annoying, especially in shared hosting environments when you might not have access to certain settings.

date.time = “US/New_York”

Here’s a list of American time zones for quick reference.

Why are there so many names?  Decoupling in the web is a principle that applies to virtually everything (pun intended).  One zone description for a time zone doesn’t suffice when different localities within a time zone may abide by DST (Daylight Savings Time) and others don’t.  Go figure.


Symfony’s routing system is pretty easy to understand, however, what happens when you need a default, catch-all route that doesn’t match any other routes?  Instead of sending a customer to a 404, you can redirect them to a default path, in this case, it’s the root path “/” (defined in the line “path: /” below) but it could be another path if you’d like.  Remember that the order of the routes are important and take precedence over ones Symfony encounters later down the routing directives list.

defaultCatchAll:
    path:     /{path}
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /
        permanent: true
    requirements:
        path: ".+"

Visit Symfony’s documentation for more details:
http://symfony.com/doc/current/cookbook/routing/redirect_in_config.html
http://symfony.com/doc/current/cookbook/routing/slash_in_parameter.html