Blog Posts

Touring North America

After pretty much exactly a month I have concluded my north american "tour" featuring speaking at Confoo in Montreal, a PHP UG meeting on Boca Raton and last, but definitely not least DrupalCon Denver. In between relaxing at my parents place in Florida. Lets me review the experience in chronological order.

I had previously attended Confoo in 2008 where it was still very much focused on PHP developers. These days Confoo aims to cover all web technologies all the while also including non-developers in some tracks. My first talk was on PHPCR, while everyone back home was celebrating Liip Day. This usually attracts a smaller crowd that have both experienced the pains of todays CMS and are ready to look beyond. I always ask the audience at the end of they think that PHPCR looks relevant to them and pretty much everyone raised their hand. The other talk I gave was a presentation on Symfony2. I came with zero slides, but only my editor, the shell and a browser to show people the guts of Symfony2 in its raw beauty. I did this before at PHP Conference in Mainz and I think I am improving in terms of finding the right pace and order of topics. However a single 60 min slot is just too short, so if I am going to submit this talk in the future I will need to ensure I have 120 min. In general interested in Symfony2 with all around at the conference. It seemed to be the dominant PHP framework discussed which surprised me, since I thought that Symfony2 was struggling in North America, but maybe it isn't or maybe its just struggling in the USA.

My next speaking engagement was at the South Florida PHP UG. Pablo from ServerGrove suggested that I leverage the fact that I will be in Florida to give a talk. I also held my PHPCR talk there to quite a diverse group. Most people were using home grown CMS solutions or heavily customized solutions based on other CMS. Once again I felt like in the end people really saw the value in having a mature and consistent storage API as well as the benefits of collaboration across CMS for implementing this.

My next stop was Denver for DrupalCon. I was quite excited to be going because I had invested quite a bit of my personal time as well as my Liip sponsored weekly "do what you want on OSS" day in supporting the WSCCI initiative for Drupal8. In a way its strange, since I have never done a Drupal project in my life. Furthermore I am one of the lead people behind the Symfony CMF initiative. However it is simply an exciting opportunity for the entire PHP world, heck given that Drupal runs close to 2% of all websites in the world, its should be exciting for quite a large portion of people on this planet! Furthermore I know that collaboration with Drupal will have benefits for Symfony2 as well as the CMF project as the will continue to push the common code pieces.

The first talk I did together with Fabien Potencier. He has submitted a talk on the Symfony2 components, which Dries announced the day before at the keynote would become a key piece in Drupal8's core architecture. Since I was involved in the initial evaluation of Symfony2 for Drupal, Fabien figured it would make sense if I start things off with a little introduction about why this development could be beneficial for the Drupal community. Needless to say the attendance was jaw-dropping: This was easily the biggest presentation on Symfony2 .. ever .. at a DrupalCon no less! During the entire conference people walked up to me expressing their excitement and so I just want to pass along the countless "thank you for Symfony2" I heard to the Symfony2 community. Speaking of which, many people also asked me why the Symfony community cares so much about Drupal? To which I replied, we realize that this will mean we have a lot more users which will lead to more developers, leading to more code contributions. By the way, DrupalCon Denver has over 3000 attendees, I have been to plenty of PHP conference that had less attendees than were present at the hack day on the day following the conference. Of course we also realize that with Drupal8 using the HttpKernel, it will be a breeze to integrate Drupal8 and Symfony2 applications. This is something many of us currently have to deal with already.

My other talk was a core conversation together with Damien Tournoud about defining the next steps towards a documented oriented storage API for Drupal. I think this makes me the first DrupalCon core conversation speaker to never have installed Drupal. I started things off again with a 15 min intro to PHPCR. Then Damien discussed how to refactor the current Entity and Field API's to a unified API that should eventually be replaced with PHPCR. The goal is to get things far along with Drupal8 that it would be possible to provide a contrib module that would already switch things to PHPCR and at the latest with Drupal9 PHPCR would become the native storage API. We would of course have to push the Doctrine DBAL implementation of Jackalope quite a bit to be able to handle larger use cases in order to make this a viable option for Drupal. As this was a core conversation we then had about 30 min of Q&A where to my surprise no tomatoes were thrown. Instead all attendees seemed to be quite excited and so it seems like things are pretty much on track to get PHPCR into Drupal!

