PHPでコードジェネレーターを作成した方法とその結果

解決すべき理由と問題



この記事では、phpでコードジェネレーターを作成した方法について説明します。彼が単純なテーブルを生成してから、htmlおよびcssコードのかなり完全なジェネレーターに至るまでの道のりについて説明します。その使用例を示し、すでに完了したプロジェクトを示します。



今学期は、1つの科目でPHPのみを使用できました。



無限のプロジェクトの名前を変更した後プロジェクトはMelonPHPと名付けられました。人々が彼の名前を言うときに食べ物について考えるために?しかし、ここにデリリウムの生成に関する記事がないので、デリリウムが作成された理由について説明します。



書くことはたくさんありましたが、それは問題ではありません。主な問題は、PHPを介してHTMLコードを出力することでした。以下に問題を説明しようと思います。



たとえば、おなじみのエコーを介して出力されるテキストは次のとおりです。



$text = "out text";
echo "<p>$text</p>";


シンプルでわかりやすいように見えます。友人がテーブルを生成するコードのスニペットを見てみましょう。



...
$sql = "SELECT * FROM table";$result = $conn->query($sql);
if($result->num_rows > 0) {
    echo "<b>Table table</b><br><br>";
    echo "<table border=2>";
  echo "<tr><td> name </td>"."<td> name </td>"."<td> name </td></tr>";
    while($row = $result->fetch_assoc()) {
        echo "<tr><td>".$row["name"]."</td><td>".$row["name"]."</td><td>".$row["name"]."</td></tr>";
    }
    echo "</table>";
} else {
echo "0 results";}
...


それ ひどい コードは、私が解決したかった問題を示しています。



  • phpコードにhtmlが存在するため、私の意見では読みにくくなっています。それでも、私の意見では、1つのヤップのファイルには1つのヤップのコードのみが含まれている必要があります
  • ロジックの分離はなく、すべてが混乱しています。より良いPHPフロントエンドが欲しかった


私は比較的長い間Flutterで書いてきましたが、ウィジェットからツリーを構築してインターフェイスを作成するという、その背後にあるアイデアが本当に気に入っていることは注目に値します。そこからノード(ウィジェット)でアイデアを借りることにしました。



, , .



. .



:



  • UI / ( React)
  • ( div, div, div, div...)
  • UI PHP ( JS, HTML, CSS).
  • Rebuild callback , AJAX + JQuery
  • CSS ( , "width: 100px", PHP )


MelonPHP



  • ( , ) 100%, .
  • , , . ScrollView.
  • .




, PHP , . ( , Microsoft MAUI, ).



MelonPHP Node. , 2 : Generate(), static Create().



  • Generate() string — .
  • Create() — . .


abstract class Node
{
  abstract function Generate() : string;

  static function Create() ...
}


Element


Element — , .



html .



, , .



Component


, , . ( ).



( MelonPHP), , , .



abstract class Component extends Element
{
  function Initialize() ...

  abstract function Build() : Element;

  function Detach() ...
}


, ; Element. .



. ListItem, Component.



Initialize() Build().



Initialize() . .



Build() . . .



Detach() .

Build() , $Text.



Initialize() $Text .



Text(string) $Text.



$this , .


class ListItem extends Component
{
  private $Text;

  function Initialize() {
    $this->Text = "Name";
  }

  function Build() : Element {
    return Container::Create()
    ->Child(
      Text::Create()
      ->Text($this->Text)
    );
  }

  function Text(string $string) {
    $this->Text = $string;
    return $this;
  }
}


DisplayComponent


DisplayComponent — , . Display.



.



Build() Document Title(string).



DisplayComponent, Build() Document. Document — , HTML5.

BuildList(), ListItem.



BuildList() . .



- , Builder. ...

Diplay(), , c .



class ListDisplay extends DisplayComponent
{

  function Build() : Document {
    return Document::Create()
    //  
    ->Title("test page")
    ->Child($this->BuildList());
  }

  function BuildList() {
    $column = new Column;
    for($i = 0; $i < 10; $i++)
      $column->Children(
        ListItem::Create()
        ->Text("number: $i")
      );
    return $column;
  }

} ListDisplay::Display();




— .



Container




Container — , .



.



Column Row


. Child , Children .



Child Children .



Children , .



Children([Text::Create()]) Children(Text::Create())

Column — , .



CrossAlign MainAlign .





Row Column, .





Stack


Stack — , . , .





ScrollView, HorizontalScrollView, VerticalScrollView




.



HorizontalScrollView — .



VerticalScrollView — .



ScrollView — .





css .



css "background-color". php "". .



...
const BackgroundBlendMode = "background-blend-mode";
const BackgroundAttachment = "background-attachment";
const Border = "border";
const BorderSpacing = "border-spacing";
const BorderRadius = "border-radius";
const BorderImage = "border-image";
...


"34".Px. . css — Px(34). .





ThemeParameter(...). — , — /.



.



#f0f0f0.



. 20px, 15px.



. , CommaLine().


...
Container::Create()
->ThemeParameter(BackgroundColor, Hex("f0f0f0"))
->ThemeParameter(Padding, [Px(20), Px(15)]);
...


, (hover )? .





— css, media, keyframes, .



hover active.



ThemeBlock ThemeBlocks.



/ . my_container.



. : StandartModifier, HoverModifier, ActiveModifier. Parameter(...). Parameter ThemeParameter.



function GetMyTheme() : Theme {
  return Theme::Create()
  ->ThemeBlocks([
    ThemeBlock::Create()
    ->Keys("my_container")
    ->Modifiers([
      StandartModifier::Create()
      ->Parameter(BackgroundColor, Red)
      ->Parameter(Padding, [Px(10), Px(12)]),
      HoverModifier::Create()
      ->Parameter(BackgroundColor, Green),
      ActiveModifier::Create()
      ->Parameter(BackgroundColor, Blue)
    ])
  ]);
}


( css) ThemeKeys. Themes.



class TestThemeDisplay extends DisplayComponent
{

  function Build() : Document {
    return Document::Create()
    ->Themes(GetMyTheme())
    ->Child(
      Container::Create()
      ->ThemeKeys("my_container")
    );
  }

} TestThemeDisplay::Display();


.





keyframes.



keyframe, FrameBlocks.



FrameBlock.



FrameBlock Frames. , Value. ( Pr(value)) From To.



, .



, shake_text.



, .



, .



function GetMyTheme() : Theme {
  return Theme::Create()
  ->ThemeBlocks([
    ThemeBlock::Create()
    ->Keys("my_container")
    ->Modifiers([
      StandartModifier::Create()
      ->Parameter(Padding, [Px(10), Px(12)]),
      HoverModifier::Create()
      ->Parameter(BackgroundColor, Green),
      ActiveModifier::Create()
      ->Parameter(BackgroundColor, Blue)
    ]),
    ThemeBlock::Create()
    ->Keys("shake_text")
    ->Modifiers([
      StandartModifier::Create()
      ->Parameter(Color, Red)
      ->Parameter(Animation, ["shake_text_anim", ".2s", "ease-in-out", "5", "alternate-reverse"])
    ])
  ])
  ->FrameBlocks(
    FrameBlock::Create()
    ->Key("shake_text_anim")
    ->Frames([
      Frame::Create()
      ->Value(Pr(0))
      ->Parameter(Transform, Translate(0, 0)),
      Frame::Create()
      ->Value(Pr(25))
      ->Parameter(Color, Hex("ff4040"))
      ->Parameter(Filter, Blur(Px(0.5))),
      Frame::Create()
      ->Value(Pr(50))
      ->Parameter(Filter, Blur(Px(1.2))),
      Frame::Create()
      ->Value(Pr(75))
      ->Parameter(Color, Hex("ff4040"))
      ->Parameter(Filter, Blur(Px(0.5))),
      Frame::Create()
      ->Value(Pr(100))
      ->Parameter(Transform, Translate(Px(10), 0)),
    ])
  );
}


class TestThemeDisplay extends DisplayComponent
{

  function Build() : Document {
    return Document::Create()
    ->Themes(GetMyTheme())
    ->Child(
      Container::Create()
      ->ThemeKeys("my_container")
      ->Child(
        Text::Create()
        ->ThemeKeys("shake_text")
        ->Text("Error text")
      )
    );
  }

} TestThemeDisplay::Display();






2 . , . : MinWidth, MaxWidth, MinHeight, MaxHeight, .



MinWidth 800px.



MaxWidth 800px.



, — . adaptive_color.



.



.



function GetMobileTheme() : Theme {
  return Theme::Create()
  ->MinWidth(Px(800))
  ->ThemeBlocks(
    ThemeBlock::Create()
    ->Keys("adaptive_color")
    ->Modifiers(
      StandartModifier::Create()
      ->Parameter(BackgroundColor, Green)
    )
  );
}


function GetDesktopTheme() : Theme {
  return Theme::Create()
  ->MaxWidth(Px(800))
  ->ThemeBlocks(
    ThemeBlock::Create()
    ->Keys("adaptive_color")
    ->Modifiers(
      StandartModifier::Create()
      ->Parameter(BackgroundColor, Red)
    )
  );
}


class TestThemeDisplay extends DisplayComponent
{

  function Build() : Document {
    return Document::Create()
    ->Themes([
      GetMyTheme(), 
      GetDesktopTheme(), 
      GetMobileTheme()
    ])
    ->Child(
      Container::Create()
      ->ThemeKeys(["my_container", "adaptive_color"])
      ->Child(
        Text::Create()
        ->ThemeKeys("shake_text")
        ->Text("Error text")
      )
    );
  }

} TestThemeDisplay::Display();






.



DisplayComponent.



Build() Document.



class ClickerDisplay extends DisplayComponent
{

  function Build() : Element {
    return Document::Create()
    ->Title("Clicker"); 
  }

} ClickerDisplay::Display();


.



.



class ClickerDisplay extends DisplayComponent
{

  function Build() : Element {
    return Document::Create()
    ->Title("Clicker")
    ->Child(
      Column::Create()
      ->Children([
        Text::Create()
        ->Text("Pressed 0 times"),
        Button::Create()
        ->Text("Press")
      ])
    ); 
  }

} ClickerDisplay::Display();


.





ThemeParameter, .



class ClickerDisplay extends DisplayComponent
{

  function Build() : Element {
    return Document::Create()
    ->Title("Clicker")
    ->Child(
      Column::Create()
      ->ThemeParameter(Padding, Px(15))
      ->Children([
        Text::Create()
        ->ThemeParameter(PaddingBottom, Px(15))
        ->Text("Pressed 0 times"),
        Button::Create()
        ->ThemeParameter(Width, Auto)
        ->ThemeParameter(Padding, [Px(4), Px(10)])
        ->ThemeParameter(BackgroundColor, Blue)
        ->ThemeParameter(Color, White)
        ->ThemeParameter(BorderRadius, Px(4))
        ->Text("Press")
      ])
    ); 
  }

} ClickerDisplay::Display();


.





.



Initialize() TapCount.



form — Action.

Action . Action Post. , .



click_count Action. TapCount.



Initialize() Action::GetValue(name, standart_value, action_type) . 0, Post.



.



本文では、「$ this-> TapCounttimesを押してください」と印刷します



これで、簡単なクリッカーの準備が整いました。



class ClickerDisplay extends DisplayComponent
{
  private $TapCount;

  function Initialize() {
    $this->TapCount = Action::GetValue("click_count", 0 /* standart value */, ActionTypes::Post);
    $this->TapCount++;
  }

  function Build() : Document {
    return Document::Create()
    ->Title("Test page")
    ->Child(
      Action::Create()
      ->Type(ActionTypes::Post)
      ->Variable("click_count", $this->TapCount)
      ->Child(
        Column::Create()
        ->ThemeParameter(Padding, Px(15))
        ->Children([
          Text::Create()
          ->ThemeParameter(PaddingBottom, Px(15))
          ->Text("Press $this->TapCount times"),
          Button::Create()
          ->ThemeParameter(Width, Auto)
          ->ThemeParameter(Padding, [Px(4), Px(10)])
          ->ThemeParameter(BackgroundColor, Blue)
          ->ThemeParameter(Color, White)
          ->ThemeParameter(BorderRadius, Px(4))
          ->Text("Press")
        ])
      )
    );
  }
} ClickerDisplay::Display();




結果



シンプルでありながら強力なコードジェネレーターを作成することができました。



彼は、単純なテーブルの生成から、プロジェクトを便利にレイアウトし、レイアウトとロジックを組み合わせることができる本格的なhtmlおよびcssジェネレーターに移行しました。



このフレームワークで、私はコースプロジェクト(以下のスクリーンショット)を作成し、それを試験で使用し、研究課題を行いました。



MelonPHPで作成されたコースプロジェクトのスクリーンショット







ソース



GitHub-MelonPHP



フラッター



マウイ




All Articles