Extbase - Query Objekt: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
 
(16 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 +
 +
 
Siehe auch:
 
Siehe auch:
  
 
[[Extbase - Sortierung und Abfrage von Objekten]]
 
[[Extbase - Sortierung und Abfrage von Objekten]]
  
http://mbless.de/blog/2015/03/05/typo3-extbase-query-methods.html
+
http://mbless.de/blog/2015/03/05/typo3-extbase-query-methods.html (gute Sammlung und best practice)
  
 
http://lbrmedia.net/codebase/Eintrag/extbase-query-methods/
 
http://lbrmedia.net/codebase/Eintrag/extbase-query-methods/
  
Das Query Object steuert Abfragen auf die Datenbank. Wenn man z.B. findAll() im Controller ausführt, werden die Parameter für die Abfrage aus diesem Objekt geholt.
+
Das Query Object steuert Abfragen auf die Datenbank. Wenn man z.B. findAll() im Controller ausführt, werden die Parameter für die Abfrage aus diesem Objekt geholt. Die Standardfunktionen lassen sich überschreiben oder man kann die im Query Object enthaltenen Arrays manipulieren. Best Practise ist Query Funktionen etc. im Repository definieren. Ausführen dann im Controller.
 +
 
 +
 
 +
== Übersicht ==
 +
=== Allgemeines Vorgehen ===
 +
==== Einfache Anfragen ====
 +
Einfache Anfragen z.B. Filtern nach einer bestimmten Eigenschaft (Property) geht mit der findBy[property] Methode. Nach der uid sucht man z.B. mit.
 +
findByUid(42)
 +
findOneByName('foo') // gibt nur das erste zurück
 +
Das geht mit allen Eigenschaften im Model (findByName, findByIrgendwas)
 +
==== Speziellere Queries ====
 +
Für '''spezielle Queries''' erstellt man mit
 +
$this->createQuery()
 +
ein neues '''Query Objekt'''. Diesem gibt man dann '''Conditions und Sortierungen''' mit. Wichtige Methoden sind z.B. matching(), execute() und setOrderings())
 +
==== Daten im Controller nachbearbeiten ====
 +
SQL wird normalerweise ausgeführt, wenn der ViewHelper des Fluid Templates Daten anfordert, also nachdem der Controller abgearbeitet ist. Das ist ein Problem wenn man die Daten noch im Controller bearbeiten will. Man kann die Daten aber auch im Controller durchgehen, bearbeiten und dann wieder dem Fluid Template übergeben.
 +
<syntaxhighlight lang="php"
 +
$array = array();
 +
 +
foreach($this->repository->findAll() as $object)
 +
{
 +
    $object->SetWhatEver(42);
 +
    $array[] = $object;
 +
}
 +
 +
$this->view->assign('list', $array);
 +
</syntaxhighlight>
 +
=== Group By ===
 +
Das wird von Extbase nicht erzeugt.  Aber es gibt einen GroupFor View Helper. Ansonsten kann man auch auf eigene Queries ausweichen.
 +
=== Eigene Queries ===
 +
Todo
  
 
== Beipiele ==
 
== Beipiele ==
=== Beispiel Kommaseparierte Liste für Abfrage ===
+
 
 +
=== Beispiel: Sortierreihenfolge ===
 +
Für angepasste Sortierungen reicht es '''im Repository das Array $defaultOrderings zu überschreiben.'''
 +
<syntaxhighlight lang="php">
 +
class DeviceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
 +
protected $defaultOrderings = array(
 +
'deviceClass.classTitle' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
 +
'deviceTitle' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
 +
//'date' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
 +
);
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
=== Beispiel: FE-User by uid und by group finden ===
 +
Aus Powermail (gekürzt)
 +
 
 +
'''Repository'''
 +
<syntaxhighlight lang="php">
 +
use TYPO3\CMS\Extbase\Persistence\Repository;
 +
 
 +
/**
 +
* UserRepository
 +
*
 +
* @package powermail
 +
* @license http://www.gnu.org/licenses/lgpl.html
 +
* GNU Lesser General Public License, version 3 or later
 +
*/
 +