I cannot express how huge this is as the only way I could imagine I could would be with a video of me doing a back flip, but I can't do back flips. With Dries emphasis on mobile and content authoring which was also pushed in Luke's mobile first keynote I think that Drupal is well on track to become the first big CMS to adopt the Decoupled CMS vision that Henri and I have been shouting from the roof tops for a while now. I also discussed CMIS briefly during the talk and then later on with a guy from Alfresco (darn forgot the name) and then again at the hack day with several Drupal core people. We might look into providing an implementation that can expose any PHPCR repository via the CMIS protocol, similar to what Apache Chemistry does for JCR. For an introduction to CMIS see this blog post by Jeff.

Needless to day I am thrilled with what is going on with Symfony2, Drupal and of course PHPCR. Really enjoyed each speaking opportunity and I want to especially thank Liip for funding my travel expenses to Denver as core conversation speakers need to pay for travel and hotel on their own.

Related Entries:
- Paris PHPCR meetup
- Doctrine PHPCR-ODM now handles versioning
- News for the symfony2 cmf: Second PHPCR implementation, hackday announcement and PHPCR to become "official"
- Multilanguage support for Doctrine PHPCR-ODM
- How to manage patching a github hosted repo

Comments [1]

Table Inheritance with Doctrine

Introduction

Lately we had several projects where we had to store in a database very different items that shared a common state.

As an example take the RocketLab website you are reading: Events and BlogPosts are aggregated in the LabLog list as if they were similar items. And indeed they all have a Title, a Date and a Description.

But if you get the detail page of an Event or a BlogPost you can see that they actually don't contain the same information: a BlogPost contains essentially formatted text when an Event contains more structured information such as the place where the event will take place, the type of event it is, if people need to register to attend, etc..

Still we have to access those entities sometimes as similar items (in the LabLog list) or as different items (in the events list and in the blog posts list).

Naïve database model

Our first idea, and it was not that bad, Drupal does just the same, was to have a database table with the common fields, a field containing the type of item (it's either an event or a blog post) and a data field where we serialized the corresponding PHP object. This approach was ok until we had to filter or search LabLog items based on fields that were contained in the serialized data.

Indeed SQL does not know anything about PHP serialized data, thus you cannot use any of it's features on that data.

So how do you get all the LabLog items that are Events, happen in April 2012 and are "techtalks"? The only way is to go through all the Events records of April, unserialize the data and check if it's a techtalk event. In SQL you would normally only do a single request to find those items.

A better database model

There is a better way to model this in a database, it's called table inheritance. It exists in two forms: single table inheritance and multiple table inheritance.

Multiple table inheritance

Multiple table inheritance requires to use three tables instead of a single one. The idea is to keep the common data in a "parent" table, which will reference items either in the Event table or in the BlogPost table. The type column (called the discriminator) helps to find out if the related item should be searched in the Event table or in the BlogPost table. This is called multiple table inheritance because it tries to model the same problem as object inheritance using multiple database tables.

Multiple table inheritance

When you have a LabLogItem you check the type field to know in which table to find the related item, then you look for that item with the ID equals to related_id.

Single table inheritance

Alternatively the same can be modelled in a single table. All the fields are present for all the types of LabLogItem but the one that do not pertain to this particular type of item are left empty. This is called single table inheritance.

Single table inheritance

Single or multiple table inheritance

The difference is really only in how the data is stored in the database. On the PHP side this will not change anything. One may notice that single table inheritance will promote performance because everything is in a single table and there is no need to use joins to get all the information. On the other hand, multiple table inheritance will allow a cleaner separation of the data and will not introduce "dead data fields", i.e. fields that will remain NULL most of the time.

Table inheritance with Symfony and Doctrine

Symfony and Doctrine make it extremely easy to use table inheritance. All you need to do is to model your entities as PHP classes and then create the correct database mapping. Doctrine will take care of the hassle of implementing the inheritance in the database server.

Please note that the code I present here is not exactly what we use in RocketLab; we are developers and as such we always have to make things harder. But the idea is there...

The parent entity

In the case of RocketLab we created a parent (abstract) entity, called LabLogItem, that contains the common properties.

/**
 * This class represents a LabLog item, either a BlogPost or an Event.
 * It is abstract because we never have a LabLog entity, it's either an event or a blog post.
 * @ORM\Entity
 * @ORM\Table(name="lablog")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap( {"event" = "Event", "blogpost" = "BlogPost"} )
 */
abstract class LabLogItem
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="date")
     */
    protected $date;

    /**
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @ORM\Column(type="text")
     */
    protected $description;

    /***** Getters and setters *****/

    public function getId()
    {
        return $this->id;
    }

    public function setDate($date)
    {
        $this->date = $date;
    }

    public function getDate()
    {
        return $this->date;
    }

    // And so on...
}

