-1

The question boils down to finding the proper way how to getPrimaryKey when iterating over a yielded result. When using select method, the result is an object of ArrayCollection which doesn't provide the getPrimaryKey method. A simple snippet

$q = UserQuery::create();
$q->select('a', 'b'); //yields an ArrayCollection object, doesn't have getPrimaryKey method when iterated
$q->find();

However,

$q = UserQuery::create();
$q->find(); //yields an ObjectCollection object, has getPrimaryKey method when iterated

Update

I have tried to use the setFormater to force using the ObjectCollection. Ultimately, it resulted in exception being thrown.

$q = UserQuery::create()
         ->setFormater(ModelCriteria::FORMAT_OBJECT)
         ->select('a', 'b')
         ->find();  //Error populating object

Update 2

Providing an exact use case, since it may be unclear at first what I am looking for. I have a table with >100 columns. I am providing the functionality using behaviour to not disable (not select) some of them. Thus, I am unseting some of the columns, and basing the $q->select on the remaining ones.

if (!empty($tableQuery->tableColumnsDisable)) {
    $columns = $tableQuery->getTableMap()->getColumns();

    foreach ($columns as $index => $column) {
        if (!empty($tableQuery->tableColumnsDisable[$column->getName()])) {
            unset($columns[$index]);

            continue;
        }

        $columns[$index] = $column->getName();
    }

    //TODO - returns array collection, object collection needed
    $tableQuery->select($columns);
}
sitilge
  • 3,687
  • 4
  • 30
  • 56

1 Answers1

1

When using select(), Propel will skip object hydration and will just return an ArrayCollection containing an array for each result row. To retrieve the id of each result row, you need to add the column name to the select(). You can then just retrieve the value from the row arrays by using the column name:

$users = UserQuery::create()
    ->select(['id', 'a', 'b'])
    ->orderBy('c')
    ->find();

foreach ($users as $user) {
    $id = $user['id'];
}

The select functionality is described in the documentation and in the docblock of Propel\Runtime\ActiveQuery\ModelCriteria#select() (source).

When you are using Propel 1, the functionality is the same. Read more about it in the Propel 1 documentation or the docblock of ModelCriteria#select() (source).

Pieter
  • 1,764
  • 1
  • 12
  • 16
  • No, it is not said that `id` is the primary key. Moreover, the primary key can be (and will be in some cases) composite, meaning that is consists of more than just a single column. The goal here is to have `ObjectCollection` in order to have the `getPrimaryKey` working. Also, `setFormater` throws an exception (see the update). – sitilge Jun 17 '16 at 08:25
  • You can replace `id` with whatever the name of your primary key column is. If you want to retrieve entity objects, you cannot use `select()`. This is because Propel needs all row data to be able to hydrate the objects. – Pieter Jun 17 '16 at 08:29
  • The idea is that I am purposely not aware of the exact primary key columns. I am iterating over `tableMap->getColumns` and excluding some of them. I am using behaviours to generate some extra methods I need to provide. TL;DR - imagine a table with 100 columns. I am providing the functionality using behaviour to not disable (not select) some of them. Thus, I am unseting some of the columns, and basing the `q->select` on the remaining ones. Updated the question. – sitilge Jun 17 '16 at 08:36
  • Gotcha; that's a pretty bad idea though. You would probably be better off either removing the columns from the database schema definition xml file or define separate views within your database so you can handle them within Propel the normal way. If you really want to go the dynamic select column route, you will need to manually hydrate the entities with the partial array data. – Pieter Jun 17 '16 at 08:54
  • Finally, we are on the same track :) so my question to you is as follows: what is the best way to disable a column by not editing the schema but rather modifying the respective table/tableQuery subclass (that would the preferred in my case)? – sitilge Jun 17 '16 at 09:09
  • You would probably need to override the object `hydrate` method to allow column values to not be defined in the `$row` data. – Pieter Jun 17 '16 at 11:49