Posted by & filed under Development, JavaScript.

If, like me, you use AMD-style loading for your JavaScript projects, you might have wondered how to integrate the (non-AMD enabled) Google Analytics library into your project.

 

Define fallbacks

Many web apps these days are being built with offline capabilities in mind. Go ahead and download http://www.google-analytics.com/analytics.js to your local web folder. We’ll need it as a fallback in a second.

Add the following to your paths config:

paths: {
    ...
    "google-analytics":         [
        "//www.google-analytics.com/analytics",
        "vendor/google-analytics" // this is your local copy
    ]
}

Shim it!

The GA library doesn’t contain any AMD-detection, so we’ll need to shim it and export the ga global.

shim: {
    ....
    "google-analytics":  {
        exports: "ga"
    }
}

Usage

You’ll need to initialise it. Here’s a basic analytics module I’ve written that serves as an example:

 

define(["eventbus", "google-analytics"], function (Eventbus, ga) {

    var self = {};

    self.trackPageView = function (uri) {
        // @todo check active ga/connection before each event
        ga('send', 'event', 'pageView', uri);
    };

    self.trackAction = function (type, description) {
        ga('send', 'event', type, description);
    };

    self.trackTiming = function (category, identifier, time) {
        time = time || new Date().getTime() - window.performance.timing.domComplete;
        ga('send', 'timing', category, identifier, time);
    };

    Eventbus.on("loading.finished", function () {
        ga('create', 'UA-XXXXXXX-X', {
            'cookieDomain': 'none'
        });
        ga('send', 'pageview');
        self.trackTiming("webapp", "initialise")
    });

    return self;

});

You’ll probably want to pass in the tracking code as a config parameter, and check for a valid ga session before each tracked event, or perhaps collect some events when offline and only fire them once back online. Go ahead and be creative!

Posted by & filed under Development, symfony.

Composer is a great way to manage your PHP dependencies. The documentation is still a bit scarce, so you could imagine that it took a while to find out how to add an external dependency (in my case from github) which doesn’t have a composer.json file and is not registered on packagist. There are different solutions, but Composer seems to be under active development and none worked for me.

Read more »

Posted by & filed under Development, symfony.

I’ve had a bit of an odd issue where JavaScript files from a plugin I’d written weren’t being included for some reason.

Turns out that there’s a bug / feature (?) in the way symfony merges config files. Read more »

cluster_icon

Posted by & filed under Development, symfony.


While the title might sound a tad complicated, the problem is pretty straight forward:

Your production environment consists of a multi-server set-up (e.g. a cluster, but works on a single server just as well) with a centralised database and you use sfFileCache as your caching strategy (because you don’t want to litter your database with cache entries).

So how would you clear parts or all of the cache? You can’t just use symfony:cc or the sfViewCacheManager because:

  • It won’t work across applications, e.g. when triggered from your backend application, you won’t be able to clear the cache on your frontend.
  • It will only clear the cache on your current server, while the other servers still contain the old cache version.

Read more »

Posted by & filed under Development, symfony.

Are you growing tired of Facebook games that have absolutely no depth and simply consist of nice graphics without any strategic gameplay like Farmville, Mafia Wars etc.? Well, so was I to say the least. I believe I can do better than this and so I teamed up with Daniel West (graphics, storyline) and Francesca Sciarmella (3D graphics) in February to build a full-scale strategic game. Read more »

Posted by & filed under symfony.

In order to automate tasks that should run on a regular basis, you will need a cronjob. Fortunately, creating cronjobs with symfony is a piece of cake.

First, you will need to create a batch task. Navigate to your project directory and enter

symfony generate:task [your task] 

This will generate a task skeleton for you in lib/task/[your task]Task.class.php , which contains two important methods: configure() and execute(). The names are pretty self-explanatory. All your code should go in the execute() method. You might want to do some configurations first. Change the following lines in configure() accordingly:

$this->namespace        = 'project';
$this->name             = '[name-for-your-task]';
$this->briefDescription = '[some short explanation of what your task does]';

Before you start hacking your code into the execute() method, I would recommend to test-run it in a normal symfony module first. When you’re done, copy&paste the action of your test module into the execute() method. Be aware that tasks don’t contain a view and, therefore, you will need to echo any output directly in the method itself. An example that, frankly speaking, does nothing useful at all:

protected function execute($arguments = array(), $options = array())
{
 // initialize the database connection
 $databaseManager = new sfDatabaseManager($this->configuration);
 $connection = $databaseManager->getDatabase($options['connection'] ? $options['connection'] : null)->getConnection();

 // add your code here

 echo "I just did nothing at all, but at least I did it successfully!\n\n";
}