class UserRepository extends Repository {
 +
/**
 +
* Find FE_Users by their group
 +
*
 +
* @param int $uid fe_groups UID
 +
* @return \TYPO3\CMS\Extbase\Persistence\Generic\QueryResult
 +
*/
 +
public function findByUsergroup($uid) {
 +
$query = $this->createQuery();
 +
$query->getQuerySettings()->setRespectStoragePage(FALSE);
 +
$query->matching(
 +
$query->contains('usergroup', $uid)
 +
);
 +
return $query->execute();
 +
}
 +
 
 +
/**
 +
* Find by Uid but don't respect storage page
 +
*
 +
* @param \int $uid
 +
* @return \In2code\Powermail\Domain\Model\User
 +
*/
 +
public function findByUid($uid) {
 +
$query = $this->createQuery();
 +
$query->getQuerySettings()->setRespectStoragePage(FALSE);
 +
$query->matching(
 +
$query->equals('uid', $uid)
 +
);
 +
return $query->execute()->getFirst();
 +
}
 +
}
 +
</syntaxhighlight>
 +
Die Funktionen werden dann im '''Controller''' aufgerufen z.B.
 +
<syntaxhighlight lang="php">$mail->setFeuser( $this->userRepository->findByUid(Div::getPropertyFromLoggedInFeUser('uid')) );</syntaxhighlight>
 +
 
 +
 
 +
 
 +
=== Beispiel: Custom Query ===
 +
Aus Powermail
 +
<syntaxhighlight lang="php">
 +
/**
 +
* Get parent page uid form given field uid
 +
*
 +
* @param int $fieldUid
 +
* @return array
 +
*/
 +
protected function getPageUidFromFieldUid($fieldUid) {
 +
$query = $this->createQuery();
 +
$sql = 'select pages';
 +
$sql .= ' from tx_powermail_domain_model_fields';
 +
$sql .= ' where uid = ' . (int) $fieldUid;
 +
$sql .= ' and deleted = 0';
 +
$sql .= ' limit 1';
 +
$row = $query->statement($sql)->execute(TRUE);
 +
return $row[0]['pages'];
 +
}
 +
</syntaxhighlight>
 +
 
 +
 
 +
=== Beispiel: Mehrere Conditions auf die Abfrage anwenden ===
 +
Wenn du mehrere Filter brauchst oder etwas anderes als ein uid=4 Abfrage, dann erstelle ein Query Objekt mit mehreren Conditions
 +
<syntaxhighlight lang="php">
 +
public function findNonPublicByTest(\TYPO3\MyExt\Domain\Model\Test $test) {
 +
$query = $this->createQuery();
 +
$condition1 = $query->equals('public', false);
 +
$condition2 = $query->equals('test', $test);
 +
$condition  = $query->logicalAnd($condition1, $condition2);
 +
$query->matching($condition);
 +
$query->setOrderings(array('titel' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
 +
return $query->execute();
 +
}
 +
</syntaxhighlight>
 +
 
 +
=== Beispiel Logische Verknüpfungen ===
 +
<syntaxhighlight lang="php">
 +
Public Function findForMyView (  $var1, $var2  ) {
 +
  $query = $this->createQuery();
 +
    Return $query
 +
      ->matching(
 +
        $query->logicalAnd(
 +
            $query->equals('field1', $var1 ),
 +
            $query->lessThan('field2',  $var ),
 +
            $query->greaterThan('field3', '1')
 +
        )
 +
      )
 +
      ->setOrderings(Array('uid' => Tx_Extbase_Persistence_Query::ORDER_DESCENDING))
 +
 
 +
      -> setLimit (1)
 +
      -> execute();
 +
  }
 +
</syntaxhighlight>
 +
 
 +
 
 +
=== Beispiel: Kommaseparierte Liste für Abfrage ===
 
http://www.buero-sonne.de/2014/10/16/mysql-orderby-field-in-extbase.html
 
http://www.buero-sonne.de/2014/10/16/mysql-orderby-field-in-extbase.html
 
<syntaxhighlight lang="php">
 
<syntaxhighlight lang="php">
Zeile 43: Zeile 196:
 
     return $orderings;
 
     return $orderings;
 
}
 
}
 +
</syntaxhighlight>
 +
== Beispiele aus Extensions ==
 +
=== gbrma ===
 +
<syntaxhighlight lang="php">
 +
/**
 +
* Find by multiple family Ids using, seperated string and Sort by Name
 +
*
 +
*/
 +
