Raisons et problÚmes à résoudre
Dans cet article, je vais vous expliquer comment j'ai écrit un générateur de code en php. Je vais vous parler du chemin qu'il est passé de la génération de tableaux simples à un générateur assez complet de code html et css. Je vais donner des exemples de son utilisation et montrer des projets déjà achevés.
Ce semestre, seul PHP pouvait ĂȘtre utilisĂ© dans l'une des matiĂšres.
AprÚs le renommage du projet sans finLe projet a été nommé MelonPHP. Pour que les gens pensent à la nourriture quand ils disent son nom? Mais nous avons ici un article non pas sur la génération du délire, alors laissez-moi vous expliquer la raison de sa création.
Il y avait beaucoup Ă Ă©crire, mais ce n'est pas un problĂšme. Le principal problĂšme Ă©tait la sortie du code HTML via PHP. Je vais essayer d'expliquer le problĂšme ci-dessous.
Par exemple, voici la sortie de texte via l'Ă©cho familier:
$text = "out text";
echo "<p>$text</p>";
Cela semble simple et direct. Prenons un extrait du code de mon ami oĂč il gĂ©nĂšre une table:
...
$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";}
...
il terrible le code montre les problÚmes que je voulais résoudre:
- La présence de html dans le code php, ce qui le rend moins lisible à mon avis. Pourtant, le fichier pour un yap devrait contenir le code d'un seul yap (s), à mon avis
- Il n'y a pas de séparation de la logique, tout est en désordre. Je voulais une interface PHP plus agréable
Il est intĂ©ressant de noter que j'Ă©cris dans Flutter depuis relativement longtemps et que j'aime vraiment l'idĂ©e derriĂšre cela, liĂ©e Ă l'Ă©criture d'une interface en construisant un arbre Ă partir de widgets. J'ai dĂ©cidĂ© d'emprunter l'idĂ©e avec des nĆuds (widgets) Ă partir de lĂ .
, , .
. .
:
- 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.
.
Imprimer " Press $ this-> TapCount times " dans le texte .
VoilĂ , un simple clicker est prĂȘt.
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();
RĂ©sultat
J'ai réussi à écrire un générateur de code simple mais assez puissant.
Il est passé de la génération de tableaux simples à un générateur html et css à part entiÚre, sur lequel vous pouvez facilement mettre en page des projets et combiner la mise en page avec la logique.
Sur ce cadre, j'ai écrit un projet de cours (captures d'écran ci-dessous), je l'ai utilisé dans l'examen et y ai étudié des devoirs.