Let’s give it a test run. Open your command line and enter

symfony project:[your task]

If you see the expected output, you’re ready to go to the next step.

Please notice: The paths I’ve used apply to OpenSuse 11.1. If you run another Linux distribution, you might have to amend them.

Open your servers crontab at /etc/crontab in your favourite text editor and add the following line to the end of the document:

*/5 * * * * cd [YOUR SF APP DIR] && /usr/bin/symfony project:[YOUR TASK] >>[YOUR SF APP DIR]/log/crontab.log

Update: Thanks to Marcell Fülöp for the suggestion to use >> to avoid overriding existing log entries

Explaining every detail of cronjobs would definitely blow the extent of this how-to and there are some very good sites out there that can help you understand. Just a quick explanation: This task runs every 5 minutes, changes to your symfony application directory, executes your task (please note that you don’t have access to your $PATH variables, so no symfony shortcut!) and outputs the result to /log/crontab.log .

Posted by & filed under symfony.

Eclipse and Symfony - A beautiful couple

Every programmer knows it, every programmer loves it: the Eclipse IDE. It is probably the most extensive free open-source development environment out there (Netbeans put aside). In this tutorial I’d like to show you how you can get it ready for symfony, the (in my opinion) best PHP framework there is at the moment.

1. Download and install the Eclipse-based PDT (PHP Development Tools) standalone version: http://www.eclipse.org/pdt/

2. Now we’re going to install some plugins that are going to make your life easier when you are a symfony developer. Click Help -> Install New Software … and add the following plugins to Eclipse:

  • Aptana Studio Update Site – http://update.aptana.com/update/studio/ -> Aptana Studio (only if you want to use the built-in FTP functionality, otherwise you don’t need to bother about this one)
  • YEdit – http://dadacoalition.org/yedit -> YEdit (a YAML syntax highlighter, since most of symfony’s configuration is being done through .yml files

3. After restarting Eclipse, we are going to add some symfony-specific auto-completion features to Eclipse. At this point, you will probably have the symfony framework installed somewhere on your PC. If you have not done so, download it from here or here and unpack it to a directory that you can easily remember.
Now change back to Eclipse. Open Window -> Preferences -> PHP -> PHP Libraries -> New, enter “symfony” as a name and tick the Add to environment option. After clicking OK, you will notice the entry we just added in your libraries list. Mark the new entry by clicking on it, the click Add external folder…, browse to the folder where you put the symfony framework and add it.
Now you can add the symfony library every time you create a new PHP Project in Eclipse or by right-clicking on an existing project ->Include Path -> Configure include path. Either way, you need to click on Add Library -> User Library -> symfony and add it.

4. If you have installed the Aptana plugin before, you might want to activate the built-in shortcut for uploading the current file you are working on. Since that shortcut (Ctrl + Shift + U) is already reserved by Eclipse itself (and the Aptana team probably did not think of that when writing their framework), you need to do the following steps: Window -> Preferences -> General -> Keys, then do a search for “Show Occurrences in File Quick Menu” (filter) and unbind these shortcuts from this rather useless command (Click -> Unbind Command).
You need to modify the Sync Manager (that is needed for uploading). Click Window -> Show View -> Other -> Aptana Standard Views -> Sync Manager. The configuration window will pop up at the bottom of Eclipse. Configuration is pretty much self-explanatory. Just make sure you have the FTP data for you symfony-enabled web server at hand.

Now you can start developing beautiful symfony applications with Eclipse! There are dozens of (video) tutorials about how to effectively use Eclipse out there, so you might want to have a look at these if you’ve never used Eclipse before (I absolutely recommend that, it will save you loads of time). To start a new project, select File -> New -> PHP Project, enter the necessary data and don’t forget to include the symfony library.

If you’re running you own server on localhost (a future tutorial will cover how to set one up with symfony enabled), another feature will come in quite handy as well: right-clicking on the project in your PHP Explorer and selecting Command Line Shell will start a shell with the project’s root folder. From there, you can start to use your symfony commands as usual.

Have fun developing symfony applications even quicker and easier!

Posted by & filed under Development, symfony.

Call to all developers:

Since this plugin is no longer being developed and is still using the old REST-interface, I’m looking into forking or developing a new Facebook plugin that uses the new OAuth protocol. Please contact me if you’re interested.

We‘re currently working on an extensive symfony (1.4) plugin that builds upon the new Graph API. Watch this blog for further updates!