public function findByFamilies($uidList) {
 +
if(!is_array($uidList)) $uidArray = explode(",", $uidList);
 +
else $uidArray = $uidList;
 +
$query = $this->createQuery();
 +
$query->matching(
 +
$query->in('class_family', $uidArray),
 +
$query->logicalAnd(
 +
$query->equals('hidden', 0),
 +
$query->equals('deleted', 0)
 +
)
 +
);
 +
$query->setOrderings($this->orderByField('class_title', $uidArray));
 +
 +
return $query->execute();
 +
}
 +
/**
 +
* Set the order method
 +
*
 +
*/
 +
protected function orderByField($field, $values) {
 +
$orderings = array();
 +
foreach ($values as $value) {
 +
$orderings["$field={$value}"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
 +
}
 +
return $orderings;
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>

Aktuelle Version vom 13. November 2015, 13:29 Uhr


Siehe auch:

Extbase - Sortierung und Abfrage von Objekten

http://mbless.de/blog/2015/03/05/typo3-extbase-query-methods.html (gute Sammlung und best practice)

http://lbrmedia.net/codebase/Eintrag/extbase-query-methods/

Das Query Object steuert Abfragen auf die Datenbank. Wenn man z.B. findAll() im Controller ausführt, werden die Parameter für die Abfrage aus diesem Objekt geholt. Die Standardfunktionen lassen sich überschreiben oder man kann die im Query Object enthaltenen Arrays manipulieren. Best Practise ist Query Funktionen etc. im Repository definieren. Ausführen dann im Controller.


Übersicht[Bearbeiten]

Allgemeines Vorgehen[Bearbeiten]

Einfache Anfragen[Bearbeiten]

Einfache Anfragen z.B. Filtern nach einer bestimmten Eigenschaft (Property) geht mit der findBy[property] Methode. Nach der uid sucht man z.B. mit.

findByUid(42) 
findOneByName('foo') // gibt nur das erste zurück

Das geht mit allen Eigenschaften im Model (findByName, findByIrgendwas)

Speziellere Queries[Bearbeiten]

Für spezielle Queries erstellt man mit

$this->createQuery()

ein neues Query Objekt. Diesem gibt man dann Conditions und Sortierungen mit. Wichtige Methoden sind z.B. matching(), execute() und setOrderings())

Daten im Controller nachbearbeiten[Bearbeiten]

SQL wird normalerweise ausgeführt, wenn der ViewHelper des Fluid Templates Daten anfordert, also nachdem der Controller abgearbeitet ist. Das ist ein Problem wenn man die Daten noch im Controller bearbeiten will. Man kann die Daten aber auch im Controller durchgehen, bearbeiten und dann wieder dem Fluid Template übergeben.

repository->findAll() as $object)
{
    $object->SetWhatEver(42);
    $array[] = $object;
}
 
$this->view->assign('list', $array);

Group By[Bearbeiten]

Das wird von Extbase nicht erzeugt. Aber es gibt einen GroupFor View Helper. Ansonsten kann man auch auf eigene Queries ausweichen.

Eigene Queries[Bearbeiten]

Todo

Beipiele[Bearbeiten]

Beispiel: Sortierreihenfolge[Bearbeiten]

Für angepasste Sortierungen reicht es im Repository das Array $defaultOrderings zu überschreiben.

class DeviceRepository extends \TYPO3\CMS\Extbase\Persistence\Repository {
	protected $defaultOrderings = array(
		'deviceClass.classTitle' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING,
		'deviceTitle' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING
		//'date' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
	);
}


Beispiel: FE-User by uid und by group finden[Bearbeiten]

Aus Powermail (gekürzt)

Repository

use TYPO3\CMS\Extbase\Persistence\Repository;

/**
 * UserRepository
 *
 * @package powermail
 * @license http://www.gnu.org/licenses/lgpl.html
 * 			GNU Lesser General Public License, version 3 or later
 */
class UserRepository extends Repository {
	/**
	 * Find FE_Users by their group
	 *
	 * @param int $uid fe_groups UID
	 * @return \TYPO3\CMS\Extbase\Persistence\Generic\QueryResult
	 */
	public function findByUsergroup($uid) {
		$query = $this->createQuery();
		$query->getQuerySettings()->setRespectStoragePage(FALSE);
		$query->matching(
			$query->contains('usergroup', $uid)
		);
		return $query->execute();
	}

