Wie ich einen Codegenerator in PHP geschrieben habe und was daraus wurde

GrĂŒnde und Probleme, die gelöst werden mĂŒssen



In diesem Artikel werde ich Ihnen erzĂ€hlen, wie ich einen Codegenerator in PHP geschrieben habe. Ich erzĂ€hle Ihnen von dem Weg, den er von der Generierung einfacher Tabellen zu einem ziemlich vollstĂ€ndigen Generator von HTML- und CSS-Code gegangen ist. Ich werde Beispiele fĂŒr seine Verwendung geben und bereits abgeschlossene Projekte zeigen.



In diesem Semester konnte nur PHP in einem der FĂ€cher verwendet werden.



Nach dem endlosen Projekt umbenennenDas Projekt wurde MelonPHP genannt. Damit die Leute ĂŒber Essen nachdenken, wenn sie seinen Namen sagen? Aber wir haben hier einen Artikel, in dem es nicht darum geht, Delirium zu erzeugen. Lassen Sie mich Ihnen den Grund fĂŒr seine Entstehung erlĂ€utern.



Es gab viel zu schreiben, aber das ist kein Problem. Das Hauptproblem war die Ausgabe von HTML-Code ĂŒber PHP. Ich werde versuchen, das Problem unten zu erklĂ€ren.



Hier ist zum Beispiel die Textausgabe ĂŒber das bekannte Echo:



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


Es sieht einfach und unkompliziert aus. Nehmen wir einen Ausschnitt aus dem Code meines Freundes, in dem er eine Tabelle generiert:



...
$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";}
...


Das schrecklich Der Code zeigt die Probleme, die ich lösen wollte:



  • Das Vorhandensein von HTML im PHP-Code, was es meiner Meinung nach weniger lesbar macht. Dennoch sollte die Datei fĂŒr ein Yap meiner Meinung nach den Code von nur einem Yap (s) enthalten
  • Es gibt keine Trennung der Logik, alles ist durcheinander. Ich wollte ein schöneres PHP-Frontend


Es ist erwÀhnenswert, dass ich schon relativ lange in Flutter schreibe und die Idee dahinter, die mit dem Schreiben einer BenutzeroberflÀche durch Erstellen eines Baums aus Widgets zusammenhÀngt, sehr mag. Ich beschloss, die Idee mit Knoten (Widgets) von dort auszuleihen.



, , .



. .



:



  • 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.



.



Drucken Sie im Text " DrĂŒcken Sie $ this-> TapCount times ".



Das war's, ein einfacher Clicker ist fertig.



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();




Ergebnis



Ich habe es geschafft, einen einfachen, aber leistungsfÀhigen Codegenerator zu schreiben.



Er ging von der Erstellung einfacher Tabellen zu einem vollwertigen HTML- und CSS-Generator ĂŒber, mit dem Sie Projekte bequem gestalten und Layout mit Logik kombinieren können.



In diesem Rahmen habe ich ein Kursprojekt geschrieben (Screenshots unten), es in der PrĂŒfung verwendet und Studienaufgaben gemacht.



Screenshots des Kursprojekts auf MelonPHP







Quellen



GitHub - MelonPHP



Flattern



MAUI




All Articles