There are several things to note about the mapping:

  • @ORM\InheritanceType: indicates that this entity is used as parent class in the table inheritance. This example uses single table inheritance, but using multiple tables inheritance is as easy as setting the parameter to "JOINED". Doctrine will create an manage the unique or multiple database tables for you !
  • @ORM\DiscriminatorColumn: indicates which column will be used as discriminator (i.e. to store the type of item). You don't have to define this column in the entity, it will be automagically created by Doctrine.
  • @ORM\DiscriminatorMap: this is used to define the possible values of the discriminator column as well as associating a specific entity class with each type of item. Here the discriminator columns may contain the string "event" or "blogpost". When its value is "event" the class Event will be used, when its value is "blogpost", the class BlogPost will be used.

Basically that's the only thing you need to use table inheritance, but let's have a look at the children entities.

The children entities

We have two regular entities to model the events and blog posts. Those entities extend LabLogItem.

/**
 * Represent a blog post item.
 * Note that this class extends LabLogItem
 */
class LabLogItemBlog extends LabLogItem
{
    /**
     * @ORM\Column(type="text")
     */
    protected $content;

    /***** Getters and setters *****/

    public function getContent()
    {
        return $this->content;
    }

    public function setContent($content)
    {
        $this->content = $content;
    }
}

/**
 * Represent an event item.
 * Note that this class extends LabLogItem
 */
class LabLogItemEvent extends LabLogItem
{
    /**
     * @ORM\Column(type="string")
     */
    protected $eventType;

    /**
     * @ORM\Column(type="string")
     */
    protected $location;

    /**
     * @ORM\Column(type="boolean")
     */
    protected $requiresRegistration;

    /***** Getters and setters *****/

    public function getEventType()
    {
        return $this->eventType;
    }

    public function setEventType($type)
    {
        $this->eventType = $type;
    }

    // And so on...
}

There is not much special in the children entities. An important thing to note is that the common fields defined in the parent entity LabLogItem SHOULD NOT be repeated here. Also you may notice that there is no annotations in the children such as @ORM\Entity to indicate that they are entities. Indeed they will inherit the annotations of LabLogItem and become entities.

From now on, when you create a PHP object of type Event and ask the entity manager to persist it, Doctrine will automatically do the complex work for you. From the developper point of view, Events and BlogPosts are just entities like any other.

It's easy to do operations on items which you don't know exactly the type:

$item = $entityManager->getRepository('RocketLabBundle:LabLogItem')->findOneByDate($someDate);

// Here we don't know exactly whether $item contains a blog post or an event...

if ($item instanceof Event) {
    // Then it's an Event
    echo $item->getEventType();
} else {
    // Otherwise it's a BlogPost
    echo $item->getContent();
}

But, if you know the type of item you are using you still can use them as regular entities:

$item = $entityManager->getRepository('RocketLabBundle:Event')->findOneByDate($someDate);

//  We have searched the Event entity repository so what we get in $item MUST BE an Event
echo $item->getEventType();

Conclusion

As you can see above using table inheritance with Symfony and Doctrine is very easy. It's just a matter of creating the parent class and the correct mapping. Furthermore you can switch from single to multiple table inheritance by modifying one line of code.

This technique should be used whenever you need to store items with a common state but that are very different in their nature.


Comments [5]

CMF editor: overview, screencasts and live demo

I will present you the CMF editor and some of its key features. It's a content editor for the CMF project that we designed at Liip AG to pave the way to better experiences in this somehow traditionnal field.

We didn't start reiventing the wheel, we wanted to create an editor based on the last technologies, leveraging the 'decoupled' content management approach to improve the user's efficiency and also to improve the fun while using a backend application. We based our work on some great open source components such as VIE and Hallo.

