BemPHP:PHPを使用したBEM方法論の実装

ここでPHPを学習するためのアイデアを思いつきました。ご存知のように、言語を学習する最良の方法は、その上に自転車フレームワークを作成することです。 さまざまなフォーラムやトピックを選ぶとき、尊敬されているYandex社が推進している1つの方法論-BEMに興味がありました。 この方法論を知らない人は、 公式ページを読んでください 。 また、Habréには「最小のレイアウト」という出版物があります。 xnim habrayuzerからBEMページ ' 'を作成しています。ここでは、具体的な例を使用してすべてを説明します。 Yandexはプロジェクトをビルドするためのモジュールとスクリプトを作成しましたが、それらはすべてNode.jsで行われましたが、PHPでそのようなものを見つけることができませんでした(率直に言って、私はそれを本当に探していませんでした)。 さらに、オブジェクト指向言語としてのPHPは、興味深い機会を提供します。







開始する



GitHubからBemPHPフォルダーをダウンロードし、プロジェクトのフォルダーに配置します。 次に、BemPHP.phpを接続します。

include_once "BemPHP/BemPHP.php";
      
      





オートロード機能をまだ持っていない場合は、登録してください:

 BemPHP::register_autoload();
      
      





それでは、最初のブロックを作成しましょう。 これを行うには、BemPHP / blocks /フォルダー内のブロックの名前でフォルダーを作成します(例: 'b-block-name')。 実際にはすべて。 これは、b-block-nameという名前のブロックオブジェクトをブロックストアにロードするのに十分です。 アップロードしましょう:

 BemPHP::includeBlocksList('b-block-name');
      
      





もちろん、この方法で各ブロックを個別にロードするのは多すぎるので、カンマで区切って記述できます。

 BemPHP::includeBlocksList('b-block-1, b-block-2, block-3');
      
      





「block-3」は接頭辞「b-」なしで記述されていることに注意してください。これはエラーではありません。この場合、「b-block-3」という名前のブロックはもちろんロードされます。 プレフィックス「b-」は、ブロックの説明がこのフォルダーにあることを示します。このプレフィックスで始まらないフォルダーがブロックフォルダーにある場合、それは無視されます。 includeBlocksListメソッドでプレフィックスを指定することはオプションです。

必要なすべてのブロックをリストすることも非常に時間がかかるため、たとえば次のようにマスクを作成できます。

 BemPHP::includeBlocksList('b-page1*, *input*, *down');
      
      





この場合、b-page1で始まるすべてのブロックがロードされ、その名前にはすべてinputという単語があり、すべてがdownで終わります。 たとえば、b-page1で始まるすべてのものが必要な場合、エントリは次のようになります。b-page1* input *。 さて、例外なくすべてのブロックをロードする必要がある場合は、次のようにします。

 BemPHP::includeBlocksList('*');
      
      





これで、スタイルと動作の説明をb-block-nameフォルダーに追加できます。 これらの目的のために、フォルダーにb-block-name.cssおよびb-block-name.jsファイルを作成します。これらのファイルは自動的にオブジェクトにロードされます。 ファイル名はブロックの名前と一致する必要があり、そうでない場合は無視されることに注意してください。 また、起動中に、b-block-name.cssファイルの '.b-block-name'クラススタイルと圧縮の説明、つまり余分なスペース、改行、コメントの削除が確認されます。



ブロック定義



オブジェクト指向言語を扱っているので、PHPを使用してオブジェクトとしてブロックを作成することは素晴らしいことです。 これを行うには、b-block-nameフォルダーでb-block-name.phpファイルを作成します。 この場合、.cssおよび.jsファイルは無視され、ブロックの説明全体がphpファイルから取得されます。



 use BemPHP\Block; $_blockName_ = 'b-block-name'; /*     (   ) */ $_blockObj_ = new Block($_blockName_); $_blockObj_->setBlockDir(__DIR__) /*   ,       */ ->loadCSSFile($_blockName_.'.css') /*    css  (  null,      $_blockName_.'.css') */ ->loadJSFile()/*   .js*/ ->addCssRule('color:red','hover') /*       */ ->setTag('a') /* .         Block::TAG_DEFAULT*/ ->setAttribute('href','http://tricksterz.ru') /*  */ ->setContent('Tricksterz') /* */ ->addContent('<b>',true) /*   */ ->addContent('</b>') /*  */ ;
      
      





