Search code examples
phpfat-free-framework

f3 / Fat Free Framework: why does the SQL-Mapper select function return all columns from a table?


Imagine a MySQL table with two columns, col1 and col2, queried by f3's SQL-Mapper like this:

$rows = $mapper->find();
$rows = $mapper->select('col1');

When using find both columns are queried and returned and one can access them like this:

... = $rows[0]->col1;
... = $rows[0]->col2;

When using select calling $rows[0]->col2 will return null, because col2 was not included in the string argument of the select method, which is fine.

Now when doing a var_dump I noticed that the select method returns all columns! Why is this?

I imagined the purpose of the select method would be to save resources on the database server by only querying for the specified columns. So what is the purpose of the SQL-Mapper: select method if it returns the full set of columns – we have the find method for that, don't we?


Solution

  • The purpose of the Fat-Free SQL mapper is to automatically map table columns to PHP object properties. This is done at instantiation time in DB\SQL\Mapper::__construct.

    So when you call $mapper->find() or $mapper->select(), the instantiation has already been performed and table columns have already been mapped to the $mapper object.

    This explains the results of your var_dump command.

    Now you can adjust the list of columns actually mapped, but that has to be done at instantiation:

    // map all columns
    $mapper = new DB\SQL\Mapper($db,'table_name');
    
    // only map col1 & col2 columns
    $mapper = new DB\SQL\Mapper($db,'table_name','col1,col2');
    

    Concerning the select() method, I'm wondering why this method has been made public. It is used internally by find(), but is not very handy to use on its own, considering that all the specified fields have to match declared columns at instantiation and that computed columns should be both aliased AND declared. See:

    $mapper = new DB\SQL\Mapper($db,'table_name','col1,col2');
    
    // ex.1: column not declared
    $results = $mapper->select('*');
    echo $results[0]->col3; // undefined field col3
    
    // ex.2a: computed column not aliased
    $results = $mapper->select('SUM(col1)');
    echo $results[0]->{'SUM(col1)'}; // undefined field SUM(col1)
    
    // ex.2b: computed column aliased but not declared
    $results = $mapper->select('SUM(col1) AS sum1');
    echo $results[0]->sum1; // undefined field sum1
    
    // ex.2c: computed column declared but not aliased
    $mapper->sum1 = 'SUM(col1)';
    $results = $mapper->select('SUM(col1)');
    echo $results[0]->sum1; // empty
    
    // ex.2d: computed column aliased and declared
    $mapper->sum1 = 'SUM(col1)';
    $results = $mapper->select('SUM(col1) AS sum1');
    echo $results[0]->sum1; // OK!
    

    As you can see, the usage of this method is very strict. I wouldn't advise to use it, unless you really know what you're doing. Use find() instead.