SociallyNotable: Amazon.com Affiliate Site
March 19th, 2011
A little side project of mine, SociallyNotable.com, that I built using Symfony2 and the Doctrine MongoDB ODM is starting to get a pretty regular stream of traffic each day. It is not a lot, but I can see it steadily increase as Google slowly indexes all the content. It was an interesting project and a fun one because of the amount of data you gather searching Twitter for tweets with links to Amazon.com products. It is also interesting watching the trends and seeing what products are the most popular each day. The site is pretty simple, you can see past daily deal, watch a live stream of the products that people are tweeting right now, browse all products, or register for daily e-mail notifications of the most popular products at the end of each day. You can even use the site to generate random popular gifts to give to your friends for birthdays, holidays, etc.
The site was built as an experimental playground for myself and uses the following technologies:
- Ubuntu
- nginx
- supervisor
- PHP
- MongoDB
- Symfony2
- Doctrine MongoDB ODM
Posted in: Doctrine, MongoDB, Open Source, PHP, Symfony2
Tags: affiliate, amazon, mongodb, odm, php
Keep your Kitchen Sink Clean
March 18th, 2011
When programming in any language, you must remember to keep your kitchen sink clean and do the dishes regularly!
* Image courtesy of Jeremy Mikola
Posted in: PHP
Tags: php, programming, technical debt, testing
Getting married and buying a new house
March 17th, 2011
Yep, it’s true! I am getting married to the love of my life, Megan Byrd! and we are currently shopping for a new house for us to start our lives in together. I bought my first house when I was 19 and I can’t believe I’ve been living here for almost 7 years now! It is time to move on to a new place and rent out our current house.
Buying a new house is an exciting ride. It has been up and down so far and we have already put in an offer on a house we really liked. Unfortunately, another offer was made and we did not get the house. So, we’ve started looking again and I think this time we’ll find something that we like even better!
Posted in: Life
Tags: house, marriage
MongoDB Tailable Cursors
March 16th, 2011
Tailable cursors are a cool feature of MongoDB. It allows you to setup scripts that run forever and are constantly processing new data that gets inserted to the collection. You need a capped collection in order to tail a cursor so just create a new collection and make sure it is capped to a size you can specify:
> db.createCollection("my_collection", {capped:true, size:100000})
Now you can tail a cursor in your favorite language. I have a few examples of the same script in PHP, Ruby, Python and Perl!
PHP
<?php $mongo = new Mongo(); $db = $mongo->selectDB('my_db') $coll = $db->selectCollection('my_collection'); $cursor = $coll->find()->tailable(true); while (true) { if ($cursor->hasNext()) { $doc = $cursor->getNext(); print_r($doc); } else { sleep(1); } }
Ruby
db = Mongo::Connection.new().db('my_db') coll = db.collection('my_collection') cursor = Mongo::Cursor.new(coll, :tailable => true) loop do if doc = cursor.next_document puts doc else sleep 1 end end
Python
By Robert Stewart:
from pymongo import Connection import time db = Connection().my_db coll = db.my_collection cursor = coll.find(tailable=True) while cursor.alive: try: doc = cursor.next() print doc except StopIteration: time.sleep(1)
Perl
By Max
use 5.010;
use strict;
use warnings;
use MongoDB;
my $db = MongoDB::Connection->new;
my $coll = $db->my_db->my_collection;
my $cursor = $coll->find->tailable(1);
for (;;)
{
if (defined(my $doc = $cursor->next))
{
say $doc;
}
else
{
sleep 1;
}
}
If you want to provide the same example in another language please add it in the comments and I’d be glad to include it here!
Posted in: MongoDB, PHP
Tags: mongodb, php, ruby
MongoDB Hosting by ServerGrove
March 15th, 2011
Recently I partnered with ServerGrove to help bring a new product to the market for MongoDB hosting. The service aims to be a highly scaleable, fast and easy solution for MongoDB hosting. The service features a pay for usage billing structure and a fully featured user interface for managing everything related to your shared and dedicated MongoDB instances. Below are a few highlights of the features the service will provide.
Features
- Free, Shared and Dedicated Options
- UI for managing databases, collections, documents, backups and much more.
- Easy to get started with free option and connect to your MongoDB servers remotely. Great for development!
- Pay for usage only.
- Tight integration with the existing ServerGrove shared and VPS web hosting options.
We are currently under heavy development integrating the MongoDB hosting with the ServerGrove infrastructure and the awesome already existing control panel. You can sign up for a beta invite at mongodbhosting.com and we’ll let you know when the service is live and ready for you to test with the FREE option!
Posted in: MongoDB, ServerGrove
Tags: hosting, mongodb, servergrove
Tips on Being Successful in Open Source
February 28th, 2011
This morning I got an e-mail from someone asking for some pointers on how to build a successul open source project. It’s a difficult question to answer. In the end I think it comes down to a lot of things, but mainly it is being consistent and active. I responded to him with some of my thoughts and when I was done I practically had a blog post so I decided flesh it out a little more and post it here.
Identity
First, it is extremely important for your project to have a name and an identity. Just pick a word, anything, something is better than nothing. Then pick some colors and slice up a logo in Photoshop.
Source Control
You must use some kind of source control. I recommend using GitHub as it will help to build the community around your project and generate contributions.
Mailing Lists & IRC
Next, setup a mailing list using Google Groups and create an IRC channel on the irc.freenode.net network. Now you have a way to communicate with your users and contributors!
Setup a Website
Once you have your identity, your code publicly available and a way to communicate with your users you need a website to organize all the information about your project. I recommend a blog, documentation, information about your community, how to contribute, how to download your code, release/download information, etc.
Social Networking
I think leveraging social networking is also a big part of connecting with your users. Create a Twitter account for your project and announce updates there. When you are developing and working on your project, be sure to let your users know what you are up to. Be active and passionate about what you do and your users will more likely connect with you and help contribute to building a great open source project.
Release Early and Release Often
In the early days of an open source project you need to release early and release often. The project is new, and the users know that so the project needs to show that it is active and moving fast in order for developers to consider using your project. As your project matures, and you have stable versions users can rely on, then you can consider throttling down the frequency of releases. Get your users new stuff fast!
Maintenance
After you have your project ground work done, you need to maintain your project and stay active. If you do not maintain your project, then it will die a slow death. Frequently write blog posts about new developments, new versions, updates to documentation, use cases and example tutorials, etc. This will get your users coming back to your site and seeing the new stuff you are working on and will be more likely to use and or contribute to your library.
I hope this helps someone with getting a new open source project off the ground or sparks someones interest to open source something today!
Posted in: Open Source, PHP
Tags: oss, php, software
Changing Jobs
October 28th, 2010
For the last two years I have worked full-time for Sensio Labs and it has been an awesome experience to get to work with the lead developer of The Symfony Project, Fabien Potencier. Working with the Doctrine team we accomplished many things, three major Doctrine 1 releases, integration with several popular development frameworks such as Symfony, a published and printed guide to Doctrine, the expansion of the Doctrine umbrella to many different projects including the new Doctrine2 ORM, MongoDB and CouchDB ODM. I’ve gotten the chance to travel to several different countries and talk about Doctrine and Symfony. I definitely feel very lucky. I have Fabien to thank for everything as he dedicates his time and money to open source and I don’t think most people really truly understand and appreciate what he gives.
What is next?
On November 1st I start a new full-time job with OpenSky where they use Symfony2, Doctrine2 MongoDB ODM and ORM in production! I am excited to help build and improve the business but also to continue building great open source tools along the way. It is a good opportunity to help really improve Symfony2 and Doctrine2 by having first hand experience building a large product with it. I look forward to the next few years and what evolves both on the business side and in the PHP open source world!
Posted in: Uncategorized
Tags: job
Blending the Doctrine ORM and MongoDB ODM
August 25th, 2010
Since the start of the Doctrine MongoDB Object Document Mapper project people have asked how it can be integrated with the ORM. This blog post demonstrates how you can integrate the two transparently, maintaining a clean domain model.
This example will have a Product
that is stored in MongoDB and the Order
stored in a MySQL database.
Defining our Document and Entity
First lets define our Product
document:
<?php namespace Documents; /** @Document */ class Product { /** @Id */ private $id; /** @String */ private $title; public function getId() { return $this->id; } public function getTitle() { return $this->title; } public function setTitle($title) { $this->title = $title; } }
Next create the Order
entity that has a $product
and $productId
property linking it to the Product
that is stored with MongoDB:
<?php namespace Entities; use Documents\Product; /** * @Entity * @Table(name="orders") * @HasLifecycleCallbacks */ class Order { /** * @Id @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ private $id; /** * @Column(type="string") */ private $productId; /** * @var Documents\Product */ private $product; public function getId() { return $this->id; } public function getProductId() { return $this->productId; } public function setProduct(Product $product) { $this->productId = $product->getId(); $this->product = $product; } public function getProduct() { return $this->product; } }
Event Subscriber
Now we need to setup an event subscriber that will set the $product
property of all Order
instances to a reference to the document product so it can be lazily loaded when it is accessed the first time. So first register a new event subscriber:
<?php $eventManager = $em->getEventManager(); $eventManager->addEventListener( array(\Doctrine\ORM\Events::postLoad), new MyEventSubscriber($dm) );
So now we need to define a class named MyEventSubscriber
and pass a dependency to the DocumentManager
. It will have a postLoad()
method that sets the product document reference:
<?php use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ORM\Event\LifecycleEventArgs; class MyEventSubscriber { public function __construct(DocumentManager $dm) { $this->dm = $dm; } public function postLoad(LifecycleEventArgs $eventArgs) { $order = $eventArgs->getEntity(); $em = $eventArgs->getEntityManager(); $productReflProp = $em->getClassMetadata('Entities\Order') ->reflClass->getProperty('product'); $productReflProp->setAccessible(true); $productReflProp->setValue( $order, $this->dm->getReference('Documents\Product', $order->getProductId()) ); } }
The postLoad
method will be invoked after an ORM entity is loaded from the database. This allows us to use the DocumentManager
to set the $product
property with a reference to the Product
document with the product id we previously stored.
First create a new Product
:
<?php $product = new \Documents\Product(); $product->setTitle('Test Product'); $dm->persist($product); $dm->flush();
Now create a new Order
and link it to a Product
in MySQL:
<?php $order = new \Entities\Order(); $order->setProduct($product); $em->persist($order); $em->flush();
Later we can retrieve the entity and lazily load the reference to the document in MongoDB:
<?php $order = $em->find('Order', $order->getId()); // Instance of an uninitialized product proxy $product = $order->getProduct(); // Initializes proxy and queries the database echo "Order Title: " . $product->getTitle();
If you were to print the $order
you would see that we got back regular PHP objects:
<?php print_r($order);
The above would output the following:
Order Object
(
[id:Entities\Order:private] => 53
[productId:Entities\Order:private] => 4c74a1868ead0ed7a9000000
[product:Entities\Order:private] => Proxies\DocumentsProductProxy Object
(
[__isInitialized__] => 1
[id:Documents\Product:private] => 4c74a1868ead0ed7a9000000
[title:Documents\Product:private] => Test Product
)
)
That is it! It is not a very abstract example right now but it demonstrates how to utilize the events to do some very interesting things with the Doctrine persistence libraries! I hope that now someone will inspired to create an extension that offers an abstract solution for blending the ORM and ODM together!
Posted in: Doctrine, MongoDB, PHP
Tags: doctrine, mongodb, odm, orm, php
New Doctrine MongoDB ODM Documentation
August 19th, 2010
Yesterday I added a few new chapters to the Doctrine MongoDB ODM Documentation:
- Capped Collections
- Indexes
- Geospatial Queries
- Storing Trees/Hierarchical Data
I hope it is helpful to someone!
Posted in: MongoDB, Open Source, PHP
Tags: doctrine, mongodb, odm, php
Doctrine Annotations Library
August 2nd, 2010
The Doctrine Annotations library was born from a need in the Doctrine2 ORM to allow the mapping information to be specified inside the doc-blocks of classes, properties and methods. The library is independent and can be used in your own libraries to implement doc block annotations.
Setup and Configuration
To use the annotations library is simple, you just need to create a new AnnotationReader
instance:
<?php $reader = new \Doctrine\Common\Annotations\AnnotationReader();
Usage
Using the library API is simple. Imagine you had some annotation classes that looked like the following:
<?php namespace MyCompany\Annotations; class Foo extends \Doctrine\Common\Annotations\Annotation { public $bar; } class Bar extends \Doctrine\Common\Annotations\Annotation { public $foo; }
Now to use the annotations you would just need to do the following:
<?php /** * @MyCompany\Annotations\Foo(bar="test") * @MyCompany\Annotations\Bar(foo="test") */ class User { }
Now we can write a script to get the annotations above:
<?php $reflClass = new ReflectionClass('User'); $classAnnotations = $reader->getClassAnnotations($reflClass); echo $classAnnotations['MyCompany\Annotations\Foo']->bar; // prints foo echo $classAnnotations['MyCompany\Annotations\Foo']->foo; // prints bar
You have a complete API for retrieving annotation class instances from a class, property or method docblock:
- getClassAnnotations(ReflectionClass $class)
- getClassAnnotation(ReflectionClass $class, $annotation)
- getPropertyAnnotations(ReflectionProperty $property)
- getPropertyAnnotation(ReflectionProperty $property, $annotation)
- getMethodAnnotations(ReflectionMethod $method)
- getMethodAnnotation(ReflectionMethod $method, $annotation)
Read the full documentation to learn more about how to use the Doctrine annotations library!
Posted in: Doctrine, PHP, Uncategorized
Tags: annotations, doctrine, php