Aggregate Functions in extbase typo3 - typo3

I am using extbase-query-method ( like , in ,contains ).
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
$query->equals("deleted", "0"),
$query->equals("hidden", "0"),
$query->equals("status", $status)
)
);
return $query->execute();
but how can i used Aggregate Functions in extbase query statement.

As far as I know, Extbase doesn't support the use of aggregate functions in the ORM. See more here: https://docs.typo3.org/typo3cms/ExtbaseFluidBook/6-Persistence/3-implement-individual-database-queries.html
You will have to build the SQL query yourself (in the statement) and to tell the query to return raw result (that is stored in an array) instead of returning an object based query.
Exemple:
$query = $this->createQuery();
$query->statement("SELECT AVG(clicks) as 'avg' FROM tablename ...");
$query->getQuerySettings()->setReturnRawQueryResult(TRUE);
$result = $query->execute()[0][avg];
Cheers,
Olivier

I think the only solution for Extbase Query is
$query->statement('SELECT AVG(clicks) FROM tablename ...')
Or not?

If you use Plain SQL Statements, you have can get problems with sql injection!
A better way should be using the new doctrine querybuilder which is since 8.7 available:
// SELECT COUNT(`uid`) FROM `tt_content` WHERE (`bodytext` = 'klaus')
// AND ((`tt_content`.`deleted` = 0) AND (`tt_content`.`hidden` = 0)
// AND (`tt_content`.`starttime` <= 1475580240)
// AND ((`tt_content`.`endtime` = 0) OR (`tt_content`.`endtime` > 1475580240)))
$count = $queryBuilder
->count('uid')
->from('tt_content')
->where(
$queryBuilder->expr()->eq('bodytext', $queryBuilder->createNamedParameter('klaus'))
)
->execute()
->fetchColumn(0);
https://docs.typo3.org/typo3cms/CoreApiReference/latest/ApiOverview/Database/QueryBuilder/Index.html

As others have pointed out, you cannot use these functions on the Query object itself. However, you could use the ExpressionBuilder class for something like this:
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('my_awesome_table');
$statement = $queryBuilder
->select('uid')
->addSelectLiteral(
$queryBuilder->expr()->max('interesting_field', 'awesome_alias')
)
->from('my_awesome_table')
->groupBy('interesting_field')
->execute();
Note that this returns a QueryResult object.

The only function you can use is COUNT() with
return $query->execute()->count();
For all other functions you have to do a native query, like described in other answers

Related

TYPO3: Translated mm records in command controller

I am trying to get the translated records from the command controller by calling a function from extension repository like this.
function findAllForLang($lang){
//$lang = 1;
$query = $this->createQuery();
$query->getQuerySettings()->setRespectSysLanguage(false);
$query->getQuerySettings()->setLanguageMode(false);
$query->getQuerySettings()->setLanguageUid($lang);
$query->getQuerySettings()->setLanguageOverlayMode('hideNonTranslated');
$query->matching(
$query->logicalAnd(
$query->equals('sys_language_uid', $lang),
//$query->equals('mmfield.sys_language_uid', $lang)
)
);
return $query->execute();
I am getting the translated records. But the mm inline records are not translated and getting the default language records.
Is there any specific way to get all the translated inline records ?
TYPO3 version is 8.7.20
Thank you
There is a longstanding bug regarding fetching of translated relations with Extbase: https://forge.typo3.org/issues/57272
It was fixed for TYPO3 v9+.
For your case I suggest to build the query yourself with the (newer) doctrine-dbal API:
https://docs.typo3.org/m/typo3/reference-coreapi/8.7/en-us/ApiOverview/Database/QueryBuilder/Index.html

zendframework 2 select max of a column

I'm using ZendFramework 2 and TableGateway which is fine for normal select statements. But I can't seem to find how to get a max of a column using ZendFramework 2 select.
My select should look something like
SELECT MAX( `publication_nr` ) AS maxPubNr FROM `publications`
and my code looks like:
use Zend\Db\TableGateway\TableGateway;
class PublicationsTable
{
protected $tableGateway;
...
public function getMaxPubicationNr()
{
$rowset = $this->tableGateway->select(array('maxPubNr' => new Expression('MAX(publication_nr)')));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not retrieve max Publication nr");
}
return $row;
}
If you look at the TableGateway you will notice the parameters for the Select method are actually passed to the Where part of the Query, which is making your query incorrect.
You need to modify the Select Object directly as the TableGateway won't give you any proxy methods to do this.
You could try something like this:
public function getMaxPubicationNr()
{
$select = $this->tableGateway->getSql()->select();
$select->columns(array(
'maxPubNr' => new Expression('MAX(publication_nr)')
));
// If you need to add any where caluses you would need to do it here
//$select->where(array());
$rowset = $this->tableGateway->selectWith($select);
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not retrieve max Publication nr");
}
return $row;
}
I've not tested it, but that should just about get you there :)
You will probably bump into another issue though, and that will be due to the TableGateway trying to build you an object from the result, but you aren't bringing back a full row to build an object, you're just bringing back a single Column.
I would just add use the Db/Select objects to do this and not bother with the GateWay to be honest, I don't think it's supposed to be used like this.