After having a first version we participated to the IKS semantic UX contest happening last winter. Winning the prize allowed us to add semantic functionalities in our product.

In the last weeks we also merged our work with the CreateJS project so that we would all work under the same project and share some important features that we did separately.

To give you a better overview of the software we built here is a list of the main features:

-  Edit in place: The editor doesn't live in the back of your website, it's right here on the front of your pages.

-  Rich but simple interface: The interface is very simple yet very powerful. For example, you can drag and drop your images in your content and directly see how it will look like or you don't have to worry about loosing your content as auto-saving and local recoveries are included.

-  Extendable: We wrote some plugins to pave the way, but the idea is that one can write new plugins for the users to have the right tools for each specific business cases. The interface has been designed to handle extensions and keep a uniform feeling even with plugins made by different people.

-  Semantic: We built many semantic functionalities thanks to IKS.

-    Tagging suggestions based on your content

-    Automatic tagging of assets to keep highly linked and qualitative content in your system

-    Automatic article relationship through auto tagging of content

-    Automatic external links suggestion based on your actual tags and semantic services

To present the editor in a more effective way, I created some Screencasts to show the main features of the editor and how to use them.

I hope you will get interested in this project and that you found this post interesting.

Further links:

-  The screencasts are on youtube.

-  Link to the live demo.

-  Link to createJS.

-  If you want to know more about the CMF project.

-  The live demo called sandbox is on Github.

Kind regards,

Loïc Schülé

Read whole post

Comments [3]

Doctrine PHPCR-ODM now handles versioning

The Doctrine PHPCR-ODM allows you to easily map your PHP objects onto content repository nodes. Since last week, the PHPCR-ODM leverages the versioning support of PHPCR in the ODM layer. This gives your application a very simple way to work with versioned content.

The versioning is pretty simple to use. DocumentManager::find() will always give you the current version of the document. The DocumentManager provides access to old versions with getAllLinearVersions($document) and findVersionByName($class, $id, $name). The later gives you a detached document with the values it had when the specified version was created. Using checkin/checkout/checkpoint you generate versions. Finally there is restoreVersion and removeVersion to restore the document to an old version resp. to remove something from the version history.

An example should help understanding the workflow:

$article = new Article();
$article->id = '/test';
$article->topic = 'Test';
$dm->persist($article);
$dm->flush();

// generate a version snapshot of the document as currently stored
$dm->checkpoint($article);

$article->topic = 'Newvalue';
$dm->flush();

// get the version information
$versioninfos = $dm->getAllLinearVersions($article);
$firstVersion = reset($versioninfos);
// and use it to find the snapshot of an old version
$oldVersion = $dm->findVersionByName(null, $article->id, $firstVersion['name']);

echo $oldVersion->topic; // "Test"

// find the head version
$article = $dm->find('/test');
echo $article->topic; // "Newvalue"

// restore the head to the old version
$dm->restoreVersion($oldVersion);

// the article document is refreshed
echo $article->topic; // "Test"

// create a second version to demo removing a version
$article->topic = 'Newvalue';
$dm->flush();
$dm->checkpoint($article);

// remove the old version from the history (not allowed for the last version)
$dm->removeVersion($oldVersion);

Related Entries:
- Multilanguage support for Doctrine PHPCR-ODM
- News for the symfony2 cmf: Second PHPCR implementation, hackday announcement and PHPCR to become "official"
- Touring North America
- Paris PHPCR meetup
- Progress on PHPCR with a hackday

Comments [0]

Paris PHPCR meetup

 Last weekend I went to Paris to attend the Paris PHPCR meetup with about a dozen other people at the offices of CommerceGuys. Things started off with a short personal intro round, followed my presentations on PHPCR and PHPCR ODM. During the presentation there was a fair bit of discussion about the different available PHPCR implementations as well. Afterwards things split up in multiple groups working on integration of PHPCR with the Sonata Symfony2 Bundles, but also hacking on the Doctrine DBAL transport for Jackalope.

Overall I think the meetup managed to get quite a few new people up to speed with PHPCR, but more importantly was a great way to socialize with people around the common interest of CMS technology. Its always more efficient to communicate via email/irc etc after a bit of face time (not the apple kind). :)

