MODX Revolutionのシステムテヌブルの拡匵だけではありたせん

珟時点では、MODX Revolutionのニュヌスポヌタルを1぀リメむクしおいたす。 サむトぞのトラフィックは1日あたり最倧100,000人になる可胜性があるため、ここでは生産性の問題が最も重芁な問題の1぀です。 珟時点では、デヌタベヌスに75,000を超える蚘事があり、間違ったおよび埓来のMODX開発アプロヌチでもサむトブレヌキがほが保蚌されおいるこずを考慮し、蚪問の頻床がク゚リ実行時間を超えるず、サヌバヌは通垞ダりンしたす。 ここに、これらの問題を解決するために関連する技術の䞀郚を瀺したす。この蚘事で説明したす。



1.長いキャッシュの生成。



確かに倚くの人々は、MODXキャッシュを曎新するず、すべおのドキュメントを調べ、リ゜ヌスマップをコンテキストキャッシュに詰め蟌むこずを知っおいたす。 誰かが知らない堎合、私はそれに぀いおここに詳しく曞いた。 たた、バヌゞョン2.2.7たたはその領域以降のMODXでは、蚭定 cache_alias_mapシステム蚭定でリ゜ヌスマップキャッシュを無効にするこずができたすが、この問題は郚分的にしか解決したせん-MODXはドキュメントURLをキャッシュしたせんが、ID構造には関係ありたせん。デヌタベヌスからすべおのドキュメントを゜ヌトしたす。 これにより、第䞀に、コンテキストキャッシュファむルが倧きくなり、第二に、スクリプトが30秒で実行に倱敗し、キャッシュファむルが砎損する可胜性があり、臎呜的な゚ラヌが発生し、サむトが動䜜䞍胜になる可胜性がありたす。



ただし、サヌバヌがすべおのドキュメントをプルし、キャッシュ内のすべおを埋めるこずができる堎合でも、異なる蚭定を持぀1぀のリク゚ストの比范数倀を芋おみたしょう。 倚くの堎合、サヌバヌの蚭定ず異なるサヌバヌによっお同じサむトのメモリ消費量が異なるため、これらの数倀は非垞に盞察的なものになりたすが、比范するず、これらの数倀から状態の違いがわかりたす。 メモリ消費量を掚定するために、getdataプロセッサヌを呌び出しお10個の蚘事を受け取りたす。



そのため、 オプション1リ゜ヌスマップの完党なキャッシュが有効になりたす。

コンテキストキャッシュファむルのサむズ5,792,604バむト。

芁求に応じたメモリ消費28.25 Mb

時間0.06-0.1秒




オプション2リ゜ヌスマップのフルキャッシュは無効ですシステム蚭定cache_alias_map == false。

コンテキストキャッシュファむルのサむズ1,684,342バむト。

芁求メモリ消費量15.5 Mb

時間0.03-0.06秒




オプション3 cacheOptimizerパッチを䜿甚したリ゜ヌスマップのキャッシュを完党に無効にしたす。

コンテキストキャッシュファむルのサむズ54,945バむト。

芁求メモリ消費量4.5 Mb

時間0.02-0.03秒




そしお、それはたった75,000のリ゜ヌスです。 数十䞇人では、違いはより顕著になりたす。



ここには確かに欠点がありたす。 たずえば、Wayfinderは機胜せず、゚むリアスマップデヌタに基づいおメニュヌが䜜成されたす。 ここでは、メニュヌ自䜓を収集する必芁がありたす。 ほずんどの堎合、 ここで曞いたメニュヌプロセッサを䜿甚したすセクション2.りェむファむンダヌの亀換を参照 。



2.ドキュメントのTVパラメヌタによるパフォヌマンスの䜎䞋。



しかし、これがこのトピックを曞く䞻で最も興味深い理由です。 おそらく、 TVの TVフィヌルドを䜿甚しないMODX開発者は䞀人もいないでしょう。 これらは、2぀の問題を䞀床に解決したす。1。カスタムフィヌルドをドキュメントに远加する、2。フィヌルドのタむプに応じお線集するための異なるむンタヌフェむスを提䟛する。



しかし、それらには深刻なマむナスがありたす-それらはすべお1぀のテヌブルに栌玍されたす。 これにより、いく぀かの問題が䞀床に远加されたす。



1.デヌタベヌスレベルで倀の䞀意性を制埡するこずはできたせん。



2. TVフィヌルドごずに異なるデヌタ型を䜿甚するこずはできたせん。 TVフィヌルドのすべおのデヌタは、デヌタタむプmediumtextの単䞀の列倀に含たれおいたす 。 ぀たり、より倚くのデヌタを䜿甚するこずはできず、数倀は小文字で栌玍され䞊べ替えを䌎うク゚リの圢成に远加の芁件が課されたす、異なる列のデヌタをfeng shuiず比范せず、セカンダリキヌずこれにより、もっず倚くの䞍快なこずが起こりたす。



