Let's say I have two SQL tables:
QYZ: id, uid<user id, FK*>, somedatacolumn
USERS: id<FK*>, name, surname
And $rows
is simply a list of rows from QYZ whe开发者_如何学编程n I run SELECT * FROM qyz
.
The objective is to generate an html table that looks like:
ID (of QYZ) | User | Data
1 | Aaa Bbb | xyzfghh
2 | Ccc Ddd | dfash
3 | Aaa Bbb | sdafdfa
The following code allows me to search in Data
, but not User
...
Please consider the following code:
// index.php?q=Something
// Note: the following could have been done through SQL,
// but let's consider it wasn't (I'm well aware of the consequences).
$search=$_REQUEST['q'];
foreach($rows as $i=>$row){
$found=false;
foreach((array)$row as $k=>$v){
if(stripos($v,$search)!==false){
$found=true;
break; // <- optimization
}
}
if(!$found)unset($rows[$i]);
}
// And somewhere later on...
echo '<table>';
foreach($rows as $row){
echo '<tr>';
foreach((array)$row as $k=>$v){
echo '<td>';
echo formatter($row,$k,$v); // <- in truth, I'm using call_user_func(),
// but for the sake of argument...
echo '</td>';
}
echo '</tr>';
}
echo '</table>';
// And maybe somewhere earlier, perhaps passed as a function argument...
function formatter($row,$column,$cell){
switch($column){
case 'uid':
$cell=getUser($cell)->name().' '.getUser($cell)->surname();
}
return htmlspecialchars(''.$cell,ENT_QUOTES);
}
I know it's a bit jumbled up. Hopefully it's not too difficult to understand. In short, here's what it does:
- we first filter out the database results ($rows) according a search term (search system is very basic, do not suggest alternative search engines, that's not the point).
- next we print a table of the search results using a formatting function...
- ...which we might have defined somewhere earlier*
- and which, using caching techniques, we print out mixed db data without any further queries (thus the reason I didn't
SELECT * FROM xyz, users WHERE xyz.uid=users.id
- it is important to note that as a side effect, I'm using getUser()
The problem? I can't search for user "John Doe" since at the time the search is done, only user IDs are known (formatting as done later on) [as well as the fact that user John Doe doesn't exist =P].
In this specific case, we could fix it easily with some specific coding (eg: adding getUser to search filter code). But sometimes, the formatting routine is quite complex, much more than just resolving an ID to a name, (such as parsing WikiMarkup or same advanced computations).
The logical solution would be to do the search at the end, ie after rendering the rows.
With output buffering(needed since some stuff in formatter() is written directly) and strip_tags
, this would be as easy as:
ob_start();
foreach($rows as $row){
foreach((array)$row as $k=>$v){
echo '<td>'.formatter($row,$k,$v).'</td>';
stripos(strip_tags(ob_get_contents()),$search)!==false
? ob_flush() : ob_clean();
}
}
ob_end_clean();
Basically, we flush the buffer if search query matches, otherwise, we clear the buffer.
Although I believe it ought to work, and might even require less CPU cycles, it sounds like a lot of content manipulation.
Oh, and come to think of it, scratch off output buffering - it makes absolutely no sense if I had to introduce pagination (which I have every intention to do so).
See where the problem lies? It needs to manipulate/search the generated data (search) to actually generate the right one. Sounds awfully inefficient in several counts.
PS: This is important. This system is generic, which is why I can't make it specific for certain situation.
The logical solution would be to do the search at the end, ie after rendering the rows.
Why? Your data access should get all the information needed to choose rows in one round of querying. If you're using a database, you should just be able to join tables together. If you're not using a database, I would question that decision.
As far as formatting/rendering, if the data to be displayed is homogeneous in structure (same for each row), then you should be able to get all that in the initial round of querying. If it's heterogeneous in structure, maybe you'd have to do additional queries later.
I would strongly suggest you decouple data querying and rendering as much as possible, otherwise you have one large and difficult-to-maintain problem instead of two smaller ones.
精彩评论