As a bonus we even got progress on the code side of things and maybe got one step closer to bringing PHPCR to Drupal8, though its of course still too early to pop the champagne. Damien gave me the following topics to look into in regards to potential Drupal adoption:

- facetting

- query across version labels as a way to handle content staging workflows

- Jackalope Doctrine DBAL needs to be able to handle 10k+ documents with full text search on a shared hoster

- locking (pessimistic/optimistic locking, SELECT .. FOR UPDATE)

On facetting it should be noted thar I have already brought this topic up in the JSR-333 list.

Querying and versioning is something I need to look into, since I am very unsure if there is any support here. I will also try to find time to checkout HippoCMS and other JCR CMS and how they handle this.

For full text search in the Doctrine DBAL transport we discussed approaches briefly, but things might go in the direction similar to the full text search provided in Doctrine 1.x, which apparently is similar to how things are in Drupal today. Aside from this I am waiting for Damien to send a bunch of bug fixes that he worked on during the meetup.

On the topic of locking we are currently making progress in Jackalope, so I hope we can address the concerns soon.

Related Entries:
- Touring North America
- Doctrine PHPCR-ODM now handles versioning
- News for the symfony2 cmf: Second PHPCR implementation, hackday announcement and PHPCR to become "official"
- Multilanguage support for Doctrine PHPCR-ODM
- How to manage patching a github hosted repo

Comments [0]

What Liip did after winning the IKS semantics UX contest

As you maybe have heard, we won the IKS Semantics UX contest a few weeks ago (see this and this for more details). We of course we're not lazy in the meantime and integrated Apache Stanbol into this editor.

Loïc wrote a little summary on the IKS blog what we already did and what's coming in January 2012. Go and read it here. The most important part: There's a hackaton for merging all this with the excellent CreateJS (which was on Hacker News lately) from 5 to 7 January at our Liip office in Zurich. You're all welcome to take part, more details and subscription at lanyrd.com/2012/createjs-hackathon/

Related Entries:
- Symfony CMF hackday october 22nd in Cologne
- A frontend editor for Symfony2 CMF with the help of VIE
- Progress on PHPCR with a hackday
- Doctrine PHPCR-ODM now handles versioning
- Multilanguage support for Doctrine PHPCR-ODM

Comments [0]

Multilanguage support for Doctrine PHPCR-ODM

Over the last weeks, Dan, Brian and myself worked on adding translation capabilities to Doctrine PHPCR-ODM. PHPCR-ODM is an object - document mapper for the php content repository (PHPCR). Thanks to the Liip Ecostar process, we got funding to do this during work time.

How does it work?

Using persistTranslation($document, $locale) or persist($document) with the @Locale annotation allows to store several copies of the "same" document in different languages. You update the document for the next language and then persist that translation too. Using find() to get a translated document, the LocaleChooserStrategy class will find the best (according to its implementation - might look at session locale, browser preferences, user account settings, ...) available translation for a document. And using findTranslation() you can explicitly specify which language you want.

There are two translation strategies available: Store translated fields in a separate namespace as properties of the same node, and namespaced child nodes per locale with the translated properties in them. You can add your own strategies with the DocumentManager::addTranslationStrategy() method. Translation always happens on a document level, not on individual fields to keep performance reasonable.

Our translation strategies use a namespace to avoid collisions with other attributes resp. child nodes. In order to use multilanguage, set up the console and run

php bin/phpcr doctrine:phpcr:register-system-node-types
.

When using findTranslation, the existing document instance is updated rather than a new one created. Otherwise we could get into non-deterministic situations when you update non-translated fields on two objects.

A complete example how using the translations looks like, using the default configured LocaleChooser:

use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;

/**
 * @PHPCRODM\Document(alias="translation_article", translator="attribute")
 */
class Article
{
    /** @PHPCRODM\Id */
    public $id;

    /**
     * The language this document currently is in
     * @PHPCRODM\Locale
     */
    public $locale = 'en';

    /**
     * Untranslated property
     * @PHPCRODM\Date
     */
    public $publishDate;

    /**
     * Translated property
     * @PHPCRODM\String(translated=true)
     */
    public $topic;

    /**
     * Language specific image
     * @PHPCRODM\Binary(translated=true)
     */
    public $image;
}