We have just finished developing our first facebook application using symfony and the very useful sfFacebookConnectPlugin which can be downloaded from the SVN repository (or from here for those of you who don’t use SVN). Simply unpack it to the plugins/ folder of your symfony project.

 

But before you can use the sfFacebookConnectPlugin, you need to install sfGuard:

Installing and configuring sfGuardPlugin and sfFacebookConnectPlugin

Open the command line shell (cmd on Windows, PuTTy/bash on remote systems/linux), change to your project directory and type:

symfony plugin-install http://plugins.symfony-project.com/sfGuardPlugin

to install the plugin from the official symfony repository.

Now open the settings.yml in /apps/[myapp]/config and edit

all:
  .actions:
    login_module:           sfGuardAuth   # To be called when a non-authenticated user
    login_action:           signin     # Tries to access a secure page
    secure_module:          sfGuardAuth   # To be called when a user doesn't have
    secure_action:          secure    # The credentials required for an action
  .settings:
    enabled_modules:      [default, sfFacebookConnectAuth, sfGuardAuth]

Now open myUser.class.php in /[myapp]/lib and update the myUser class to extend sfFacebookUser:

class myUser extends sfFacebookUser
{
}

Add the following lines to the end of your routing.yml at /[myapp]/config to enable the signin and signout (optional):

sf_guard_signin:
 url:   /login
 param: { module: sfGuardAuth, action: signin }

sf_guard_signout:
 url:   /logout
 param: { module: sfGuardAuth, action: signout }

sf_guard_password:
 url:   /request_password
 param: { module: sfGuardAuth, action: password }

Now edit the [myapp]/config/app.yml with all the settings you have obtained from http://www.facebook.com/developers/apps.php:

# default values
all:
 facebook:
   api_key: ...
   api_secret: ...
   api_id: ...
   callback_url: [your callback url]
   app_url: http://apps.facebook.com/[your app]/
   redirect_after_connect: true
   redirect_after_connect_url: 'http://apps.facebook.com/[your app]/'
   connect_signin_url: '[url to your app]/sfFacebookConnectAuth/signin'

 sf_guard_plugin:
   profile_class: sfGuardUserProfile
   profile_field_name: user_id
   profile_facebook_uid_name: facebook_uid
   profile_email_name: email
   profile_email_hash_name: email_hash

 facebook_connect:
   load_routing:     true
   user_permissions: []

Next, you want to modify your sfGuardUserProfile schema (apps/[myapp]/config/schema.yml) to contain these 3 additional rows needed. Simply add them to the end of schema.yml:

sf_guard_user_profile:
 _attributes:      { phpName: sfGuardUserProfile }
 id:
 user_id:     { type: integer, foreignTable: sf_guard_user, foreignReference: id, required: true, onDelete: cascade }
 nickname:         { type: varchar(32), index: unique }
 first_name:       varchar(20)
 last_name:        varchar(20)
 birthday:         date
 facebook_uid:     varchar(20)
 email:            varchar(255)
 email_hash:       varchar(255)

Site note: Since the new Facebook UIDs are way bigger than integer could possibly store, we have decided to go with varchar here. The official README is outdated.


Clear your cache:

symfony cc

Publish your assets:

symfony plugin:publish-assets

And finally, rebuild your model and insert the generated SQL using the database settings you have provided in your /config/databases.yml:

symfony propel:build-model
symfony propel:build-sql
symfony propel:build-forms
symfony propel:build-filters
symfony propel:insert-sql

Using sfFacebookConnectPlugin

We called our module facebook and the layout fb. Of course these are just examples and you may adjust them to your own needs.

Here is our layout fb.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<?php use_helper('sfFacebookConnect') ?>
<?php include_http_metas() ?>
<?php include_metas() ?>
<?php include_title() ?>
<link rel="shortcut icon" href="/favicon.ico" />
</head>
<body>

<?php echo $sf_content ?>

<?php include_bottom_facebook_connect_script(); ?>

</body>
</html>

Next, a very basic actions.class.php:

<?php

/**
 * facebook actions.
 *
 * @package
 * @subpackage facebook
 * @author     Your name here
 * @version    SVN: $Id: actions.class.php 12479 2008-10-31 10:54:40Z fabien $
 */
class facebookActions extends sfActions
{
	/**
	 * Executes index action
	 *
	 * @param sfRequest $request A request object
	 */