zend framework 1.11.5 is choking on search function - mysql db

ZF 1.11.5 is puking all over this search function. i've tried creating the query several different ways, sent the sql statement to my view, copied and pasted the sql statement into phpMyAdmin and successfully retrieved records using the sql that ZF is choking on. i have been getting a coupld of different errors: 1) an odd SQL error about 'ordinality' (from my Googling ... it seems this is a ZF hang up .. maybe?) and 2) Fatal error: Call to undefined method Application_Model_DbTable_Blah::query() in /blah/blah/blah.php on line blah
public function searchAction($page=1)
{
$searchForm = new Application_Model_FormIndexSearch();
$this->view->searchForm = $searchForm;
$this->view->postValid = '<p>Enter keywords to search the course listings</p>';
$searchTerm = trim( $this->_request->getPost('keywords') );
$searchDb = new Application_Model_DbTable_Ceres();
$selectSql = "SELECT * FROM listings WHERE `s_coursedesc` LIKE '%".$searchTerm."%' || `s_title` LIKE '%".$searchTerm."%'";
$selectQuery = $searchDb->query($selectSql);
$searchResults = $selectQuery->fetchAll();
}
here's my model ....
class Application_Model_DbTable_Ceres extends Zend_Db_Table_Abstract
{
protected $_name = 'listings';
function getCourse( $courseId )
{
$courseid = (int)$courseId;
$row = $this->fetchRow('id=?',$courseId);
if (!$row)
throw new Exception('That course id was not found');
return $row->toArray();
}
}
never mind the view file ... that never throws an error. on a side note: i'm seriously considering kicking ZF to the curb and using CodeIgniter instead.
looking forward to reading your thoughts. thanks ( in advance ) for your responses
You're trying to all a method called query() on Zend_Db_Table but no such method exists. Since you have built the SQL already you might find it easier to call the query on the DB adapter directly, so:
$selectSql = "SELECT * FROM listings WHERE `s_coursedesc` LIKE '%".$searchTerm."%' || `s_title` LIKE '%".$searchTerm."%'";
$searchResults = $selectQuery->getAdapter()->fetchAll($selectSql);
but note that this will give you arrays of data in the result instead of objects which you might be expecting. You also need to escape $searchTerm here since you are getting that value directly from POST data.
Alternatively, you could form the query programatically, something like:
$searchTerm = '%'.$searchTerm.'%';
$select = $selectQuery->select();
$select->where('s_coursedesc LIKE ?', $searchTerm)
->orWhere('s_title LIKE ?', $searchTerm);
$searchResults = $searchQuery->fetchAll($select);

Zend_Db - Building a Delete Query

I'm trying to recreate the following in Zend Framework and am not sure how to do it:
DELETE FROM mytablename WHERE date( `time_cre` ) < curdate( ) - INTERVAL 4 DAY
I was thinking something like:
$table = $this->getTable();
$db = Zend_Registry::get('dbAdapter');
$db->delete($table, array(
'date(`time_cre`) < curdate() - interval 4'
));
Does that seem correct?
What is the best way to handle something like this?
EDIT: Ack! Sorry, I was adapting this from a SELECT I was using to test and didn't change the syntax properly when I pasted it in. I've edited the example to fix it.
Figured it out...
public function pruneOld($days) {
$table = $this->getTable();
$db = Zend_Registry::get('dbAdapter');
$where = $db->quoteInto("DATE(`time_cre`) < CURDATE() - INTERVAL ? DAY", $days);
return $table->delete($where);
}
$table gets an reference of the table I want to edit...
$db grabs an instance of the database adapter so I can use quoteInto()...
$where builds the main part of the query accepting $days to make things a bit more flexible.
Create an action to call this method... something like:
public function pruneoldAction() {
// Disable the view/layout stuff as I don't need it for this action
$this->_helper->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
// Get the data model with a convenience method
$data = $this->_getDataModel();
// Prune the old entries, passing in the number of days I want to be older than
$data->pruneOld(2);
}
And now hitting: http://myhost/thiscontroller/pruneold/ will delete the entries. Of course, anyone hitting that url will delete the entries but I've taken steps not included in my example to deal with this. Hope this helps someone.
I usually do this to delete a row
$table = new yourDB;
$row = $table->fetchRow($table->select()->where(some where params));
$row->delete();
try:
$db->delete($table, array(
'date(time_cre) < ?' => new Zend_Db_Expr('curdate() - interval 4')
));

Help With Zend_Db_Stmt

I have a little problem with the Zend_Db_Stmt. This works:
$sql = " SELECT * FROM bugs";
$stmt = $this->_getDb()->query($sql);
return $stmt->fetchAll();
But I am trying to make sure the PDO gets used to query the database so I tried this:
$sql = "SELECT * FROM bugs";
$stmt = new Zend_Db_Statement_Pdo($this->_getDb(), $sql);
return $stmt->fetchAll();
And this doesn't work (it returns an empty array). Could you please help me figure this out? The above code works if I use execute() method for UPDATE or INSERT queries but fetchAll() doesn't work.
You need to execute!
$stmt->execute();
return $stmt->fetchAll();
See more examples in the PHP manual.