Anyone know a good lightweight ORM?

Hi guys, I am reconfiguring my skeleton I use on most my sites and optimizing it to be very lightweight and versatile. Doctrine is extremely powerful however I am just looking for a PHP ORM that is basically one class in one file. Does anyone know any good ones?

Thanks,
Darren

I have coded my own lightweight ORM inspired by the Propel ORM. It uses plain SQL for defining criteria, which some people find objectionable, but I have used it for some time now and I can say it’s pretty fast. I also think that the article mentioned by AnthonySterling in the previous post has some good points so I basically don’t care about perfect object to relation mapping and I skipped stuff like complex relations, etc. I believe that it’s neither possible nor practical to fully abstract from a relational database so I’m not striving for that - I use my ‘ORM’ with full awareness that I’m working on db table data and I don’t forget about it, hence the use of plain SQL in many cases. But the results are populated into objects in most cases so I get the benefit of having live data whenever I need and I find it quite useful. But whenever an ORM may have difficulties dealing with a problem, I immediately switch to talking to db directly, because I’m not trying to hammer a square peg into a round hole.

I explained more about it here: Code critique: minimalist SQL query class and some interesting discussion as well.

Far from one file (why is this a requirement?), but I really like Outlet. It doesn’t have the advanced functionality of Doctrine, but it’s fine for most stuff and a lot faster as it doesn’t use reflection.

That’s nice, very similar to my own actually. I took it a step further to make the syntax a bit more simplistic by implementing countable, arrayaccess and iterator:


//$this->mapper is a factory very similar to your QueryObject 
$users = $this->mapper->user;

echo count($this->mapper->user);

$user = $this->mapper->user[123]; 
//Same as $this->mapper->user->getById(123);

//$users[123] is cached so this doesn't create extra queries
foreach ($this->mapper->user[123]->posts as $post) {

}

//Also supports 
$user = new User;
$user->name = 'Tom';

$this->mapper->user[] = $user;


//Delete the record
unset($this->mapper->user[123]);

One thing I dislike about that (and Doctrine for that matter) is that you need your entire database schema defined in PHP (in Outlet, it looks like it’s all in 1 horribly formatted file, what if I have 100+ tables?). Really you should only need the relationships and let the database handle the schema.

Whilst not wanting to go too off topic, here is an interesting take on ORM.

Object-Relational Mapping is the Vietnam of Computer Science

Thanks,

I will probably use this.

In my opinion the only practical way to implement ORM is specific to the job at hand. Any attempt to make it generic is a waste of resources resulting in all kinds of sacrifices and work-arounds.

From my own research into this, the whole ORM thing is a bit of a minefield. If your domain allows for a predominantly 1:1 relation between data and objects, then it’s not too hard to implement. Once you start mapping disparate tables and bringing in large collections of data, it can get unwieldy pretty fast.

I suspect that what you’re looking for isn’t really an ORM, but maybe a more lightweight pattern like ActiveRecord or Table Data Gateway. However, in case you are actually looking for a one-file ORM, you will probably have to write custom mappers for each of your domain objects, something similar to this:

<?php

class PostMapper	{

	public function load($array)	{
		$post = new Post();
		$post->setId($array['id']);
		$post->setAuthor($array['author'];
		$post->setTitle($array['title']);
		$post->setBody($array['body'];
		return $post
	}
	
	public function unload($post)	{
		$array = array();
		$array['id'] = $post->getId();
		$array['author'] = $post->getAuthor();
		$array['title'] = $post->getTitle();
		$array['body'] = $post->getBody();
		return $array;
	}
	
	public function findById($id)	{
		$stmt = $this->db->prepare('SELECT * FROM posts WHERE id = :id');
		$stmt->execute(array(':id'=>$id));
		return $this->load($stmt->fetch(PDO::FETCH_ASSOC));
	}
	
	public function save($post)	{
		if ($post->getId())	{
			$this->update($post);
		} else {
			$this->insert($post);
		}
	}
	
	public function update($post)	{
		$array = $this->unload($post);
		$stmt = $this->db->prepare('UPDATE posts SET author = :author, title = :title, body = :body WHERE id = :id');
		$stmt->execute(array(':author'=>$array['author'],':title'=>$array['title'],':body'=>$array['body'],':id'=>$array['id']));
	}

	public function insert($post)	{
		$array = $this->unload($post);
		$stmt = $this->db->prepare('INSERT INTO posts SET author = :author, title = :title, body = :body');
		$stmt->execute(array(':author'=>$array['author'],':title'=>$array['title'],':body'=>$array['body']));
	}	
	
}

That’s about as lightweight an ORM as you can get. If you want to cut down on the amount of code you’re writing, automating some of the SQL generation instead of handcoding it should leave you with pretty much the load() and unload() methods as well as any custom finders you might need.

I’m not sure you’re going to find any serious ORM libraries that are just one file, but I made phpDataMapper, and it’s about as light as they come. It does pretty much everything you need in a fairly small package. The whole project is under 100k (excluding unit tests).

Wow, thanks. I think I will use that one and integrate it into my framework. Looks great, can’t believe it is under 100k.

What is the architecture / principles like? I do some PHP, but mainly C# and the new “in” thing is to talk about doing away with the relational database and store data object by object instead of using normalization. I don’t know about anyone else, but that makes me nervous. How do you do your ORM?

I’ve been working on a VERY lightweight ORM, gonna release it soon. Here’s some usage examples:

It’s small and light, yet very flexible :slight_smile:

Interesting, it looks a lot like Java’s Persistence Query Language.

At least to me anyway! :slight_smile:

That looks almost exactly like phpDataMapper’s syntax:
http://phpdatamapper.com/documentation/usage/finders/


# All posts
$posts = $postMapper->all();
 
# All posts with a 'published' status, descending by date_created
$posts = $postMapper->all(array('status' => 'published'))->order(array('date_created' => 'DESC'));
 
# All posts created before today
$posts = $postMapper->all(array('date_created <' => date($postMapper->adapter()->dateFormat())));
 
# Posts with 'id' of 1, 2, 5, 12, or 15 - Array value = automatic "IN" clause
$posts = $postMapper->all(array('id' => array(1, 2, 5, 12, 15))); 

Probably coincidence, never even heard of that :smiley:

<nevermind read wrong>

Can’t find how to edit my old post anymore :open_mouth: so just making a new one.
While it does look similar, there are several key differences.

My lookup syntax is actually more similar to the Django query language (which is very well designed, by the way!)


$articles =  QueryObject::getModel( 'ArticlesModel' );
$articles->find( array( 'title__startswith' => 'what' ) ); // translates to: WHERE title LIKE '%what'

A double underscore followed by a modifier lets you do all sorts of lookups.
Also the philosophy of mine is that by default you start out with all the rows, and that you apply filters to narrow it down to exactly the rows you want.

I’m finishing off the first version this week, so the people who want to take a look or try it out can send me a PM and I’ll let you have a sneak peak (so I’m not blatently advertising this all over the forum) :slight_smile:

I did notice that you were using the django-like ‘filter’ method name with chaining, so I wondered. I didn’t know you were doing the double-underscore feature as well, though - very nice. Not sure how you’re going to keep a django-like ORM light, though… :).