	public function executeIndex(sfWebRequest $request)
	{
		sfFacebook::requireLogin();
		//get the user object
		$user = $this->getUser();

		// facebook user id
		$this->fb_uid = $user->getCurrentFacebookUid();
		// get or create user based on fb_uid
		$fb_user = sfFacebook::getOrCreateUserByFacebookUid($this->fb_uid);
	}

And finally, and example how to render a friends invite form in your indexSuccess.php:

<?php if ($sf_user->isFacebookConnected()): ?>

<fb:serverfbml style="width: 740px;">
	<script type="text/fbml">
        <fb:fbml>
        	<fb:request-form target="_top" action="[where to redirect after invite]" method="post" type="[name of your app]" content="[text the user will receive]&lt;fb:req-choice url=&quot;http://apps.facebook.com/[your app]/&quot; label=&quot;Accept!&quot;  " image="" invite="true">
        		<fb:multi-friend-selector cols="4" actiontext="[some text above the invite form]" />
	        </fb:request-form>
        </fb:fbml>
    </script>
</fb:serverfbml>

<?php else: ?>
<p>Ooops?</p>
<br />
<?php endif; ?>

I hope you enjoyed this tutorial!

P.S.: Thanks to Andrés for the hint!

P.P.S.: As outlined by Ben below:

The other thing which was an issue I found very hard to spot (I am still new to Symfony) is in the security.yml file in “modules/sfFacebookConnectAuth/config”, if you are using symfony 1.4 (I am not sure about other versions as I haven’t used them), you have to use “false” instead of “off” – if you find that the sfGuardUser record is being created, but the user is not being signed in, this is likely to be the problem. (I believe that this is a change in the syntax of YAML in newer versions).

<?php

/**
* facebook actions.
*
* @package quiz4fun
* @subpackage facebook
* @author Your name here
* @version SVN: $Id: actions.class.php 12479 2008-10-31 10:54:40Z fabien $
*/
class facebookActions extends sfActions
{
/**
* Executes index action
*
* @param sfRequest $request A request object
*/

public function executeIndex(sfWebRequest $request)
{
sfFacebook::requireLogin();
}

public function executeApplet(sfWebRequest $request)
{
sfFacebook::requireLogin();
//get the user object
$user = $this->getUser();

// facebook user id
$this->fb_uid = $user->getCurrentFacebookUid();
// get user based on fb_uid
$fb_user = sfFacebook::getOrCreateUserByFacebookUid($this->fb_uid);

// create a new session ID for authentication
$this->tmp_session = $this->tmpSession();
// write to db
$fb_user->getProfile()->setTmpSession($this->tmp_session);
$fb_user->getProfile()->save();

// nickname
$this->nickname = $fb_user->getProfile()->getNickname();
if(!$this->nickname OR trim($this->nickname) == ”)
{
// set nickname
$this->redirect(‘facebook/updateNickname?nick=fb_’.$this->fb_uid);
}
}

Posted by & filed under openSuse 11.1.

Out of the blue, our Vserver (openSuse 11.1) suddenly went mad. This all began with it denying SSH access. Then, after forcing a restart through the rescue system Strato provides, I could log on via shell again. Unfortunately, after a while, openSuse kept quitting any prompt with
-bash: fork: Not enough memory available
Read more »

Posted by & filed under Random thoughts.

Lately, I haven’t been too happy with how things went. That is not only due to me having to give up the walk to Portugal after just about a week (which was a pretty big defeat for myself), the way things went with some people this summer and some aims I didn’t achieve.

To add to that, I came across some people and bands that really impressed me. Why did they impress me? Because they seemed to know exactly what they were doing and what they were fighting for. They all had one thing in common, one thing that I only smiled at in the past: they were Straight Edge. Now some of you might have never heard this before or might not know what the hack that means.

Straight Edge mainly implies one thing: Live your life drug-free. No more tobacco, no more alcohol, no more drugs.
In the 90s vegetarianism/veganism was also added to the lifestyle and many people associate that with Straight Edge at first, though it’s not necessarily part of it. It can also imply standing for animal rights, giving up promiscuity, and, coming from the hardcore punk movement, a certain political attitude.

I’m gonna give it a try. While the moderate way might be the right thing for many people, I have always been a bit more radical. I have found that doing things by halves just doesn’t work for me. Even though Straight Edge is often called a lifetime commitment, I’m gonna give it a try till christmas for now and try if it’s the right thing for me. Hope I’ll get some support by my friends & family. I’m pretty sure I can do it. Updates on this to follow!

X marks the spot… two X’s mark Straight Edge…
So long, xBurgix ;)

straight edge singer