ここで、Blockクラスのオブジェクトを作成します。これは、作成時にブロックストレージに保存され、ブロックファイルが保存されているディレクトリを示し、ファイルをロードします(パスは上記で指定したディレクトリに相対的です)、スタイルルールを追加し(2番目のパラメーターは擬似クラス)、ブロックタグを設定しますデフォルトはdivです)、属性を追加し、コンテンツを貼り付けます。 注目に値する2つのメソッドは、setContentとaddContentです。 1つ目-前のコンテンツを削除してコンテンツを設定し、2つ目はコンテンツを追加します。addContentメソッドには2つ目のパラメーターがあり、trueの場合は既存のコンテンツの先頭に、falseの場合はコンテンツを追加します デフォルトはfalseです。



木を育てる



ブロックが作成され、ブロックストレージにロードされました。次に、それらを明らかにします。 これを行うには、Treeモジュールを接続してBEMツリーを構築する必要があります。

 use BemPHP\Tree; […] echo Tree::html('b-block-name');
      
      





作成されたHTMLドキュメントにエントリが表示されます。

 <a class='b-block-name' href='http://tricksterz.ru' ><b>Tricksterz</b></a>
      
      





すべて順調ですが、クラス '.b-block-name'のスタイルの説明はありません。 これを行うには、スタイルタグ内のページヘッダーで、すべてのブロックのcssを表示します。

 <?php echo "<style> "; print_r(BemPHP::getCss()); echo "</style>"; ?>
      
      





jsスクリプトでも同じことを行います。

 <script> <?php print_r(BemPHP::getJs()); ?> </script>
      
      





将来、これらのスクリプトは最小化して個別のファイルに表示できます(リリース1.2で実装が計画されています)。

Tree :: html($ blockName)メソッドはオブジェクトを返しますが、オブジェクトはブロックそのものではなく、ラッパー内のブロックであることに注意してください。 これは、ブロックを「オンザフライ」で再定義できるようにするために必要です。 例のコード:

 echo Tree::html('b-block-name')->setTag('p'); echo Tree::html('b-block-name');
      
      





次を出力します。

 <p class='b-block-name' href='http://tricksterz.ru' ><b>Tricksterz</b></p> <a class='b-block-name' href='http://tricksterz.ru' ><b>Tricksterz</b></a>
      
      





つまり、出力中にブロック自体を変更せずにタグを再定義しました。

Tree :: html()はオブジェクトを返すため、変数を使用してリンクを割り当てることができます。

 $b_block_name = Tree::html('b-block-name');
      
      





この場合、タグを再定義すると、特定のラッパーオブジェクトのプロパティを変更するため、この変数で「生きている」ままになります。

 echo $b_block_name->setTag('p'); echo $b_block_name;
      
      





出力:

 <p class='b-block-name' href='http://tricksterz.ru' ><b>Tricksterz</b></p> <p class='b-block-name' href='http://tricksterz.ru' ><b>Tricksterz</b></p>
      
      





ラッパーを元の状態に戻すため、つまり 元のブロックの状態に戻すには、getDefault()メソッドを使用する必要があります。

 echo $b_block_name->setTag('p'); //   p echo $b_block_name->getDefault(); //   a
      
      





したがって、たとえば、すべてのブロックが変数の形式で記述されるファイルを作成できます。

 $b_menu = Tree::html('b-menu'); $b_menu__item = Tree::html('b-menu__item'); […]
      
      





接続し、構文強調表示でBEMツリーを記述します。

 echo $b_menu->setContent( $b_menu__item->setContent('Home')->setAttribute('href','#home'). $b_menu__item->setContent('Music')->setAttribute('href','#music'). $b_menu__item->setContent('Video')->setAttribute('href','#video') );
      
      





複合ブロック



「ブロックではすべてが明確に見えますが、要素と修飾子についてはどうですか?」熱心な読者は叫ぶでしょう。 実際には、要素と修飾子は本質的に同じブロックであり、親ブロックと組み合わせて使用​​されるだけです。 理解するために、前に述べた投稿で説明されている特定の例を分析します。 そのようなメニューの実装があります:

画像

やってみましょう。 最初に、b-menu.cssの中に内容を持つフォルダー「b-menu」を作成します。

 .b-menu { margin:0; padding:0; list-style:none; width:100%; display:table; table-layout: fixed; }
      
      





