| SitePoint Sponsor |




Not method chaining, but I just thought I'd draw attention to other libraries which by-pass writing raw SQL in your code. You could go with a simple DB abstraction layer like ADODB or Creole, or you could go a step further and jump into ORM. Take a look at Propel (which uses Creole). Symfony uses this and has a nice overview of it in their documentation:
http://www.symfony-project.com/book/...he-Model-Layer
~ctx2002, abstraction is a good thing, albeit this approach seems pretty counter-intuitive internally, but readable to end-users anyway.
"but readable to end-users anyway." then how do you define end-users here? for me, i define "end-user" as computer programmer, that sql statement method chaining just totally wrong for me.


I use method chaining but in this fashion.
I don't see anything wrong with that, I think it's pretty legible, but if you present it to someone who is unfamiliar with method chaining, then perhaps it could be a little hard to read.PHP Code:// just an example
$this->_injector
->getRequest()
->getURI()
->getAction(); // returns string.
I see it more an "order of execution" than a description of relationships.
Noticing that this thread has somehow acquired statement preparation object(s) as a side note, I'm curious as to what advantage they'd have over writing up actual SQL statements.
On the subject of legibility, at a glance, I for one find it easier to read scripted SQL statements like:
OverPHP Code:$sql = "SELECT `some_id`, `some_name`, `some_surname`
FROM `some_table`
WHERE `some_id` = {$this->escape($someID)}
So then aside from creating wrappers around built in objects like PDO and MySQLI which has been benchmarked to "speed up" execution (sorry that's the first relevant documented benchmark I could find), what else would be the advantage to doing things this way?PHP Code:$db->select('some_id, some_name, some_surname')
->from('some_table')
->where('some_id',$someID);
Regards,
RV David
Web Development Blog
very true, raw sql statement has more readability.
i think that author of codeignite want to use method chaining pattern, but she/he actully used a "template" pattern that ask coder to fill in "sql blank".
regards


I'm sure they have their reasons, like reusing a premade db abstraction package for instance like Symfony has with Propel as their ORM layer.
Off Topic:
ctx2002 vs CodeIgniter
Round one... FIGHT!
sorry I was bored, so I thought I'd make vbboard art
Last edited by rvdavid; May 10, 2007 at 18:55. Reason: changed the word "fight" to uppercase.
RV David
Web Development Blog
My motivation to use the array way for the interface: (May someone has an idea how to build such a system with "fluent interfaces"?)
I was searching for an interface to communicate with the model (mvc). the criteria are :
- pluggable
- module support
- loose coupled
- independed
So i have found the following solution with characteristics:
A model class with 3 public methods which play the role of the model interface. The model itself consists of actions classes.:
1. $model-action( 'module_name', 'action_class_name', [ array data ] )
Is sending an action call to a single action class
PHP Code:ex.: $model->action('article', 'get_article',
array('result' => & array,
'id_article' => int,
'fields' => array('id', 'title')
))
2. $model->broadcast( 'action_class_name', [ array data ] )
Is sending an broadcast action call to all modules:
PHP Code:ex.: $model->broadcast('init')
3. $model->broadcast2( array of module_names, 'action_class_name', [ array data ] )
Is sending an broadcast action call to defined modules.
Each of those action classes consists at least of 2 public methods which are executed by the model class:PHP Code:ex.: $model->broadcast2( array('article','navigation'), 'init' )
- validate / do some validation of the data array
- perform / execute the real job
the perform method is only executed when the validate methode returns true else it throws an exception.
The characteristics of this interface are:
- If an action class dosent exists the system dosent hangs
- plug&play of model action classes
- Even callable from within action classes itself. So you can build complex action blocks (LEGO like)




In general, abstraction and security. You can hide some differences between DBMSes. And noticing your use of $this->escape(), you're implying that this is happening automatically behind the scenes in the other example. That would help you not forget about it.
I just happened to hear Derick Rethans present eZ Components yesterday. They do something similar to your second example.
Dagfinn Reiersøl
PHP in Action / Blog / Twitter
"Making the impossible possible, the possible easy,
and the easy elegant" -- Moshe Feldenkrais


Just for an FYI, the mentioned behavior (although a 'feature' of CodeIgniter) is not the only way to do things. I personally don't care for that format and I use the simply $db->query($sql); approach




While I find the CodeIgniter example very easy to read, and it looks like something I would wanna use myself, I do have one question: do I need to create different DB objects for every query? 'Cause to me, this:
...looks like it is changing internal members of the DB object. But what if I want to do a second query later, like this:PHP Code:$db->getFields('title')->from('mytable')->where('id', $id);
if ($_GET['all'] != 'true') {
$db->limit(10);
}
$result = $db->retrieve();
...the "limit" member of the object would still be altered. Wouldn't that screw up my query? Of course, I know nothing of the inner workings of CodeIgniterPHP Code:$db->getFields('title')->from('mytable')->where('id', $id);
$result = $db->retrieve();
![]()


No, it would not affect it. After each final query ($db->get();) all the fields are reset.
Full information regarding this can be found here:
http://codeigniter.com/user_guide/da...ve_record.html




This is used in PHP (and Java) to work around its syntactic limitations. I think it tries to emulate Smalltalk style:Code:$this->db->select('title')->from('mytable')->where('id', $id)->limit(10, 20);
No sane Smalltalk programmer would write such a method though. This is a single method named select:from:where:equals:limit:to:, equivalent to this PHP:Code:db select: 'title' from: 'mytable' where: 'id' equals: id limit: 10 to: 20.
But because this PHP code is unreadable they use multiple method calls.Code:$db->selectFromWhereEqualsLimitTo('title', 'mytable', 'id', $id, 10, 20)
P.S. A limit 10,20 and a fixed id?




Sorry, but the whole idea of using OOP syntax to construct queries is a complete nonsense. Those are two orthogonal concepts, and they don't have much in common.
The point of OOP is to think in terms of objects, where you decide what objects you need (e.g. a collection of widgets) and define how those objects are constructed (e.g. their data are pulled from a database). Then you resolve that construction internally (e.g. you write an optimized SQL query, or you use some generic helper object like an Active Record), and you expose the object's interface to the world. That's it.


Hi
Ah thanks, I see that now (awesome), but still, the whole concept feels unnatural and seems to be trying to solve a problem that doesn't need solving.
I can see the advantages of abstraction here, It'd certainly be a great help to my team and I should stakeholders decide to change RDBMSes - we have a 60+ table database each with a Table Data Gateway object and a payload of methods.
But still how often are you going to change dbs? and even if we did, how many days gain are we really making? I'd say 1 day to implement changes and another day to test.
Regarding security... hmmm well, I think the developer should be knowledgable enough to KNOW to escape variables and not really forget to?PHP Code:$db = new MySQLQuery(); // if I changed dbs to postgres, then I could use a PostgressQuery object instead and that's the end of it - Ideally anyway.
$db->select('somefield, otherfield, anotherfield')
->from('someTable')
->where('someId', $someId');
I see it more as a convenience thing than anything - just so that you don't have to remember. I guess.
But compare this convenience and a solution to an exceptional scenario
to the legibility of SQL statements.
I see and like the advantages, but they seem unjustified - it just doesn't seem worth the trouble. Well in my POV anyway.
Regards,
RV David
Web Development Blog

Method chaining makes perfect sense, and even though it's somewhat confusing for non-MVC PHP developers, the syntax can be cleaned up a bit such as in rvdavid's example. And there's nothing really wrong about the CI way of working with databases as far as I can see, plus the syntax looks cool =D
Personally, though, I would add methods that execute raw constructed SQL to a model and then call that method from the model e.g. $this->db->getUsers(). I would rather escape data properly and do my own input validation (or use reasonable, flexible, inbuilt methods from a framework) than call chained methods to construct an SQL query.
Using chained methods like this just makes syntax a whole lot more verbose, however, and there can't be methods for every type of query - does CI have a REPLACE INTO method, for instance? I don't mind using either $this->db->select(), $this->db->update() and similar syntax; or $this->db->getUsers() style syntax with my own method defined, but mixing and matching doesn't seem like the best idea.
Check out my SitePoint articles and blog posts!





That way of thinking has landed more than one PHP programmer (and project) in hot water. It is also one of the prime reasons why PHP has a bad security reputation.
Doing things right should be easy, doing it wrong should be hard.
There is also a performance issue here. Calculating a query plan for a complex query can be expensive: The optimizer has to look up indexes, consider many, many alternative ways (nested loops, full table scans, value distributions etc.). For this reason most serious database systems will cache execution plans, but they will do so using the literal sql as key.
By using parameterized queries you enable the database system to reuse query plans for different set of parameter values. By using a variable interpolated query the execution plan can really only be reused for the same set of parameter values.
And finally, as mentionened above, the abstraction issue. SQL server uses [Column] and not `Column`. With interpolated sql it is really hard to write portable SQL. With synthesized SQL this is a lot easier.


Why do you think virtually every C application has a buffer overrun problem? People forget these things, get sloppy and what not. Security should really be as automatic as it can be, because you shouldn't have to take the risk of forgetting it. One very favorable way to do that might be with StringBorg or using an abstraction layer, it should not be up to the programmer.




Come off it, you can still be aware of having to escape data for insertion into SQL without actually doing it manually each time. I'll say it again, abstraction is a good thing.


Hi there,
I disagree. well, about the prime reasons why php has a bad security reputation anyway.
The reason that PHP has a bad security reputation is because of the level of entry. Not because developers think that other developers should know to escape data.
I say level of entry because those who have begun programming PHP would not have had prior knowledge or tertiary level education of "best and secure practices" in software development.
While to a certain extent it IS the assumption that people should know to escape data is the root of some security flaws (php doesn't escape your data for you :P ), this could be said of any other language that does not escape their data.
The big difference is that programmers of other languages have had best and secure practices drummed into them from the second they step into the classroom. Whereas php gained it's popularity by attracting newcomers who have had little or no exposure to such concepts.
One week after learning about for loops and myql_query() newcommers unleash unsecured sites and apps which are sent for public consumption and are then taken as a "standard" php app.
The developer responsible for this should be THROWN into hot water because his application is insecure and people purchasing will have to nut out and support his spaghetti code. This is the story with many PHP Apps and because there are so many of them, it became regarded as THE standard way to build a PHP site/app - an insecure, unescaped POS.
I think this itself gives PHP the bad security reputation, not the assumption or expectation that professional php developers or developers in general should know and remember to escape data themselves which is what I was talking about.
Performance issues are a moot point at this stage because unless you had a buttload of data to process, then it's a useless arguement. However, if it got to a stage where I had to squeeze apps for optimisation, then I'd be looking at using the built in mysqli prepared statements and even then I'd only do it to a select few.
Last thing,
there's nothing hard about escaping data. at all. I mean come on... Escaping data is hard? Since when?
I think you're both over reacting and are just thinking up of scenarios that might, or could easily happen and while "common-sensical" (yes that's a term now) and has some possibility of occurring, I think it is on the same level as the old "designers don't know how to type <?php echo $templateVar; ?> so we'll create a templating system with a new language the these designers can understand" idea that template engines have.
dbms abstraction, I can see a use for though very rarely would you use this and as I've said in previous reply, it'd probably take 2 days tops to switch - if you were going to go table for table. Performance? ok, there are rare occasions I'll have a use for that, I'll buy that, but securing against people forgetting to escape their variables? no.. I can't take that at all.
People aren't dumb, other people think people are dumb...
Off Topic:
(sorry I was trying to come up with a one liner to contra the profound one liner "Doing things right should be easy, doing it wrong should be hard." - as you can see I failed... quite miserably might I add.).
regards,
RV David
Web Development Blog


Last edited by rvdavid; May 12, 2007 at 05:56. Reason: removed smiley - because I wanted to appear serious when making this comment to agree with d11wtq
RV David
Web Development Blog

Check out my SitePoint articles and blog posts!





> People aren't dumb, other people think people are dumb...
Well, I would disagree with you; For the vast majority of PHP developers without a proper CS background, they are uneducated and yes, they are dumb.
People though, in general are dumb anyways; That is why we have leaders in goverment to help for the most part, to stop dumb people doing dumb things, either to themselves, or others. Look at the recent fiasco of the Scottish local elections? 124,000 people didn't get it right but to vote it was so simple...
I got it right, so why not those 124,000? That is because they are dumb...
Parametrised queries solve these problems, while still allowing the programmer to write queries in SQL.
The only thing, which parametrised queries doesn't do for you, is the ability to dynamically construct a query. This can be useful in certain cases, and in those cases, I would use an abstraction layer to construct the SQL. But I definitely wouldn't use it as the default interaction with a RDBMS. SQL is a far superior for this.


The problem is broader than just SQL injection, think about arbitrary shell execution, cross side scripting, regular expressions that can be injected and every other "guest platform" (as defined in the StringBorg link I posted earlier). Yes, it can be solved using parametrised queries but that seems like an ah hoc solution to a general problem.


RV David
Web Development Blog
Bookmarks