$localePrefs = array(
    'en' => array('en', 'fr'),
    'fr' => array('fr', 'en'),
);

$dm = new \Doctrine\ODM\PHPCR\DocumentManager($session, $config);
$dm->setLocaleChooserStrategy(new LocaleChooser($localePrefs, 'en'));

// then to use translations:

$doc = new Article();
$doc->id = '/my_test_node';
$doc->publishedDate = new \DateTime();
$doc->topic = 'An interesting subject';
$doc->image = fopen('english.jpg');

// Persist the document in English
$this->dm->persistTranslation($this->doc, 'en');

// Change the content and persist the document in French
$this->doc->topic = 'Un sujet intéressant';
$doc->image = fopen('english.jpg');
$this->dm->persistTranslation($this->doc, 'fr');

// Flush to write the changes to the phpcr backend
$this->dm->flush();

// Get the document in default language (English if you bootstrapped as in the example)
$doc = $this->dm->find('Doctrine\Tests\Models\Translation\Article', '/my_test_node');
echo $doc->topic;

// Get the document in French (updates the existing document)
$this->dm->find('Doctrine\Tests\Models\Translation\Article', '/my_test_node', 'fr');
echo $doc->topic;

What was added?

The complete overview is in the pull request. Just a summary:

  • New annotation options:
    • translator=attribute|child|your_own is a new attribute for the @Document annotation, to mark a document as being translated and specify how translations are to be stored
    • @Locale makes a class property hold the locale the document is currently translated to.
    • translated=true is a new attribute for all properties to mark the String, Number, Binary and so on as being translated.
  • TranslationStrategy is used for the translator attribute of the document. Default strategies for attribute and child exist.
  • LocaleChooserStrategy is used to determine what language matches best for doing language fallback, with the possibility to do language fallbacks based on your self defined logic. The default strategy is configurable with an ordered list of locales per requested locale
  • DocumentManager::persistTranslation($document, $locale) save document in that language
  • DocumentManager::findTranslation($className, $id, $locale) load a document in the specified locale (instead of the default one)
  • DocumentManager::getLocalesFor($document) (get the list of locales this document currently exists in)
Related Entries:
- Doctrine PHPCR-ODM now handles versioning
- News for the symfony2 cmf: Second PHPCR implementation, hackday announcement and PHPCR to become "official"
- Touring North America
- Paris PHPCR meetup
- What Liip did after winning the IKS semantics UX contest

Comments [1]

How to manage patching a github hosted repo

Here at Liip we obviously try to reuse all the good stuff in the Symfony2 and PHP community. So instead of reinventing the wheel when we find that a feature is missing we just fork, patch and submit our changes upstream. So far so simple.

The problem is of course that this entire process takes time during which our projects need to move on. As a result there is a time period where most likely our project will need to use the fork. I must say I am still not entirely happy with the workflow I am going to describe here. So it is definitely still a work in progress and needs refinement and we are only partially using the below described approach. Hopefully feedback to this post will get us to a perfected approach.

1) fork the project

Make sure to fork to an organization that co-workers can reach. Usually we fork to the Liip organization. If we have client developers on the team we fork to the clients organization.

2) update the description of the fork

Make sure to declare this fork as transient, so that nobody gets the idea that this fork will stick around. Github's repo description can be modified without changing anything in the repository.

3) create a feature branch with your changes

Committing to master would seriously break the workflow. Never assume you will only need one feature changed and mixing features will make it harder to get your features merged upstream. Never assume that upstream will accept your patch, they might go with someone else's patch. Never assume that your PR actually makes sense, sometimes after submitting your PR you realize that it was actually a bad idea and you should have taken a different approach.

4) create a ticket on your fork for the branch

This ties in with 2). Anyone using this branch should subscribe to that ticket. The ticket should also reference the PR. This way it is later easily possible to alert anyone that cares that the PR has been merged upstream and that you are going to remove the branch in X number of days.

5) submit a PR

6) update your project to point to your feature branch

At this point you need to make sure that all relevant people from your project are subscribed to the branch ticket.

6) once the PR is merged switch point your project back to the original repo

7) update the branch ticket that you are about to remove the branch in X number of days

8) remove the feature branch

9) if there are no more feature branches, remove the repo

Since nobody should depend on your master it should be safe to remove the repo once all feature branches are removed.