	/**
	 * Find by Uid but don't respect storage page
	 *
	 * @param \int $uid
	 * @return \In2code\Powermail\Domain\Model\User
	 */
	public function findByUid($uid) {
		$query = $this->createQuery();
		$query->getQuerySettings()->setRespectStoragePage(FALSE);
		$query->matching(
			$query->equals('uid', $uid)
		);
		return $query->execute()->getFirst();
	}
}

Die Funktionen werden dann im Controller aufgerufen z.B.

$mail->setFeuser( $this->userRepository->findByUid(Div::getPropertyFromLoggedInFeUser('uid')) );


Beispiel: Custom Query[Bearbeiten]

Aus Powermail

	/**
	 * Get parent page uid form given field uid
	 *
	 * @param int $fieldUid
	 * @return array
	 */
	protected function getPageUidFromFieldUid($fieldUid) {
		$query = $this->createQuery();
		$sql = 'select pages';
		$sql .= ' from tx_powermail_domain_model_fields';
		$sql .= ' where uid = ' . (int) $fieldUid;
		$sql .= ' and deleted = 0';
		$sql .= ' limit 1';
		$row = $query->statement($sql)->execute(TRUE);
		return $row[0]['pages'];
	}


Beispiel: Mehrere Conditions auf die Abfrage anwenden[Bearbeiten]

Wenn du mehrere Filter brauchst oder etwas anderes als ein uid=4 Abfrage, dann erstelle ein Query Objekt mit mehreren Conditions

public function findNonPublicByTest(\TYPO3\MyExt\Domain\Model\Test $test) {
 	$query = $this->createQuery();
 	$condition1 = $query->equals('public', false);
	$condition2 = $query->equals('test', $test);
	$condition  = $query->logicalAnd($condition1, $condition2);
 	$query->matching($condition);
	$query->setOrderings(array('titel' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING));
 	return $query->execute();
}

Beispiel Logische Verknüpfungen[Bearbeiten]

 Public Function findForMyView (  $var1, $var2  ) {
   $query = $this->createQuery();
    Return $query
      ->matching(
        $query->logicalAnd(
            $query->equals('field1', $var1 ),
            $query->lessThan('field2',  $var ),
            $query->greaterThan('field3', '1')
        )
      )
      ->setOrderings(Array('uid' => Tx_Extbase_Persistence_Query::ORDER_DESCENDING))

      -> setLimit (1)
      -> execute();
  }


Beispiel: Kommaseparierte Liste für Abfrage[Bearbeiten]

http://www.buero-sonne.de/2014/10/16/mysql-orderby-field-in-extbase.html

/**
 *  Find by multiple uids using, seperated string and maintain the list order 
 * 
 */
public function findByUidListOrderByList($uidList) {
    $uidArray = explode(",", $uidList);
    $query = $this->createQuery();
    $query->matching(
        $query->in('uid', $uidArray),
        $query->logicalAnd(
            $query->equals('hidden', 0),
            $query->equals('deleted', 0)
        )
    );
    $query->setOrderings($this->orderByField('uid', $uidArray));
 
    return $query->execute();
}
 
 /**
 *  Set the order method 
 * 
 */
protected function orderByField($field, $values) {
    $orderings = array();
    foreach ($values as $value) {
        $orderings["$field={$value}"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
    }
    return $orderings;
}

Beispiele aus Extensions[Bearbeiten]

gbrma[Bearbeiten]

	/**
	 *	Find by multiple family Ids using, seperated string and Sort by Name 
	 * 
	 */
	public function findByFamilies($uidList) {
		if(!is_array($uidList)) $uidArray = explode(",", $uidList);
		else $uidArray = $uidList;
		$query = $this->createQuery();
		$query->matching(
			$query->in('class_family', $uidArray),
			$query->logicalAnd(
				$query->equals('hidden', 0),
				$query->equals('deleted', 0)
			)
		);
		$query->setOrderings($this->orderByField('class_title', $uidArray));
	
		return $query->execute();
	}	
	 /**
	 *	Set the order method 
	 * 
	 */
	protected function orderByField($field, $values) {
		$orderings = array();
		foreach ($values as $value) {
			$orderings["$field={$value}"] = \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING;
		}
		return $orderings;
	}