What does this doctrine query do? - php

$this->facebook_applications = Doctrine::getTable('FacebookApplication')
->createQuery('a')
->execute();
I don't understand how this works at all. Why is the query just 'a' and why does that seem to get a list of the applications?

The static method Doctrine::getTable() gets an object that represents the FacebookApplication table.
That object has a method called createQuery(), which creates a Doctrine_Query object for querying that table. The argment ('a'), specifies an alias for the table in the query.
So essentially Doctrine::getTable('FacebookApplication')->createQuery('a') creates a query that translates to SQL like:
SELECT * FROM FacebookApplication as a
Which, naturally, returns all rows from that table.

You can see it by using :
$this->facebook_applications->getSqlQuery()

Related

Allowed memory size exhausted with Propel2 custom query

(updates at bottom)
I'm trying to get the latest entry in my table called "VersionHistory", and since the ID is set to auto increment, I was trying to get the max id. Trying to stay away from sorting the whole table in descending order and taking the top as I want to minimize the computation required for this query as the table grows, and this table will probably get pretty huge fast.
class VersionHistoryQuery extends BaseVersionHistoryQuery {
public function getLatestVersion() {
return $this
->withColumn('MAX(version_history.id)')
->limit(1);
}
}
I'm calling the function in my VersionHistory constructor as below:
class VersionHistory extends BaseVersionHistory {
public function __construct($backupPath = "") {
$lastVersion = VersionHistoryQuery::create()
->getLatestVersion()
->find();
$lastVersion->setBackupPath("backup/" . $backupPath);
$lastVersion->save();
parent::setImportedAt(date("Y-m-d H:i:s"));
}
}
This outputs a "Allowed memory size exhausted" error in php. Any idea why? Commenting out the query in the VersionHistory constructor fixes the error, so it's somewhere in the query. I tried setting up a custom query following the instructions here: http://propelorm.org/documentation/03-basic-crud.html#using-custom-sql. But I couldn't get that to work. Running:
SELECT * FROM version_history WHERE id = (SELECT MAX(id) FROM version_history)
From MySQL workbench works fine and quickly.
Any ideas of what I'm doing wrong?
What I tried
Updated the code to:
public function getLatestVersion() {
return $this
->orderById('desc')
->findOne();
}
Still get the same memory allocation error.
Updated the code to:
$lastVersion = VersionHistoryQuery::create()
->orderById('desc')
->findOne();
Removed the custom function, turned on propel debug mode, it outputs that this query is run:
[2015-10-11 17:26:54] shop_reporting_db.INFO: SELECT `version_history`.`id`, `version_history`.`imported_at`, `version_history`.`backup_path` FROM `version_history` ORDER BY `version_history`.`id` DESC LIMIT 1 [] []
Still runs into a memory overflow.
Thats all:
SELECT * FROM version_history ORDER BY id DESC LIMIT 1;
From the documentation, withColumn does the following:
Propel adds the 'with' column to the SELECT clause of the query, and
uses the second argument of the withColumn() call as a column alias.
So, it looks like you are actually querying every row in the table, and also every row is querying the max ID.
I don't know anything about propel (except what I just googled), but it looks like you need a different way to specify your where condition.
Your raw SQL and your Propel Query are different / not equivalent.
In the propel query merely added a column, whereas is your raw SQL your actually have two queries with one being a sub-query to the other.
So you need to do the equivalent in Propel:
$lastVersionID = VersionHistoryQuery::create()
->withColumn('MAX(id)', 'LastVersionID')
->select('LastVersionID')
->findOne();
$lastVersion = VersionHistoryQuery::create()
->filterByVersionHistory($lastVersionID)
->find();
Note the ->select('LatestVersionID') since you only need a scalar value and not an entire object, as well as the virtual column (alias in SQL) using withColumn()

ZF2 where expression

In mu ZF2 project I have Model using TableGateway.
Inside function responsible for fetching objects based on search criteria (city, postal_code, range, type).
Generally I fetch rows of data by simple
$rowset = $this->tableGateway->select($where);
In my MySQL database I have procedure GetObjectsInCityRange(city, range) which returns all object_id in range of geocoded city coordinates
I intend to add in the where clause condition:
WHERE object_id IN (call GetObjectsInCityRange(city, range))
Is it possible with MySQL? How write correctly $where array element to make it work?
You can call a where() method in your select object and call in() on the return value or create a where statement.
E.g.
$select = new Select();
$select->from($this->tableName)->columns(array($expression));
$where = new Where();
$where->in($identifier, $valueSet);
// or
$where->addPredicate(
new Predicate\In($identifier, $valueSet)
);
// and then
$select->where($where);
and append it to the select object.
The link below is exactly what you need I believe :)
http://framework.zend.com/manual/2.1/en/modules/zend.db.sql.html#in-identifier-array-valueset-array
Hope this helps :)
For MySQL it is suggested that you should use function instead of procedure as function can be used in any sql query while procedure is itself a query like statement. Ex.
call MyPrcedure();
SET var = MyFunction();
So you can call function in your query most of the time. However as per my knowledge function will return valid mysql data-type like varchar, int float etc. So query rows may not be available in your In query. Then only way to execute your query to convert your procedure logic to a subquery and pass inside IN statement.
WHERE object_id IN (SUB_QUERY)

