ZF2: How to do this simple query with Zend\Db - zend-framework2

I have the following statements but they return an empty result set:
$sql = 'SELECT * FROM `industry` WHERE `code` LIKE ?';
$statement = $this->getAdapter()->createStatement($sql, array('A_'));
$statement->execute();
What am I doing wrong? I really don't want to use the Zend\Db\Sql\Sql, as it is very verbose.
On a related point, where can I go to find out more about the theory of operation for Zend\Db? It's absolutely maddening. Why does it sometimes return a driver result? Sometimes a ResultSet? How can you view the complete SQL (after quoting, but before execution?) Etc...

OK, I had missed the fact that a Result is iterable (as well as a ResultSet). Therefore, assigning the result of $statement->execute() to a variable, then iterating that variable, sorted out the problem.
Futhermore, you can call getResource() on the result object, and from there access the underlying object (in this case, a PDO Statement). This means you can do things like result->getResource()->fetchAll();

Try with this query.
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Sql;
class tableNameTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
Publice function getIndustry(){
$adapter = $this->tableGateway->getAdapter();
$statement = $adapter->query("Your Query");
$results = $statement->execute();
return $results;
}
}

Related

Jena - Find statements by property and object class

I'm looking for the way how to get all statements from my model by its property and by a class of an object.
For example I have property :driverOf and individuals either of type Bus or Truck. Then I want to get all statements where the property is :driverOf and the object is instanceOf Bus. Thanks.
UPDATE 1
Actually I need the result to be a set of statements (resp. StmtIterator) because in my app I use statement objects already. I think the most clean solution would be to have subproperties of :driverOf property, something like :driverOfBus and :driverOfTruck. But it would make my app more complicated, so I would like to find out some simple workaround.
You could use sparql query. You have to replace labels with full namespaces.
String queryString =
"SELECT ?x WHERE { ?x driverOflabel ?y . {?y a Buslabel} UNION { ?y a Trucklabel} . }";
Query query = QueryFactory.create(queryString);
QueryExecution qexec = QueryExecutionFactory.create(query, YOURMODEL);
try {
ResultSet results = qexec.execSelect();
while(results.hasNext()) {
QuerySolution soln = results.nextSolution();
System.out.println(soln.toString());
}
} finally {
qexec.close();
}
I hope i understood this correctly:
Say you have model m and namespace NAMESPACE
// Get the property and the subject
Property driverOf = m.getProperty(NAMESPACE + "driverOf");
Resource bus = m.getResource(NAMESPACE + "bus");
// Get all statements/triples of the form (****, driverOf, bus)
StmtIterator stmtIterator = m.listStatements(null, driverOf, bus);
while (stmtIterator.hasNext()){
Statement s = stmtIterator.nextStatement();
Resource busDriver = s.getObject();
// do something to the busdriver (only nice things, everybody likes busdrivers)
}

ZF2 : Change a row field in ResultSet

I want to change a row field in my ResultSet before returning it to my Controller.
$resultSet->buffer();
foreach ($resultSet as $row) {
$row->foo = $newvalue;
}
return $resultSet;
Problem is, when I use the buffer() function I can indeed loop over my ResultSet and make some changes on my rows, but once the loop ends all changes are gone.
I tried to set up a reference on $row :
foreach ($resultSet as &$row)
But then caught the following exception :
Fatal error: An iterator cannot be used with foreach by reference
I also tried to change resultSet to array but the same problem occurs.
Have I missed something ?
I don't think it is possible via the usual ResultSet usage. The array solution might work only if you are going to use the array in loops (foreach() in this case).
From any Table class -
$arr_resultSet = array();
foreach ($resultSet as $row) {
$row->foo = $newvalue;
//Object is assigned instead of converting it to an array.
$arr_resultSet[] = $row;
}
return $arr_resultSet;
Usage of this array in controller or view file -
//Here you can access that $row object as if the $resultSet was never converted to array.
foreach($arr_resultSet as $row) {
echo $row->foo;
}
No need of buffer(). I hope it works for now. Will definitely search for a proper solution.

