webdevRefinery Forum: Planning the new SQLBeans - webdevRefinery Forum

Jump to content

  • 3 Pages +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

Rate Topic: -----

User is online Kyek 

  • Founder of wdR
  • Group: Administrators
  • Posts: 4834
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML,CSS,PHP,Java,Javascript,Node.js,SQL

Posted 26 December 2010 - 09:31 PM (#1)

Planning the new SQLBeans


Input please! :D
So the handful of you that have been using Hydrogen in its Alpha stages (<3 you guys, I couldn't do this without you) know that my least favorite part of the library right now is SQLBeans (and Query, to a lesser degree) because of how absurdly hard it is to use. I still maintain that most popular ORMs (Object-relational-maps... systems to let you interact with PHP objects instead of writing your own DB queries, sortof like SQLBeans) are horrible because they generate more overhead and more additional queries than they're worth. So my goal is still to have an ORM-like library that doesn't generate any extra queries than what you would run if you wrote your queries by hand, but I'd also like to make SQLBeans much much much more intuitive for the programmer to use. Because right now, it's just not. At all. Not even a little bit.

Since I've been finishing up the new Hydrogen templating engine, I've been thinking more about how I want to change SQLBeans, and I've put down a few pretty solid ideas I'm excited about. So I just want to cover the basics of what I'm planning for the new library, and I would love your feedback about whether you like it, whether any of your webapps need to do something that my new system won't support, and whether you've seen any other ORM or ORM-like solution that's better than what I've come up with.

So here's what I'm thinking.

Right now, if you want to narrow down the set of results you get from an SQLBean, you have to create a new instance of Query and put in a few WHERE clauses and pass that to the SQLBean. That is *messy*. The new system won't require you to use the Query library like that. Instead, if you want to retrieve all users in, for example, the group named Moderator, you might do this:
$users = UserBean::find()->group_name('Moderator');


Or maybe you want to find all normal members with exactly one post:
$users = UserBean::find()->group_name('Members')->posts(1);


Or maybe you want to do the same thing, but for members with more than 20 posts:
$users = UserBean::find()->group_name('Members')->posts_greaterThan(20);


Or maybe you want to find just one user, change his name to "Fluffy", change his age to 6, and save that back to the database:
$user = UserBean::findOne()->username('Kyek');
$user->username = 'Fluffy';
$user->age = 6;

Done. No calling update(), no multiple queries, you just change what you need to change, and when you're done making changes, it saves back to the database.

You can also update many users at once. This line will promote all Moderators to Administrators:
$users = UserBean::find()->group_name('Moderators');
$users->group_name = 'Administrators';

Again, no calling update(), and this is just one SQL query. You can also pull this off in one line:
UserBean::find()->group_name('Moderators')->group_name = 'Administrators';


Here's another improvement over SQLBeans, too: deleting records. You could always select a record from the database and THEN delete it, like this (this will still work):
$user = UserBean::findOne()->username('magik');
$user->delete();

...but the drawback is, you're running a SELECT query before you run a DELETE query, and all we wanted to do was delete it. So now, you can do this and it will never execute a SELECT query:
UserBean::findOne()->username('magik')->delete();


What's more, you can use the same concept to mass-delete a group of records without selecting them first:
UserBean::find()->group_name('Banned')->delete();


And check out how easy it is to create a record now. Actually, there will probably be two ways. Here's the long way:
$newUser = UserBean::create();
$newUser->username = "Kyek";
$newUser->email = "kyek@webdevrefinery.com";
$newUser->age = 26;
$newUser->group_name = 'Administrators';  // Note: This will actually set the group_id field of this record in the 'users' table to the id number of 'Administrators' in the groups table, all with ONE QUERY!

And done. Again, no insert() or update() or anything like that.

But check out the short way:
UserBean::create()
    ->username('Kyek')
    ->email('kyek@webdevrefinery.com')
    ->age(26)
    ->group_name('Administrators');

One line, and done.

A few notes that my examples here haven't illustrated:
  • The 'find' command will take two optional arguments: the first will be the max number of records to get (so find(1) and findOne() will actually be the exact same thing), and the second will be a combination of what the current SQLBeans' doMapping and mapOverride arguments do now. They'll allow you to get just a subset of columns rather than the whole record, and it will also allow you to specify whether the mapped tables should be JOINed and SELECTed as well.
  • No more getMapped() is required. You just prefix your function names. So UserBean::find()->group_name('Members') will first check to see if there's a field named "group_name" in the Users table, and if not, it'll look for a field named 'name' in the 'Groups' table. My whole concept here is that SQLBeans should be smart enough to know what you want without you having to be ridiculously verbose about telling it.
  • If for some reason you need to force an updated or created record to save back to the database before Hydrogen detects that you're done changing it, you can call ->save() on any bean instance.
  • I haven't decided how SQLBeans finds out about your database structure yet. I will not do what most ORMs do and force you to give up control of your database structure. That is crap. You'll either define your tables much like SQLBeans already does, or I might move to some sort of XML-based file that tells Hydrogen what your tables and fields and stuff are. Either way, I'd **LOVE** to make it possible for you to call one method and have all of your tables created in the database, making new installs a breeze. That's not my highest priority though.


Anyway, sorry, I know this was long, but I'd love to get your thoughts. Note that I'm not trying to make this something that completely removes the need for executing your own queries. That's what makes ORMs so damn heavy. Sometimes you'll need to write your own queries, and that's ok. But what I'm trying to do is make your life as easy as possible, 95% of the time ;-)
0


User is offline ShanePerreault 

  • Sleep Burns My Eyes
  • Group: Members
  • Posts: 1075
  • Joined: 19-March 10
  • LocationChicago, USA
  • Expertise:PHP,Java,Javascript,Ruby on Rails,SQL

Posted 26 December 2010 - 10:43 PM (#2)

This seems pretty painless. I might have to give Hydrogen a try if you do this. B)

Languages: PHP | JS | Ruby | Rails | C# | Python | Java
0


User is online derTechniker 

  • BadBoy™
  • Group: Members
  • Posts: 1183
  • Joined: 06-July 10
  • LocationAustria
  • Expertise:HTML,CSS,PHP,Javascript,SQL

Posted 27 December 2010 - 03:28 AM (#3)

I think this is actually great. On the other hand, i don't think it's really painfull how the sqlbeans and querys with it work right now. (i think it's pretty cool!)

Still your idea sounds really good. People will have to learn a bit more than with the current sql beans. Oh, and with the database structure, keep the SQLBeans.php like they are now, i think thats a really good way.
0


User is offline Koen 

  • Leroy Jenkins
  • Group: Members
  • Posts: 2409
  • Joined: 10-March 10
  • Locationthe Netherlands
  • Expertise:HTML,CSS,Javascript,Graphics

Posted 27 December 2010 - 04:10 AM (#4)

I love this! I'm especially happy with the "group_name" thing, that's really cool. I also really like this:
UserBean::find(1)->username('Kyek')->delete();

Or this:
$user = UserBean::create();
$user->username = 'PWNbear';
$user->group_name = 'Administrators'; // This thing is REALLY cool :-)

Even though I have no idea how you're gonna let Hydrogen look in the future to see if you're gonna add another entry, that seems impossible for me :P Anyways, I can't wait!
Twitter: @KoenKlaren
0


User is offline AwesomezGuy 

  • 兄ジャック
  • Group: Members
  • Posts: 1121
  • Joined: 08-March 10
  • LocationIreland
  • Expertise:HTML,CSS,PHP,Javascript,Python,SQL

Posted 27 December 2010 - 06:15 AM (#5)

Holy crap Kyek, if you can pull all that off and make it work awesome-ly, I'll probably have to rewrite iSuperepo v3 just so I can use this new stuff! ;)

On a sidenote, your Query library has already spoilt me. I was writing another part for my IRC bot yesterday after weeks of doing nothing on it. And I'd forgotten how to write SQL queries...
My memory is obviously total shit when I don't use it.

Kyek said:

<3 you guys, I couldn't do this without you


:)
0


User is offline Koen 

  • Leroy Jenkins
  • Group: Members
  • Posts: 2409
  • Joined: 10-March 10
  • Locationthe Netherlands
  • Expertise:HTML,CSS,Javascript,Graphics

Posted 27 December 2010 - 07:57 AM (#6)

I can't wait till Kyek posts his post he's been working on for a while now :P His name is still italic down there!
Twitter: @KoenKlaren
0


User is online Kyek 

  • Founder of wdR
  • Group: Administrators
  • Posts: 4834
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML,CSS,PHP,Java,Javascript,Node.js,SQL

Posted 27 December 2010 - 08:04 AM (#7)

View PostderTechniker, on 27 December 2010 - 03:28 AM, said:

Still your idea sounds really good. People will have to learn a bit more than with the current sql beans.

You think so? My whole purpose with writing this was to make it *more* intuitive than SQLBeans is right now D:

View PostPWNbear, on 27 December 2010 - 04:10 AM, said:

Even though I have no idea how you're gonna let Hydrogen look in the future to see if you're gonna add another entry, that seems impossible for me :P Anyways, I can't wait!

I cheat :D. I'm going to attach the save-to-database event to the destruction of the object. So the last line here would technically instantly save the changes:
$user = UserBean::findOne()->username('PWNBear');
$user->group_name = 'Banned';
unset($user);

So if you're doing a one-line change like this:
UserBean::findOne()->username('PWNBear')->delete();

The DELETE query will be sent to the database immediately after that line executes because the variable isn't being saved. It's instantly destroyed, so it instantly works its magic.

If you DID save that to a variable, it would just execute at the end of the function (assuming that's in a function, probably in a Model class) when the variables local to that function are trashed. If you do something like this:
function getFiveUsersAndMakeThemAwesome() {
    $users = UserBean::find(5);
    $users->group_name = 'Awesome';
    return $users;
}

You're actually returning the object, so it gets kept alive. So assuming that gets returned to a controller, it won't save its changes until the controller is done executing. Either way, all variables are destroyed at the end of the request, so there's not a chance of a bean not automatically saving -- but if you're concerned about when your bean saves for one reason or another, you can do this:
function getFiveUsersAndMakeThemAwesome() {
    $users = UserBean::find(5);
    $users->group_name = 'Awesome';
    $users->save();
    return $users;
}

And you're good to go :)

View PostAwesomezGuy, on 27 December 2010 - 06:15 AM, said:

On a sidenote, your Query library has already spoilt me. I was writing another part for my IRC bot yesterday after weeks of doing nothing on it. And I'd forgotten how to write SQL queries...

Hahahaha ;-) I (generally) like the Query class as-is from an API standpoint, so my changes to it probably won't make anyone change any code. What kills me about that class is that I wrote it for AppDB back before I knew how terribly inefficient it was to use associative arrays -- which is what Query uses internally to build the actual SQL query before it gets compiled into a string. Not that associative arrays are bad, mind you, but when you use Query, it can go so far as to have HUGE nested associative arrays up to 5 arrays deep for each entry, which is **crazy**. So I'd like to change that to use straight objects instead which would be a nice speedup, and I'd like to allow it to chain similarly to how my proposed SQLBeans stuff does:
$hotties = new Query('SELECT')
    ->field('name')->field('age')
    ->from('users')
    ->where('age >= 18')
    ->where('gender = "female"')
    ->where('status' like 'hot');


I might also change to a dynamic function system similar to how the proposed SQLBeans works too:
$query->where_equal("name", "Sarah");
$query->where_greaterThan("age", $legalAge);

Because that way, you no longer have to put question marks in your strings. You just pass the variable in, and Query would take care of the question marks for you. But I definitely won't make any changes that would make it impossible to write some complex queries, because that's the biggest thing I hate about every query builder in every other framework known to man.

Anyway! Thanks for the input guys :) I'd still love to hear from someone who works extensively with other ORMs, though!

View PostPWNbear, on 27 December 2010 - 07:57 AM, said:

I can't wait till Kyek posts his post he's been working on for a while now :P His name is still italic down there!

Rofl, I should start just hitting reply and going to take a nap ;-)
0


User is offline Koen 

  • Leroy Jenkins
  • Group: Members
  • Posts: 2409
  • Joined: 10-March 10
  • Locationthe Netherlands
  • Expertise:HTML,CSS,Javascript,Graphics

Posted 27 December 2010 - 08:07 AM (#8)

View PostKyek, on 27 December 2010 - 08:04 AM, said:

I cheat :D. I'm going to attach the save-to-database event to the destruction of the object. So the last line here would technically instantly save the changes:
$user = UserBean::findOne()->username('PWNBear');
$user->group_name = 'Banned';
unset($user);

Lol! I was thinking of doing it like that, but I didn't know if there was a __destroy method or something like that :)
Twitter: @KoenKlaren
0


User is online derTechniker 

  • BadBoy™
  • Group: Members
  • Posts: 1183
  • Joined: 06-July 10
  • LocationAustria
  • Expertise:HTML,CSS,PHP,Javascript,SQL

Posted 27 December 2010 - 08:09 AM (#9)

View PostKyek, on 27 December 2010 - 08:04 AM, said:

You think so? My whole purpose with writing this was to make it *more* intuitive than SQLBeans is right now D:



Well for people who already know PHP yes. Whats more intuitive than a query that looks like .... a query?
0


User is online Kyek 

  • Founder of wdR
  • Group: Administrators
  • Posts: 4834
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML,CSS,PHP,Java,Javascript,Node.js,SQL

Posted 27 December 2010 - 08:15 AM (#10)

View PostPWNbear, on 27 December 2010 - 08:07 AM, said:

Lol! I was thinking of doing it like that, but I didn't know if there was a __destroy method or something like that :)

It's __destruct xD That was a damn good guess! http://php.net/manua....oop5.decon.php

View PostderTechniker, on 27 December 2010 - 08:09 AM, said:

Well for people who already know PHP yes. Whats more intuitive than a query that looks like .... a query?

Well, right, but it's not the structure of the query that I'm worried about :) It's the fact that people have to remember what prefix to use for their fields in complex WHERE clauses, or how to format a mapOverride, or what sending 'true' as the second argument to ::select() does, or that they have to use ->set() and pass it 'true' at the end to set a variable to an SQL function... all of those things that aren't even CLOSE to be intuitive. The new version isn't formatted like a query, so people would have to learn it -- but I think it's something they could learn and remember much better than they could with SQLBeans as it is now. Heck, *I* have to go back and read old code for reference every time I use that library, and I made it!
0


User is online derTechniker 

  • BadBoy™
  • Group: Members
  • Posts: 1183
  • Joined: 06-July 10
  • LocationAustria
  • Expertise:HTML,CSS,PHP,Javascript,SQL

Posted 27 December 2010 - 08:35 AM (#11)

View PostKyek, on 27 December 2010 - 08:15 AM, said:

It's __destruct xD That was a damn good guess! http://php.net/manua....oop5.decon.php


Well, right, but it's not the structure of the query that I'm worried about :) It's the fact that people have to remember what prefix to use for their fields in complex WHERE clauses, or how to format a mapOverride, or what sending 'true' as the second argument to ::select() does, or that they have to use ->set() and pass it 'true' at the end to set a variable to an SQL function... all of those things that aren't even CLOSE to be intuitive. The new version isn't formatted like a query, so people would have to learn it -- but I think it's something they could learn and remember much better than they could with SQLBeans as it is now. Heck, *I* have to go back and read old code for reference every time I use that library, and I made it!



yes thats true. Go along and make it like that :D
0


User is offline devinsba 

  • Group: Members
  • Posts: 115
  • Joined: 08-August 10
  • LocationClarkson University
  • Expertise:PHP,Java,Javascript

Posted 27 December 2010 - 11:18 AM (#12)

The only missing feature Ive found is that I can't have a multi-value primary key. I am also hoping that the next version of Query supports method stringing so that it doesnt take 10 lines to write a query
0


User is online Mack 

  • http://mackgoodstein.com/
  • Group: Members
  • Posts: 1961
  • Joined: 08-March 10
  • Expertise:HTML,CSS,PHP,Javascript

Posted 27 December 2010 - 11:55 AM (#13)

View PostKyek, on 27 December 2010 - 08:04 AM, said:

Quote

Still your idea sounds really good. People will have to learn a bit more than with the current sql beans.

You think so? My whole purpose with writing this was to make it *more* intuitive than SQLBeans is right now D:

If I'm not mistaken, you could use the current method with the update, or the new one. If it is that way, people can just do whichever one is easiest to them. If someone knows PHP, the second method is easier. Someone who doesn't understand the new method could still use the old way if that makes more sense. Not sure if what I'm saying makes sense to you, I'm not explaining it too well.
0


User is online Kyek 

  • Founder of wdR
  • Group: Administrators
  • Posts: 4834
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML,CSS,PHP,Java,Javascript,Node.js,SQL

Posted 27 December 2010 - 12:08 PM (#14)

View PostMack, on 27 December 2010 - 11:55 AM, said:

If I'm not mistaken, you could use the current method with the update, or the new one. If it is that way, people can just do whichever one is easiest to them. If someone knows PHP, the second method is easier. Someone who doesn't understand the new method could still use the old way if that makes more sense. Not sure if what I'm saying makes sense to you, I'm not explaining it too well.

I understood :) That's called deprecation -- supporting old methods/syntax for the sake of backward-compatibility while writing new methods to do more advanced things. I'm not planning to do any deprecation until the first major release, as we're still in Alpha :). Mixing the new method that stays away from using Query with the old method that 100% relies on it would be far too much work to introduce into an Alpha release.

View Postdevinsba, on 27 December 2010 - 11:18 AM, said:

The only missing feature Ive found is that I can't have a multi-value primary key. I am also hoping that the next version of Query supports method stringing so that it doesnt take 10 lines to write a query

Definitely yes to method-stringing, and I'll absolutely look into supporting multi-column primary keys :) Thanks!
0


User is offline Hamador 

  • Group: Members
  • Posts: 131
  • Joined: 21-March 10
  • LocationLas Vegas

Posted 27 December 2010 - 03:15 PM (#15)

Oh, that is just sexy.
[DOT DOT DOT]


Posted Image
0


User is offline Koen 

  • Leroy Jenkins
  • Group: Members
  • Posts: 2409
  • Joined: 10-March 10
  • Locationthe Netherlands
  • Expertise:HTML,CSS,Javascript,Graphics

Posted 27 December 2010 - 03:16 PM (#16)

View PostHamador, on 27 December 2010 - 03:15 PM, said:

Oh, that is just sexy.

Nah. It's hot as hell :P
Twitter: @KoenKlaren
0


User is online Kyek 

  • Founder of wdR
  • Group: Administrators
  • Posts: 4834
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML,CSS,PHP,Java,Javascript,Node.js,SQL

Posted 27 December 2010 - 03:32 PM (#17)

View PostHamador, on 27 December 2010 - 03:15 PM, said:

Oh, that is just sexy.

HAMMY! I missed you! :D Glad you like the draft :D
0


User is offline Hamador 

  • Group: Members
  • Posts: 131
  • Joined: 21-March 10
  • LocationLas Vegas

Posted 27 December 2010 - 04:03 PM (#18)

View PostKyek, on 27 December 2010 - 03:32 PM, said:

HAMMY! I missed you! :D Glad you like the draft :D


I missed this place too but . . . new job, new responsibilities, new wife, been a busy 6 months. I'll have to go back and re-read through all the new changes to Hydrogen when I get some time.
[DOT DOT DOT]


Posted Image
0


User is online Kyek 

  • Founder of wdR
  • Group: Administrators
  • Posts: 4834
  • Joined: 20-February 10
  • LocationPhiladelphia, PA, USA
  • Expertise:HTML,CSS,PHP,Java,Javascript,Node.js,SQL

Posted 27 December 2010 - 04:39 PM (#19)

View PostHamador, on 27 December 2010 - 04:03 PM, said:

I missed this place too but . . . new job

Congrats!

Quote

new responsibilities

Congrats!

Quote

new wife

Well that sucks Congrats!

Quote

been a busy 6 months

I know the feeling ;-)

Quote

I'll have to go back and re-read through all the new changes to Hydrogen when I get some time.

It'll be good to have you around again! :)
0


User is offline AwesomezGuy 

  • 兄ジャック
  • Group: Members
  • Posts: 1121
  • Joined: 08-March 10
  • LocationIreland
  • Expertise:HTML,CSS,PHP,Javascript,Python,SQL

Posted 27 December 2010 - 04:47 PM (#20)

View PostKyek, on 27 December 2010 - 08:04 AM, said:

$hotties = new Query('SELECT')
    ->field('name')->field('age')
    ->from('users')
    ->where('age = 15')
    ->where('gender = "female"')
    ->where('status' like 'hot');


$query->where_equal("name", "Sarah");
$query->where("age", $awesomezGuysAge);


Fixed that for you ;)

View PostKyek, on 27 December 2010 - 04:39 PM, said:

Congrats!

Congrats!

Well that sucks Congrats!

I know the feeling ;-)

It'll be good to have you around again! :)

lol
0


Share this topic:


  • 3 Pages +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users


Enter your sign in name and password


Sign in options
  Or sign in with these services