Note in some cases you might need multiple features at once. In that case create a separate feature branch for each feature and create another feature branch that combines all the features you need.

Also its best to make sure that upstream addresses your PR in a timely manner. Otherwise more and more people will start relying on your fork, you start to forget what it was about and more importantly, you might become incompatible with upstream. Making sure that your PR has a good description, tests and documentation will go a long way to getting your PR merged sooner rather than later. A friendly nudge now and then can also help to get things back on the radar (*nudge* Kris *nudge* *nudge*).

If all else fails and you are unhappy with the way upstream handles the merging or you want to take things into a different direction, do a for "real" fork. At this point you can start merging into master, but be aware that getting upstream features will now become potentially messy. So far we have only done this in one case where we forked the AvalancheImagineBundle to the LiipImagineBundle since we need additional flexibility that Bulat didn't want to add to his bundle.

Related Entries:
- Integrating Magento into Symfony2
- Touring North America
- Doctrine PHPCR-ODM now handles versioning
- Paris PHPCR meetup
- Multilanguage support for Doctrine PHPCR-ODM

Comments [1]

Symfony Day Cologne and CMF Hackday

 Single track conferences like Symfony Day always tend to have a more intimate feeling which make them all the more enjoyable in my opinion. While the talks were certainly interesting, I personally go to conference to use the opportunity to meet all the IRC/github accounts in person. Its more efficient to move discussion forward, get a feeling for how the given person thinks and just to build up some shared fun experiences outside of "just" coding. Symfony Day delivered all of that and more really. As a case in point about the more check out the "Knplabs Boys" (note, only one actual KnpLab employee was on stage). Just a pitty that people like Bernhard, Jon, Kris and Johannes didn't show their faces. The conference itself was also very well organized and the wifi was working mostly :)

To me the more important event was the hack day on the following day. It would be such a waste to not leverage having lots of smart developers in one place for some actual code hacking. This hack day started slow, or at least it felt like it. But when I looked at the progress that was made during the day I was quite blown away. PHPCR ODM got a lot of love from Uwe for "relation" annotations. Thanks to insights by Stof the ChainRoutingBundle was also pushed forward by David, which is really a key piece to solving the need for dynamic routes in the CMF. Mean while I had the opportunity to introduce I guess a dozen people to PHPCR and the Symfony2 CMF. Thomas demoed SonataPageBundle and Fabrice also demoed his Radiant CMS port Roger. Thomas also worked on merging ODM support into SonataAdminBundle. Both will will hopefully soon be integrated with PHPCR. Jordi and Nils also made a lot of progress on Composer and all the while Henri and Igor jump started DNode support for PHP. Stof worked on some big improvements to the SecurityBundle .. and I am sure I am missing other stuff that happened during the hack day.


Comments [0]

Symfony CMF hackday october 22nd in Cologne

Following the Symfony Day Cologne 2011, we will do a hackday on the Symfony Content Management Framework in Cologne, Germany. Interlutions kindly provides room for the hackday. We will start on Saturday October 22nd, at 10 a.m. and hack until they have to throw us out (or we decide to leave of our own accord). We will discuss the progress of the efforts to implement things and update the roadmap, then hack along on the various topics.

If you know you will be there, please sign up in the CMF Wiki. If you just drop in spontaneously, its ok too of course.

For those not following the mailing list closely, i try to summerize the current state:

  • Menu and navigation: There is work in progess on the MenuBundle and the ChainRoutingBundle that are part of the symfony-cmf repository.
  • Editor: At Liip, we started to implement Frontend Editing with VIE this week.
  • Tree and PHPCR browser: Ideato started working on a TreeBundle and the PhpcrBrowserBundle [note that the browser repository will probably be renamed at some point and the link will change]
  • Admin Backend: Help wanted
  • Asset Management: Help wanted
  • and some more, see the Roadmap

Hope to see you in cologne or read you on the mailinglist symfony-cmf-devs.

Related Entries:
- What Liip did after winning the IKS semantics UX contest
- A frontend editor for Symfony2 CMF with the help of VIE
- Progress on PHPCR with a hackday
- Doctrine PHPCR-ODM now handles versioning
- Multilanguage support for Doctrine PHPCR-ODM

Comments [0]

Next1-10/28