Doctrine 2 delete with query builder

I have two Entities with relation OneToMany, Project and Services. Now i want to remove all the services by project_id.
First attempt:
$qb = $em->createQueryBuilder();
$qb->delete('Services','s');
$qb->andWhere($qb->expr()->eq('s.project_id', ':id'));
$qb->setParameter(':id',$project->getId());
This attempt fails with the Exception Entity Service does not have property project_id. And it's true, that property does not exists, it's only in database table as foreign key.
Second attempt:
$qb = $em->createQueryBuilder();
$qb->delete('Services','s')->innerJoin('s.project','p');
$qb->andWhere($qb->expr()->eq('p.id', ':id'));
$qb->setParameter(':id',$project->getId());
This one generetate a non valid DQL query too.
Any ideas and examples will be welcome.
You're working with DQL, not SQL, so don't reference the IDs in your condition, reference the object instead.
So your first example would be altered to:
$qb = $em->createQueryBuilder();
$qb->delete('Services', 's');
$qb->where('s.project = :project');
$qb->setParameter('project', $project);
If you really can't get project object and you have to handle only with id you can use this.
Citation from doctrine documentation:
There are two possibilities for bulk deletes with Doctrine. You can either issue a single DQL DELETE query or you can iterate over results removing them one at a time. (Below I paste only first solution)
DQL Query
The by far most efficient way for bulk deletes is to use a DQL DELETE query.
Example that worked in my project
$q = $em->createQuery('delete from AcmeMyTestBundle:TemplateBlock tb where tb.template = '.intval($templateId));
$numDeleted = $q->execute();
In entity TemplateBlock I have property called template which is mapped to template_id in db.
But I agree that highly preferred way of doing it is using objects.

Is it possible to get the table from a PDOStatement object?

Say I have a PDOStatement object generated via PDO->query($query), is it possible to get the table it was executed on?
Something like this:
<?php
$statement = $pdo->query('SELECT * FROM `foo`;');
echo $statement->xyz;
// foo
I'm fully aware you can use $query->getColumnMeta(0)['table'] to do it, but as mentioned by the docs, it's not very safe. This needs to work across all PDO drivers.
You can retreive the name of the table using the PDOStatement that retrieves an associative array. The value ['name'] is the name of the table.
$select = $conn_pdo->query('SELECT * FROM foo');
$meta = $select->getColumnMeta(0);
echo "Name of table: ".$meta['table'];
You can check the query string:
$statement->queryString
Remember that a SQL query may reference multiple tables, or no tables, so there is no "table it was executed on". You could use regular expressions on the query string to find the first table referenced for standard queries (SELECT, INSERT, UPDATE, DELETE), but that may not be perfect.
Alternatively, use models to access your data, and you'll always know which tables are accessed by the model definition.
Can you not simply store the string used in the query and use simple string manipulations to access the table?

Count on Zend_Db_Select

Say I have a random zend_db_select object.
How can I perform a count on that object, so I know the amount of items that meet the query.
I tried the following:
$data->TotalRecords = $select->columns(new Zend_Db_Expr('COUNT(*)'))->query()->fetch();
But this gives me the following error:
Message: No table has been specifiedfor the FROM clause
The query by itself works fine and returns a resultset.
There's a couple of ways of specifying the columns to fetch in a Zend_Db_Select. The following two product the same SQL
$select = $db->select()
->from('myTable', array())
->columns(array('TotalRecords' => new Zend_Db_Expr('COUNT(*)')));
$select = $db->select()
->from('myTable', array('TotalRecords' => new Zend_Db_Expr('COUNT(*)')));
The from method takes a first argument, the table name, and a second argument, an array of columns to fetch. If you're using an expression, you can specify a 'key' => Expr.
It's really easy to convert a Zend_Db_Select into a SQL string for debugging or use with other functions.
echo $select; // prints SELECT COUNT(*) AS `TotalRecords` FROM `myTable`
This uses a toString method, which is called automatically by Zend_Db fetch methods:
$total = $db->fetchOne($select);
echo $total; //prints the number of rows matching the query
Where $db is an instance of Zend_Db.
Use $select->__toString() method to output your generated query and see what is wrong with it.
If u dont have a from clause in your query add From() method to your select object.
If you use Zend_Db_Select, you have to call the from method to set the table name. With a Zend_Db_Table_Select, the table is passed in the constructor, so you don't need to call from.
$select = $db->select();
$select->from(
'table_name',
array('cnt' => 'count(1)')
);
I just encountered the same issue and found out what is going wrong
the Zend_Db_Select::columns functions expects an Array instead of a Object or String (when the first parameter is an String or Object it'll probably use this as main table for the columns you give but Im not sure about that.).
Changing your code to
$data->TotalRecords = $select->columns(array(new Zend_Db_Expr('COUNT(*)')))->query()->fetch();
Will fix your issue

Categories