A
A
Aleks_ja2012-06-12 01:51:03
PHP
Aleks_ja, 2012-06-12 01:51:03

Should I Open Source an ORM for PHP?

I would like to know if the system for working with persistent objects in PHP will be useful to someone. She has been working on a large number of closed source commercial projects for several years now. And because over the years, nothing similar has appeared - I would like to know if anyone will be interested.

The system was developed according to the principle - as it would be convenient for OOP, without mixing work with one entity and collections of entities, well, without additional structures for storing data. And… without regard to any patterns.

In syntax, the main method for obtaining entities is through static methods. Those. quite often you can find such that a static method of a class will return an object of this very class.

All you need to do in order for the object to start being saved, obtained from the database (i.e. become permanent), you just need to write the following:

class User extends DataObject{
}


Those. extend from the DataObject class

To get the user:

class User extends DataObject{
    /**
     * Will return user by id
     * @param int $userId
     * @return User
     */
  public static function getById($userId){
 	return parent::_getByCondition(array('user_id'=>$userId),__CLASS__,'users');	
  }
}


It's that simple. You can similarly do more getByName and anything else. The user object will have get, set, save methods. In addition to the parent static method _getByCondition, there is _getByQuery, _create.

The user class itself might look like this:

class User extends DataObject{
  const TABLE='users';
    /**
     * Will return country of the user
     *
     * @return Country
     */
  public function getCountry(){
 	return Country::getById($this->get('country_id'));
  }

   /**
     * Will return user by id
     *
     * @param int $userId
     * @return User
     */
  public static function getById($userId){
 	return parent::_getByCondition(array('user_id'=>$userId),__CLASS__,self::TABLE);	
  }

   /**
     * Will return user by email
     *
     * @param string $email
     * @return User
     */
  public static function getByEmail($email){
 	return parent::_getByCondition(array('email'=>$email),__CLASS__,self::TABLE);	
  }
    /**
     * Will create user
     *
     * @param string $email
     * @param string $password
     * @param string $firstName
     * @param string $lastName
     * @return User
     */
  public static function create($email,$password,$firstName,$lastName,Country $country){
    return parent::_create(array('email'=>$email,
          'password'=>$password,
          'first_name'=>$firstName,
          'last_name'=>$lastName, 
          'country_id'=>$country->getId()),__CLASS__,self::TABLE,'id');
  }
}


Next, you can, for example, create a user and manipulate the data a little.

echo User::create('[email protected]','123','Vasja','Pupkin')->getCountry()->getCurrency()->getCode();


The user received by different methods - getById and getByEmail - will be links to the same object.

In fact, one row in the table corresponds to one object.

To work with several objects, there is a DataObjectGroup, and in a similar way, in order for this object to be a collection, you need to extend the special DataObjectGroup class.

class UsersGroup extends DataObjectGroup{
  /**
   * Will return premium users (UsersGroup of Users)
   *
   * @return UsersGroup
   */
  public static function getPremiumMembers(){
    return parent::_getByCondition(array('is_permium'=>1),__CLASS__,'User',User::TABLE,'id');
 	}
}


Then you can do something like this:

foreach(UsersGroup::getPremiumMembers()->orderBy('registration_date')->limit(10) as $user){
  /**<hh user=var> User $user*/
  echo $user->getCountry()->getCurrency()->getCode()."<br />";
}


These are just the basic features and principles.

It is very pleasant to work with such a structure - everything is clear and obvious. In addition, it is easily attached anywhere, including shitty sites, sites with a fuzzy structure, where you need to gradually add structure.

Why not immediately in the article - you also need to link to some popular layer of working with the database (for example, pdo), polish it a little, choose a name, and in order to do this - first of all you need to know - whether there are those who need it, or is enough for everyone existing solutions, for example - Doctrine 2.

Everything works with PHP5.2+

Answer the question

In order to leave comments, you need to log in

5 answer(s)
E
egorinsk, 2012-06-12
@egorinsk

By itself, ORM is banal, unremarkable crap. This has already been done many times in other frameworks (for example, RoR, Java) and is described in books about patterns. You take it, you do it like in Ruby and you use it even until you're blue in the face.
The example with User::create() is bad: real objects have 20 properties and a function with 20 arguments will look wild. Functions with an underscore at the beginning are ugly. Passing __CLASS__ and similar magic methods is also not very somehow.
One of the difficult moments in ORM design is the optimal organization of interaction with the repository. For example, this example of yours:
> foreach(UsersGroup::getPremiumMembers()->orderBy('registration_date')->limit(10) as $user){
> echo $user->getCountry()->getCurrency()-> getCode()."
";
How many queries will it generate when using SQL storage? In theory, it should be in the region of 3-4, and the data of directories should still be cached (because the currencies of countries change very rarely) and get by with 1-2 requests. If you have a request made in a loop for each user, this is rubbish, not ORM.
The second point is an overhead. Have you ever considered the difference in query execution time through your ORM and through mysqli_query() (including the time to load and initialize ORM classes)? Calculate, for sure after that you will generally lose the desire to use ORMs.
The third point is scaling. Is it possible, for example, by making a huge site on your ORM, without rewriting the code, to implement sharding the database into 100 servers (to cope with the load). Is it possible to make projects at the level of at least games for social networks or VKontakte on it?
If you have a solution for at least some of the 3 ORM design problems described, your article on the topic of architectural decisions and programming tricks would be extremely interesting. If there is no solution, then any student can do such an orm, as I said, by reading the manual for rubionrails.

S
silentnuke, 2012-06-12
@silentnuke

Write, it will definitely not be superfluous.

E
EugeneOZ, 2012-06-12
@EugeneOZ

I will criticize for shitty code :) Static methods are not OOP, they are just procedures, nothing more. With global visibility, dependencies.
Well, it’s very, very bad that your entities should extend from something. Between inheritance and aggregation, choose aggregation.
I wrote such crap a couple of years ago, now it's a shame to remember :)

S
Sergey Beresnev, 2012-06-12
@sectus

Of course you can write. But, as far as I understand, your main idea (because it is highlighted in bold):
> In fact, one row in the table corresponds to one object.
And I singled out this idea for myself:
> And...without looking back at any patterns.
If you still looked back, you would know what exactly you invented.

A
Anatoly, 2012-06-12
@taliban

Your activerecord is the simplest interaction with the database, and this is the weakest functional interaction, it is in any framework, in any framework there is an add-on. functionality that takes into account connections, etc. In my opinion it's not worth it. Moreover, the functional, to be honest, is depressing =)
Just for example, another piece of code:

class User extends ActiveRecord{
    protected $_table = 'users';
}

$user = User::find( array('id'=>3) );
$user->name = 'new name';
$user->set('last_name', 'new last name')->set('email', '[email protected]')->save();

Tritely, I don’t have to write anything in the class code, the parent does everything for me, he finds the fields himself, he finds the keys himself, he saves himself, he knows which key to save, he knows which fields to save.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question