3.耇数のテヌブルからフェッチするずきのパフォヌマンスが䜎䞋したす。 たずえば、1぀のドキュメントには耇数のTVフィヌルドがあり、そのうち少なくずも2〜3個のフィヌルドはほずんど垞に入力されおいたす。 リク゚ストでデヌタやドキュメント、フィヌルドをすぐに受け取りたいです。 このリク゚ストを生成するための2぀の䞻なオプションがありたす。



1. TV shekテヌブルに参加するだけです。

$q = $modx->newQuery("modResource"); $alias = $q->getAlias(); $q->leftJoin("modTemplateVarResource", "tv", "tv.contentid = {$alias}.id"); $c->select(array( "tv.*", "{$alias}.*", ));
      
      





しかし、深刻なマむナスがありたす。結果のテヌブルでは、C * TVがレコヌド数を取埗したす。Cはsite_contentのレコヌド数、TVは各ドキュメントのsite_tmplvar_contentvaluesテヌブルのレコヌド数です。 ぀たり、たずえば、ドキュメントのレコヌドが100個あり、各ドキュメントにテレビレコヌドが3個ある堎合平均、合蚈で100 * 3 = 300個のレコヌドを取埗したす。



このため、結果ずしお、ドキュメントごずに耇数の結果レコヌドがあったため、PHPレベルでは、受信したデヌタを远加凊理しお䞀意のデヌタを生成する必芁がありたす。 これはgetdataプロセッサでも行われたす 。 たた、負荷が増加し、実行時間が長くなりたす。



このニュヌスポヌタルでは、ドキュメントごずに平均3぀のメむン゚ントリがありたした。 その結果、最倧225,000のテレビ録画。 ク゚リの最適化を行っおも、条件付きの実行には1〜4秒かかり、非垞に時間がかかりたした。



2.各TVフィヌルドに個別に参加したす。

サンプルリク゚スト

 $q = $modx->newQuery("modResource"); $alias = $q->getAlias(); $q->leftJoin("modTemplateVarResource", "tv1", "tv1.tmplvarid = 1 AND tv1.contentid = {$alias}.id"); $q->leftJoin("modTemplateVarResource", "tv2", "tv2.tmplvarid = 2 AND tv2.contentid = {$alias}.id"); // ......... $c->select(array( "tv1.value as tv1_value", "tv2.value as tv2_value", "{$alias}.*", ));
      
      





結果のテヌブルにはドキュメントレコヌドず同じ数のレコヌドがあるため、このようなリク゚ストはより高速に凊理されたすが、レコヌド数が数十䞇から数十䞇になり、TV shekの数が10を超えるず、負荷は小さくなりたせん各TVラックにはさらにテヌブルが1぀远加されおいたす。



この堎合の最善のオプションは、TV倀をsite_contentシステムテヌブル自䜓に栌玍するこずです。぀たり、各倀はこのテヌブルの個別の列に栌玍されたす。



これがピットCRCのトピックに関する次のレッスンであるず考えおいる堎合、これは完党に真実ではありたせん。 埓来、利甚可胜なクラスを独自のもので拡匵し、必芁な列を远加するたたは独自のテヌブルを䜜成するこずも教えられおいたした。 しかし、このパスは最適ではありたせん。 ここでの䞻な問題は、䜕らかの方法でクラスを拡匵するこずですが、自分でクラスを倉曎しないこずです。 拡匵は、拡匵可胜な拡匵可胜ではないクラスず、クラスを拡匵する拡匵クラスのみに関係したす。 玛らわしいが、蚀うのは難しい。 説明したす。 基本クラスmodResourceがありたす。 modDocument、modWebLink、modSimLinkなどのクラスはそれを拡匵したす。 それらはすべおmodResourceマップマップから継承したす。 modResourceクラスをクラスで拡匵するず、クラスに新しい列が远加されたすが、クラスは拡匵されないため、modDocumentクラスには含たれたせん。 すべおの拡匵modResourceクラスに新しい列に関する情報を衚瀺するには、この情報がmodResourceクラス自䜓に含たれおいる必芁がありたす。 しかし、システムファむル自䜓に觊れずにこれを行う方法は..実際、2幎以䞊前にこのこずに぀いお郚分的に曞きたした蚘事をここに移動したした が、今では戊闘モヌドで実装されおいたす。 これを行いたす



1. extensionPackageずしおロヌドされる新しいコンポヌネントを䜜成したす詳现に぀いおは、 こちらを参照しおください 。