次に、その中のb-linkフォルダーはb-link.cssです。

 .b-link { color:#525252; font-size:12px; }
      
      





b-linkフォルダーで、b-link_menu修飾子フォルダーを作成します。

 .b-link_menu { text-align:center; color:#bfbfbf; cursor:pointer; font-size:14px; height:38px; background-color:#f3f3f3; line-height:38px; border: 1px solid #e7e7e7; display:table-cell; text-decoration: none; }
      
      





b-link_menuフォルダーで、別のb-link_menu_active修飾子を作成します。

 .b-link_menu_active { color:#fefefe; background-color:#29c5e6; border:1px solid #29c5e6; cursor: default; }
      
      





次に、適切なフォルダーにb-menu.php、b-link.php、b-link_menu_active.phpファイルを作成して、ブロックパラメーターを定義します。

 //b-menu.php $_blockObj_ = new Block('b-menu'); $_blockObj_->setBlockDir(__DIR__) ->loadCSSFile() ->setTag('nav'); //b-link.php $_blockObj_ = new Block('b-link'); $_blockObj_->setBlockDir(__DIR__) ->loadCSSFile() ->setTag('a'); //b-link_menu_active.php $_blockObj_ = new Block('b-link_menu_active'); $_blockObj_->setBlockDir(__DIR__) ->loadCSSFile() ->setTag('div');
      
      





次に、これらすべてをページに追加します。

 //     $menu_items_arr = array('HOME'=>'home', 'ABOUT US'=>'aboutus', 'SERVICES'=>'services', 'PARTNERS'=>'partners', 'CUSTOMERS'=>'customers', 'PROJECTS'=>'projects', 'CAREERS'=>'careers', 'CONTACT'=>'contact'); //      foreach ($menu_items_arr as $itemName=>$param) { if ($_GET['param']==$param) $active = ' b-link_menu_active'; else $active=null; $menu_items_tree = $menu_items_tree.Tree::html('b-link b-link_menu'.$active)->setAttribute('href','?param='.$param)->setContent($itemName); } //      $main_menu = Tree::html('b-menu')->setContent($menu_items_tree); echo $main_menu;
      
      





ご覧のとおり、Tree :: html()メソッドでは、スペースを使用して複数のブロック名を一度に追加できます。 この場合、ブロックパラメーターのカスケード再割り当てが発生します。 たとえば、タグ 'a'はb-linkブロックで定義され、タグはb-link_menu_activeブロックで 'div'です。 Tree :: html( 'b-link b-link_menu')と書くと、タグ 'b'は出力中に指定されます。タグはb-link_menuブロックで定義されておらず、前のブロックから継承されるためです。 Tree :: html( 'b-link b-link_menu b-link_menu_active')を記述する場合、タグの 'div'はチェーンの最後のブロックで定義されているため、示されます。 同じことがコンテンツでも発生します。 次の属性が発生します。この属性が既に存在する場合は再定義され、前のブロックにそのような属性がなかった場合は、既存の属性に追加されます。



パン



ページを作成した結果として得られるhtmlコードを見ると、インデントや改行がないため読みにくくなりますが、生成されたブロックのhtmlを見る必要がある場合は、 lighting()メソッドを使用した「ハイライト」:

 echo Tree::html('b-block-name')->lighting();
      
      





生成されたhtmlには次のようになります。

 <!-- == BLOCK b-block-name HERE!!! == --!> <a class='b-block-name' href='http://tricksterz.ru' ><b>Tricksterz</b></a> <!-- ========= END ========= --!>
      
      





また、必要なコードを簡単に見つけることができます。

また、BemPHPには、ログを記録するためのクラスLogWriterがあります。 次のようにレコードを追加できます:

 LogWriter::putLog('',3);
      
      





この場合、msg = 'Comment'およびmsgType = '3'のLogオブジェクトが作成され、LogStorageクラスのログストアに配置されます。 独自のログ出力を実装できます。このため、Notifycatorインターフェイスを接続し、LogStorageクラスのオブジェクトをパラメーターとして受け取るnotifyメソッド($ logStorage)を使用してクラスを作成する必要があります。 また、既存のロガーを使用できます。

 echo BemPHP::showLogger();
      
      





この場合、ページの右下隅にウィンドウが表示され、ログが表示されます。 カーソルがホバーしていない場合、ウィンドウは透明になります。また、対応するボタンをクリックしてウィンドウを最小化することもできます。



Loggerの作業のために、JQueryライブラリを接続する必要があり、ShowLoggerメソッドの呼び出しはページの最後でなければならないことに注意してください。



なぜこれがすべて必要なのですか?



BEM方法論のアイデアは、独立したブロックでレイアウトを作成することです。 このアプローチを使用すると、修正中にレイアウトが崩れないという安心感が得られます。 また、開発チーム内でタスクをより効率的に分散し、プロジェクトに関係するすべての人に単一のモデル言語を作成することもできます。 BemPHPでは、方法論をオブジェクト指向環境に移行できます。 その結果、レイアウトだけでなく、 オブジェクト指向のレイアウトが得られます



ご意見、ご意見、ご質問をお待ちしております。



All Articles