Object == Object2 when stored in List<T> but not when object in IEnumerable<T> - WHY?

Using ASP MVC5 and EF6.
I had a curious case the other day when I was looking to have different behaviour when a foreach-loop got to the last element.
The loop wouldn't enter if-condition comparing the object with the result from .Last()-method on the collection.
The collection I was iterating over was something like:
public class CollectionClass{
IEnumerable<TestClass1> CollectionA
IEnumerable<TestClass2> CollectionB
}
My code was something like:
DbContext db = new DbContext(); //just for illustration, not actual code
CollectionClass cc = new CollectionClass {
CollectionA = db.TestClasses1,
CollectionB = db.TestClasses2
};
//(TestClasses1 and TestClasses2 are DbSet<T> properties of my DbContext.
foreach(TestClass1 tc1 in cc.CollectionA)
{
if (tc1 == cc.CollectionA.Last()){ //<---NEVER enters in here!!
//doStuff
}
else{
//doOtherStuff
}
}
With the code above, the loop never entered into the if-condition, even for the last element, which one would expect.
But when changed my CollectionClass to:
public class CollectionClass{
List<TestClass1> CollectionA
List<TestClass2> CollectionB
}
and instantiated the CollectionClass-object like this:
CollectionClass cc = new CollectionClass {
CollectionA = db.TestClasses1.ToList(),
CollectionB = db.TestClasses2.ToList()
}; //Added .ToList()
the loop entered into the first if-condition at the last iteration as I expected.
Why this difference? Why did the equals-operator (==) evaluate to TRUE when the object had been stored in a List and FALSE when the object was stored in an IEnumerable?
I know that IEnumerable is an interface -- is that what makes the difference?
I even did an explicit test in the sorts of:
var obj1 = cc.CollectionA.Last();
var obj2 cc.CollectionA.Last();
bool result = obj1 == obj2; //result = FALSE
and the result was FALSE.
I think it's because in first example you get two objects from database. First from iteration and second from call to Last().
In second example all objects are created at the time you assign collections to CollectionA and CollectionB (you call ToList()).
It is because you are not allowed to use Last and LastOrDefault on DbSet objects. Instead you should use OrderByDescending(t=>t.ID).First()

zf2 select columns from joined tables - how?