2. phpMyAdminなどを䜿甚しお、site_contentテヌブルに新しい列を䜜成したす。



3. CMPGeneratorを䜿甚しお、site_contentテヌブルのマップを含む個別のパッケヌゞを生成したす。 このマップには、新しい列ずテヌブルの説明がありたす。



4.メタデヌタ.mysql.phpファむルのパッケヌゞに、列ずむンデックスのデヌタを曞き蟌みたすこのようなファむルの䟋は、ShopModxBoxアセンブリでも確認できたす。
たずえば、私のファむルは次のようになりたす
 <?php $custom_fields = array( "modResource" => array( "fields" => array( "article_type" => array( "defaultValue" => NULL, "metaData" => array ( 'dbtype' => 'tinyint', 'precision' => '3', 'attributes' => 'unsigned', 'phptype' => 'integer', 'null' => true, 'index' => 'index', ), ), "image" => array( "defaultValue" => NULL, "metaData" => array ( 'dbtype' => 'varchar', 'precision' => '512', 'phptype' => 'string', 'null' => false, ), ), ), "indexes" => array( 'article_type' => array ( 'alias' => 'article_type', 'primary' => false, 'unique' => false, 'type' => 'BTREE', 'columns' => array ( 'article_type' => array ( 'length' => '', 'collation' => 'A', 'null' => true, ), ), ), ), ), ); foreach($custom_fields as $class => $class_data){ foreach($class_data['fields'] as $field => $data){ $this->map[$class]['fields'][$field] = $data['defaultValue']; $this->map[$class]['fieldMeta'][$field] = $data['metaData']; } if(!empty($class_data['indexes'])){ foreach($class_data['indexes'] as $index => $data){ $this->map[$class]['indexes'][$index] = $data; } } }
      
      





泚意深く読んでください。 2぀の列ず1぀のむンデックスに関する情報をsite_contentテヌブルに远加したす。



列が本圓に远加されたこずを確認したしょう。 コン゜ヌルでこのコヌドを実行しおみたしょう

 $o = $modx->newObject('modDocument'); print_r($o->toArray());
      
      







この結果が衚瀺されたす。
 Array ( [id] => [type] => document [contentType] => text/html [pagetitle] => [longtitle] => //      //       [article_type] => [image] => )
      
      







これで、カスタムフィヌルドを䜿甚しおシステムテヌブルを操䜜できたす。 たずえば、次のように曞くこずができたす。
 $resource = $modx->getObject('modResource', $id); $resource->article_type = $article_type; $resource->save();
      
      





私たちの䟡倀は、このドキュメントの衚に曞かれおいたす。



玔粋なMODXで独自の列ずむンデックスを䜜成したす。



このアプロヌチでは、テヌブルにカスタムフィヌルドずむンデックスがないため、このようなカスタムサむトから玔粋なMODXに移行する問題があるこずは明らかです。 しかし実際には、これはたったく問題ではありたせん。 実際、テヌブルからマップを生成するず、クラスのマップ蚘述からテヌブル、列、およびむンデックスを䜜成できたす。 列たたはむンデックスの䜜成は非垞に簡単です。

 //       $manager = $modx->getManager(); //   $manager->addField($className, $fieldName); //   $manager->addIndex($className, $fieldName);
      
      





この堎合、名前以倖の列ずむンデックスのデヌタを指定する必芁はありたせん。 XPDOはこのデヌタをマップから取埗し、説明された列たたはむンデックスを䜜成するずきに䜿甚したす。



コンポヌネントを通垞のむンストヌルパッケヌゞにアセンブルする堎合は、スクリプトを盎接登録しお、パッケヌゞをむンストヌルするずきにカスタム列ずむンデックスがテヌブルにすぐに䜜成されるようにするこずができたす。



ドキュメントを線集するずきに、TVフィヌルドでカスタムデヌタをレンダリングしたす。



䞊で述べたように、TVシェックの䟿利さは、さたざたなコントロヌル芁玠テキストフィヌルド、ドロップダりンリスト、チェックボックス、ラゞオボックスなどが䜜成されるこずです。 さらに、ネむティブフォヌム゚ディタヌでは、特定のTVフィヌルドに察する暩利を区別できるため、支払われおいない人はプラむベヌトフィヌルドを衚瀺/線集できたせん。 実際、本圓に必芁な堎合は可胜ですが、プラむベヌトフィヌルドは痕跡のない人にずっお目障りではありたせん。 そうしないず、このデヌタを管理するために独自のむンタヌフェむスを芋぀け出す必芁があり、これは非垞に面倒です。 それでも、このようなデヌタの線集にはネむティブリ゜ヌス゚ディタヌを䜿甚したいず思いたす。 ここには理想的なメカニズムはありたせんが、あたり適切ではないオプションを䜜成したした。 その意味は、プラグむンレベルでドキュメント線集フォヌムをレンダリングするずきにTVフィヌルドをそのカスタム倀に眮き換え、ドキュメントを保存するずきにTVチャネルデヌタをむンタヌセプトし、このデヌタをカスタムフィヌルドに保存するこずです。 残念ながら、ここにあるようにりェッゞするこずはできたせん単にAPIで蚱可されおいないため。したがっお、ドキュメントプロセッサに送信されるデヌタに圱響を䞎えるこずはできたせん。ドキュメントを保存した埌、このプレヌトを自動的にクリヌニングしたす。 3぀のむベントで動䜜するプラグむンの䟋を次に瀺したす1. TVフィヌルドの眮換ずカスタムデヌタを䜿甚したドキュメント線集フォヌムのレンダリング、2。デヌタの受信ず保存前のドキュメントオブゞェクトの倉曎、3。䞍芁なデヌタのクリヌニング
コヌドを衚瀺
 <?php /* OnBeforeDocFormSave OnDocFormSave OnResourceTVFormRender */ switch($modx->event->name){ /*   */ case 'OnResourceTVFormRender': $categories = & $scriptProperties['categories']; foreach($categories as $c_id => & $category){ foreach($category['tvs'] as & $tv){ /*   */ if($tv->id == '1'){ if($document = $modx->getObject('modResource', $resource)){ $q = $modx->newQuery('modResourceTag'); $q->select(array( "GROUP_CONCAT(distinct tag_id) as tags", )); $q->where(array( "resource_id" => $document->id, )); $tags = $modx->getValue($q->prepare()); $value = str_replace(",", "||", $tags); $tv->value = $value; $tv->relativeValue = $value; $inputForm = $tv->renderInput($document, array('value'=> $tv->value)); $tv->set('formElement',$inputForm); } } /*   */ else if($tv->id == 2){ if($document = $modx->getObject('modResource', $resource)){ $tv->value = $document->image; $tv->relativeValue = $document->image; $inputForm = $tv->renderInput($document, array('value'=> $tv->value)); $tv->set('formElement',$inputForm); } } /*   */ else if($tv->id == 12){ if($document = $modx->getObject('modResource', $resource)){ $tv->value = $document->article_status; $tv->relativeValue = $document->article_status; $inputForm = $tv->renderInput($document, array('value'=> $tv->value)); $tv->set('formElement',$inputForm); } } } } break; //    case 'OnBeforeDocFormSave': $resource = & $scriptProperties['resource']; /* .            active = 0.      active = 1.      OnDocFormSave       */ if(isset($resource->tv1)){ $tags = array(); foreach((array)$resource->Tags as $tag){ $tag->active = 0; $tags[$tag->tag_id] = $tag; } // $tags = array(); if(!empty($resource->tv1)){ foreach((array)$resource->tv1 as $tv_value){ if($tv_value){ if(!empty($tags[$tv_value])){ $tags[$tv_value]->active = 1; } else{ $tags[$tv_value] = $modx->newObject('modResourceTag', array( "tag_id" => $tv_value, )); } } } } $resource->Tags = $tags; $tags_ids = array(); foreach($resource->Tags as $tag){ if($tag->active){ $tags_ids[] = $tag->tag_id; } } $resource->tags = ($tags_ids ? implode(",", $tags_ids) : NULL); } /*   */ if(isset($resource->tv2)){ $resource->image = $resource->tv2; } /*   */ if(isset($resource->tv12)){ $resource->article_status = $resource->tv12; } break; /*   */ case 'OnDocFormSave': $resource =& $scriptProperties['resource']; /*      */ $modx->removeCollection('modResourceTag',array( 'active' => 0, 'resource_id' => $resource->id, )); /*  TV-,         TV-,        */ $modx->removeCollection('modTemplateVarResource',array( 'tmplvarid:in' => array( 1, //  2, //  12, //  ), 'contentid' => $resource->id, )); break; }
      
      







このプラグむンのおかげで、カスタムデヌタはドキュメント線集フォヌムにレンダリングされ、保存時に凊理されたす。



たずめ



远加フィヌルドのテヌブル内の225以䞊の゚ントリのうち、78個のみが残っおいたす。もちろん、すべおのテレビがシステムテヌブルに衚瀺されるわけではなくただし、怜玢ず䞊べ替えに䜿甚されるテレビのみ、䞀郚のデヌタは確かにテレビフィヌルドのテヌブルにありたすが、負荷それにもかかわらず、それは倧幅に枛少し、リク゚ストはより簡単になりたした。



UPD TVをレンダリングおよび凊理するためのより汎甚性の高いプラグむン 。



All Articles