Created
October 29, 2024 13:27
-
-
Save michtio/8aa2ab9e45776a237b22af813e5ef20d to your computer and use it in GitHub Desktop.
Custom Field Indexes on Craft 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace craft\contentmigrations; | |
use Craft; | |
use craft\base\FieldInterface; | |
use craft\db\Migration; | |
use craft\db\Table; | |
use craft\helpers\Console; | |
use Throwable; | |
use yii\db\Exception; | |
/** | |
* m241029_131118_add_index_for_go4jobs_queryable_fields migration. | |
*/ | |
class m241029_131118_add_index_for_go4jobs_queryable_fields extends Migration | |
{ | |
// The field handles we want to add database indexes for | |
public const FIELD_HANDLES = [ | |
'branchId', | |
'vacancyId' | |
]; | |
/** | |
* @inheritdoc | |
* @throws Exception | |
*/ | |
public function safeUp(): bool | |
{ | |
$entries = Craft::$app->getEntries(); | |
$entryTypes = $entries->getAllEntryTypes(); | |
foreach ($entryTypes as $entryType) { | |
$customFields = $entryType->getFieldLayout()->getCustomFields(); | |
foreach ($customFields as $customField) { | |
if (in_array($customField->handle, self::FIELD_HANDLES, true)) { | |
$this->addIndexForField($customField); | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function safeDown(): bool | |
{ | |
$entries = Craft::$app->getEntries(); | |
$entryTypes = $entries->getAllEntryTypes(); | |
foreach ($entryTypes as $entryType) { | |
$customFields = $entryType->getCustomFields(); | |
foreach ($customFields as $customField) { | |
if (in_array($customField->handle, self::FIELD_HANDLES, true)) { | |
$this->dropIndexForField($customField); | |
} | |
} | |
} | |
return true; | |
} | |
/** | |
* @param FieldInterface $field | |
* @throws Exception | |
*/ | |
protected function addIndexForField(FieldInterface $field): void | |
{ | |
$db = $this->getDb(); | |
$tableName = Table::ELEMENTS_SITES; | |
$sql = $field->getValueSql(); | |
$indexName = $this->getIndexNameForField($field); | |
$cmd = null; | |
// MySQL | |
if ($db->getIsMysql()) { | |
// If there is no CAST returned (as there wont be for text and other types), add it | |
if (!str_starts_with($sql, 'CAST')) { | |
$sql = "CAST($sql AS CHAR(255))"; | |
} | |
$cmd = $db->createCommand("ALTER TABLE $tableName ADD INDEX $indexName (( $sql COLLATE utf8mb4_bin )) USING BTREE;"); | |
} | |
// Postgres | |
if ($db->getIsPgsql()) { | |
$cmd = $db->createCommand("CREATE INDEX $indexName ON $tableName ( $sql );"); | |
} | |
// Execute the command, swallowing any errors | |
if ($cmd) { | |
try { | |
Console::output(Console::ansiFormat("Executing the following SQL to add the index:", [Console::FG_GREEN])); | |
Console::output(Console::ansiFormat($cmd->getRawSql(), [Console::FG_YELLOW])); | |
$cmd->execute(); | |
} catch (Throwable $e) { | |
// That's fine | |
} finally { | |
return; | |
} | |
} | |
// If we got to here, we don't support this database type | |
throw new Exception("Database type not supported"); | |
} | |
/** | |
* @param FieldInterface $field | |
* @return void | |
*/ | |
protected function dropIndexForField(FieldInterface $field): void | |
{ | |
$indexName = $this->getIndexNameForField($field); | |
try { | |
$this->dropIndex($indexName, Table::ELEMENTS_SITES); | |
} catch (Throwable $e) { | |
// That's fine | |
} | |
} | |
/** | |
* @param FieldInterface $field | |
* @return string | |
*/ | |
protected function getIndexNameForField(FieldInterface $field): string | |
{ | |
return $field->handle . '_' . str_replace('-', '_', $field->layoutElement->uid); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment