©Sergey Emelyanov 2025 | Alle Rechte vorbehalten
In über 10 Jahren Arbeit mit Vtiger CRM habe ich viele Projekte und Anpassungen umgesetzt. Eine der häufigsten Anforderungen ist die Möglichkeit, in benutzerdefinierten Filtern eine Standardsortierung festzulegen. Vtiger bietet bereits ein komfortables Tool zum Erstellen von Filtern: Jeder Benutzer kann die Ansicht eines Moduls individuell konfigurieren, Spalten auswählen und Datensätze filtern. Allerdings gibt es keine native Option, eine Standardsortierung festzulegen. In diesem Artikel zeige ich Ihnen detailliert, wie Sie den Code anpassen, um diese Funktionalität zu implementieren.
WICHTIG:
Bevor Sie Änderungen durchführen, legen Sie unbedingt ein vollständiges Backup der Datenbank und aller CRM-Dateien an. Führen Sie diese Änderungen nur in einer Testumgebung durch, da sie direkt in den Systemcode eingreifen.
ALTER TABLE vtiger_customview
ADD sortingfield VARCHAR(200) NULL;
ALTER TABLE vtiger_customview
ADD sortingdirect VARCHAR(10) NULL;
Diese Spalten speichern den Namen des Feldes, nach dem sortiert wird (z. B. „cf_fieldname“), und die Sortierrichtung (Asc oder Desc).
modules/CustomView/views/EditAjax.php
foreach ($customViewSharedMembers as $memberGroupLabel => $membersList) {
if(count($membersList) > 0){
$listShared = true;
break;
}
}
Unmittelbar nach diesem Block fügen Sie folgenden Code ein, um die Sortierwerte an das Template zu übergeben:
$sortField = $customViewModel->get('sortingfield');
$sortDirect = $customViewModel->get('sortingdirect');
$viewer->assign('SORTING_FIELD', $sortField);
$viewer->assign('SORTING_DIRECT', $sortDirect);
layouts/v7/modules/CustomView/EditView.tpl
<div>
<label class="filterHeaders">{vtranslate('LBL_CHOOSE_FILTER_CONDITIONS', $MODULE)} :</label>
<div class="filterElements well filterConditionContainer filterConditionsDiv">
{include file='AdvanceFilter.tpl'|@vtemplate_path}
</div>
</div>
Direkt nach diesem Block fügen Sie folgenden Code ein:
<div class="marginBottom10px">
<label class="filterHeaders">Sorting Conditions</label>
<div class="filterElements filterConditionContainer filterConditionsDiv">
<div class="row">
<div class="col-lg-6">
<select class="select2 col-lg-6" name="sortingfield">
<option value="none">{vtranslate('LBL_SELECT_FIELD', $MODULE)}</option>
{foreach key=BLOCK_LABEL item=BLOCK_FIELDS from=$RECORD_STRUCTURE}
<optgroup label='{vtranslate($BLOCK_LABEL, $SOURCE_MODULE)}'>
{foreach key=FIELD_NAME item=FIELD_MODEL from=$BLOCK_FIELDS}
{assign var=FIELD_INFO value=$FIELD_MODEL->getFieldInfo()}
{assign var=MODULE_MODEL value=$FIELD_MODEL->getModule()}
{assign var="SPECIAL_VALIDATOR" value=$FIELD_MODEL->getValidator()}
{if !empty($COLUMNNAME_API)}
{assign var=columnNameApi value=$COLUMNNAME_API}
{else}
{assign var=columnNameApi value=getCustomViewColumnName}
{/if}
<option value="{$FIELD_MODEL->$columnNameApi()}" data-fieldtype="{$FIELD_MODEL->getFieldType()}" data-field-name="{$FIELD_NAME}"
{if decode_html($FIELD_MODEL->$columnNameApi()) eq decode_html($SORTING_FIELD)}
selected="selected"
{/if}
data-fieldinfo='{Vtiger_Util_Helper::toSafeHTML(ZEND_JSON::encode($FIELD_INFO))}'
{if !empty($SPECIAL_VALIDATOR)}data-validator='{Zend_Json::encode($SPECIAL_VALIDATOR)}'{/if}>
{vtranslate($FIELD_MODEL->get('label'), $SOURCE_MODULE)}
</option>
</optgroup>
{/foreach}
{/foreach}
</select>
</div>
<div class="col-lg-6">
<select class="select2 col-lg-6" name="sortingdirect">
<option value="Asc" {if $SORTING_DIRECT eq 'Asc'}selected="true"{/if}>Asc</option>
<option value="Desc" {if $SORTING_DIRECT eq 'Desc'}selected="true"{/if}>Desc</option>
</select>
</div>
</div>
</div>
</div>
Dieser Block stellt dem Benutzer zwei Dropdown-Felder zur Verfügung – eines zur Auswahl des Sortierfeldes und eins für die Sortierrichtung.
modules/CustomView/actions/Save.php
return $customViewModel->setData($customViewData);
Fügen Sie hier folgende Zeilen ein:
$sortingfield = $request->get('sortingfield');
if(!empty($sortingfield)) {
$customViewData['sortingfield'] = $sortingfield;
}
$sortingdirect = $request->get('sortingdirect');
if(!empty($sortingdirect)) {
$customViewData['sortingdirect'] = $sortingdirect;
}
So werden die neuen Filterwerte in der Tabelle vtiger_customview gespeichert.
modules/CustomView/models/Record.php
$status = $this->get('status');
$sortingfield = $this->get('sortingfield');
$sortingdirect = $this->get('sortingdirect');
Ändern Sie anschließend den Insert-Query (etwa Zeile 272) auf:
$sql = 'INSERT INTO vtiger_customview(cvid, viewname, setdefault, setmetrics, entitytype, status, userid, sortingfield, sortingdirect) VALUES (?,?,?,?,?,?,?,?,?)';
$params = array($cvId, $viewName, $setDefault, $setMetrics, $moduleName, $status, $currentUserModel->getId(), $sortingfield, $sortingdirect);
Und bei der Update-Abfrage (etwa Zeile 280) entsprechend:
$sql = 'UPDATE vtiger_customview SET viewname=?, setdefault=?, setmetrics=?, status=?, sortingfield=?, sortingdirect=? WHERE cvid=?';
$params = array($viewName, $setDefault, $setMetrics, $status, $sortingfield, $sortingdirect, $cvId);
modules/CustomView/CustomView.php
function getSortFieldByCvid($cvid)
{
$cv = $this->getCustomViewByCvid($cvid);
if (!empty($cv) && isset($cv['sortingfield']) && $cv['sortingfield']) {
return $cv['sortingfield'];
} else {
return false;
}
}
function getSortDirectByCvid($cvid)
{
$cv = $this->getCustomViewByCvid($cvid);
if (!empty($cv) && isset($cv['sortingdirect']) && $cv['sortingdirect']) {
return $cv['sortingdirect'];
} else {
return false;
}
}
Ergänzen Sie außerdem in der Funktion getCustomViewByCvid (etwa Zeile 181) zwei Zeilen:
$customviewlist["sortingfield"] = $cvrow["sortingfield"];
$customviewlist["sortingdirect"] = $cvrow["sortingdirect"];
so dass auch diese Werte geladen werden.
modules/Vtiger/models/ListView.php
protected function generateDefaultOrderBy($moduleName, $pagingModel)
{
$viewid = ListViewSession::getCurrentView($moduleName);
if(empty($viewid)) {
$viewid = $pagingModel->get('viewid');
}
$customView = new CustomView($moduleName);
$sortfield = $customView->getSortFieldByCvid($viewid);
$sortdirect = $customView->getSortDirectByCvid($viewid);
if ($sortfield) {
$orderBy = $this->parseFieldName($sortfield);
$sortOrder = strtoupper($sortdirect);
return ' ORDER BY ' . $orderBy . ' ' . $sortOrder;
} else {
return ' ORDER BY vtiger_crmentity.modifiedtime DESC';
}
}
protected function parseFieldName($field)
{
$fieldArr = explode(':', $field);
return $fieldArr[0] . '.' . $fieldArr[1];
}
Ündern Sie in der Funktion getListViewEntries (etwa Zeile 249) die Zeile
$listQuery .= ' ORDER BY vtiger_crmentity.modifiedtime DESC';
in
$listQuery .= $this->generateDefaultOrderBy($moduleName, $pagingModel);
Dadurch wird die Filterliste in den Listenansichten von Vtiger CRM künftig anhand der in den Custom Views definierten Sortierkriterien angezeigt.
Fazit
Nach diesen umfangreichen Anpassungen in der Datenbank, den CustomView-Modulen, Templates, Aktionen und der ListView-Struktur können Benutzer nun in den Filtereinstellungen eine Standardsortierung festlegen. Dies ermöglicht eine flexible und personalisierte Darstellung der Datensätze in Vtiger CRM.
©Sergey Emelyanov 2025 | Alle Rechte vorbehalten