I feel like I must me missing something very simple. It's a very simple task, all I want to do is get something like:
SELECT * FROM lookup_items
JOIN lookup ON lookup_items.lookup_id = lookup.id
This returns all the columns for all the joined tables, in regular SQL. Here's my attempt in zf2:
$select = new Select();
$select->from('lookup_items');
$select->join('lookup', 'lookup_items.lookup_id = lookup.id');
The result set only includes the columns in 'lookup_items'. I've tried various ways to get the 'lookup' columns, including:
$select->columns(array('lookup_items.*', 'lookup.*'));
But they all just blow up. Surely there's a way to do this, and it's just so simple I'm missing it completely.
I thought a simple example would be avoid confusion, but here's more code:
class LookupItemsTable extends AbstractTableGateway
{
public function getList($resource)
{
$system_name = str_replace('*', '%', strtoupper($resource));
$joinTable = 'lookup';
$select = new Select();
$select->from($this->table);
$select->join($joinTable, "{$this->table}.lookup_id = {$joinTable}.id");
$where = array();
$where[] = "{$this->table}.enabled is true";
$where[] = "{$joinTable}.enabled is true";
$where[] = "UPPER({$joinTable}.system_name) ilike '{$system_name}'";
$select->where($where);
$sort[] = 'sort_order ASC';
$sort[] = 'value ASC';
$select->order($sort);
$rowset = $this->selectWith($select);
return $rowset;
}
}
Where:
$resource = $this->params()->fromRoute('resource', 'BUSINESS');
And $this->table is 'lookup_items'. Really all I want to do is get columns from both joined tables. I guess there's a zf2 way to just make a straight SQL statement without all the OO falderal, so I could just force it that way. But I'd rather work within the framework as much as possible.
Just change this line
$select->join('lookup', 'lookup_items.lookup_id = lookup.id');
to
$select->join('lookup', 'lookup_items.lookup_id = lookup.id', array('lookupcol1', 'lookupcol2');
Raj answer is the best one but it only works if you don't forget to add these fiels in your LookupItems model.
class LookupItems
{
// Your lookup_items fields here...
...
// And the added lookup fields here, the ones you add in the array
public $lookupcol1;
public $lookupcol2;
And in the exchangeArray method :
public function exchangeArray($data)
{
// .... your fields, and the new ones
$this->lookupcol1 = (! empty($data['lookupcol1'])) ? $data['lookupcol1'] : null;
$this->lookupcol2 = (! empty($data['lookupcol2'])) ? $data['lookupcol2'] : null;
}
I figured it out.
Added this:
$select->columns(array('*'));
And then this near the end:
$sql = new Sql($this->adapter);
$statement = $sql->prepareStatementForSqlObject($select);
$rowset = $statement->execute();
This returns the expected result, with the caveat that now my rows are returned as associative arrays instead of objects.
This is how you can create queries with join in zf2.
$resultSet = $this->select(function (Select $select) {
// omit the table name
//$select->from('foo');
$select->join('users', "users.id foo.createdby", 'firstname', '');
$select->order('id ASC');
// echo $select->getSqlString();// to print your query
});
$entities = array();
foreach ($resultSet as $row) {
$entity = new Entity\Foo();
$entity->setId($row->id)
->setFullname($row->fullname)
->setCaseid($row->caseid)
->setTestimonial($row->testimonial)
->setSortorder($row->sortorder)
->setActive($row->active)
->setCreated($row->created)
->setModified($row->modified)
->setFirstname($row->firstname)
->setCreatedby($row->createdby);
$entities[] = $entity;
}
return $entities;

Why sql.rows Groovy method is so slow

I tried to fetch some data with the sql.rows() Groovy method and it took a very long time to return the values.
So I tried the "standard" way and it's much much faster (150 times faster).
What am I missing ?
Look at the code below : the first method returns results in about 2500ms and the second in 15 ms !
class MyService {
javax.sql.DataSource dataSource
def SQL_QUERY = "select M_FIRSTNAME as firstname, M_LASTNAME as lastname, M_NATIONALITY as country from CT_PLAYER order by M_ID asc";
def getPlayers1(int offset, int maxRows)
{
def t = System.currentTimeMillis()
def sql = new Sql(dataSource)
def rows = sql.rows(SQL_QUERY, offset, maxRows)
println "time1 : ${System.currentTimeMillis()-t}"
return rows
}
def getPlayers2(int offset, int maxRows)
{
def t = System.currentTimeMillis();
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
statement.setMaxRows(offset + maxRows -1);
ResultSet resultSet = statement.executeQuery(SQL_QUERY);
def l_list =[];
if(resultSet.absolute(offset)) {
while (true) {
l_list << [
'firstname':resultSet.getString('firstname'),
'lastname' :resultSet.getString('lastname'),
'country' :resultSet.getString('country')
];
if(!resultSet.next()) break;
}
}
resultSet.close()
statement.close()
connection.close()
println "time2 : ${System.currentTimeMillis()-t}"
return l_list
}
When you call sql.rows, groovy eventually calls SqlGroovyMethods.toRowResult for each row returned by the resultSet.
This method interrogates the ResultSetMetaData for the resultSet each time to find the column names, and then fetches the data for each of these columns from the resultSet into a Map which it adds to the returned List.
In your second example, you directly get the columns required by name (as you know what they are), and avoid having to do this lookup every row.
I think I found the reason this method is so slow : statement.setMaxRows() is never called !
That means that a lot of useless data is sent by the database (when you want to see the first pages of a large datagrid)
I wonder how your tests would turn out if you try with setFetchSize instead of setMaxRows. A lot of this has to the underlying JDBC Driver's default behavior.

Resources