Remove unnecessary we
This commit is contained in:
Родитель
6dec8e8d14
Коммит
be4611fe92
|
@ -154,8 +154,8 @@ Then a programmer avoids to use the workaround defined above.
|
||||||
\subsection{Interoperability}
|
\subsection{Interoperability}
|
||||||
|
|
||||||
The last feature to discuss in this section is interoperability between Javascript and PHP.
|
The last feature to discuss in this section is interoperability between Javascript and PHP.
|
||||||
As we mentioned, Blazor allows calling Javascript functions from C\# \cite{online:interop1} and vice-versa \cite{online:interop2}.
|
Blazor allows calling Javascript functions from C\# \cite{online:interop1} and vice-versa \cite{online:interop2}.
|
||||||
We can utilize a Blazor service,\texttt{IJSRuntime}, injected by the dispatcher, to call Javascript functions.
|
Thus, a Blazor service,\texttt{IJSRuntime} injected by the dispatcher, can be utilized to call Javascript functions.
|
||||||
The service offers a specialized API for that.
|
The service offers a specialized API for that.
|
||||||
Calling PHP from Javascript is more complex.
|
Calling PHP from Javascript is more complex.
|
||||||
Peachpie enables calling PHP function by \texttt{Call} method of \texttt{Context}.
|
Peachpie enables calling PHP function by \texttt{Call} method of \texttt{Context}.
|
||||||
|
@ -167,37 +167,37 @@ These conditions lead us to create a new Peachpie context,\texttt{BlazorContext}
|
||||||
The context requests the mentioned services provided by the dispatcher and sets the reference by calling predefined code in \texttt{Peachpie.Blazor.js}.
|
The context requests the mentioned services provided by the dispatcher and sets the reference by calling predefined code in \texttt{Peachpie.Blazor.js}.
|
||||||
The context will be the Peachpie context of the component.
|
The context will be the Peachpie context of the component.
|
||||||
Thus, it enables to call PHP methods defined in this context from Javascript by using the reference.
|
Thus, it enables to call PHP methods defined in this context from Javascript by using the reference.
|
||||||
The advantage of this approach is that we can have two components inheriting \texttt{PhpComponent} with the same context when we set their context to the same instance.
|
The advantage of this approach is that there can be two components inheriting \texttt{PhpComponent} with the same context when their context is set to the same instance.
|
||||||
Thus, we can call their functions by only one reference.
|
Thus, we can call their functions only by one reference.
|
||||||
|
|
||||||
\subsection{Summary}
|
\subsection{Summary}
|
||||||
|
|
||||||
\begin{figure}[b!]
|
\begin{figure}[t!]
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[scale=0.8]{./img/PhpComponentSolution}
|
\includegraphics[scale=0.8]{./img/PhpComponentSolution}
|
||||||
\caption{Class diagram of the use case solution.}
|
\caption{Class diagram of the use case solution.}
|
||||||
\label{img17:solution}
|
\label{img17:solution}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\par
|
\par
|
||||||
We summarize the architecture of \texttt{PhpComponent} and solution of \textit{WebGame} use case.
|
This section summarizes the architecture of \texttt{PhpComponent} and solution of \textit{WebGame} use case.
|
||||||
The component hides the original function for rendering and replaces it with our version of the builder, as shown in Figure \ref{img17:solution}.
|
The component hides the original function for rendering and replaces it with our version of the builder, as shown in Figure \ref{img17:solution}.
|
||||||
It results in transparent usage of the builder in the inherited class.
|
It results in transparent usage of the builder in the inherited class.
|
||||||
The builder is just a wrapper, so the programmer can use the original builder by accessing its property, \texttt{Builder}.
|
The builder is just a wrapper, so the programmer can use the original builder by accessing its property, \texttt{Builder}.
|
||||||
Additionally, there is a collection of classes for creating tags, making builder usage easier.
|
Additionally, there is a collection of classes for creating tags, making builder usage easier.
|
||||||
For assigning PHP handlers to C\# events, there is a universal helper class, \texttt{EventHelper}.
|
For assigning PHP handlers to C\# events, there is a universal helper class, \texttt{EventHelper}.
|
||||||
Furthermore, the last feature is a timer wrapper, which uses the C\# timer, offering a convenient API.
|
Furthermore, the last feature is a timer wrapper, which uses the C\# timer, offering a convenient API.
|
||||||
We can use our predefined API using \texttt{BlazorContext} for interoperability with Javascript.
|
Interoperability with Javascript is provided by our predefined API using \texttt{BlazorContext}.
|
||||||
These features are sufficient for implementing a game described in \textit{WebGame} use case.
|
These features are sufficient for implementing a game described in \textit{WebGame} use case.
|
||||||
Using PHP functions as handlers, we use the timer to update the game screen by \texttt{StateHasChanged}.
|
Using PHP functions as handlers, the timer is used to update the game screen by \texttt{StateHasChanged}.
|
||||||
The update consists of evaluating the position of game entities, which use the helper classes representing HTML entities.
|
The update consists of evaluating the position of game entities, which use the helper classes representing HTML entities.
|
||||||
Lastly, we use context preservation to keep the game state.
|
Lastly, context preservation is used to keep the game state.
|
||||||
\par
|
\par
|
||||||
The last necessary thing is to pass assembly references containing the components into \texttt{Router}, which is a standard duty in Blazor.
|
The last necessary thing is to pass assembly references containing the components into \texttt{Router}, which is a standard duty in Blazor.
|
||||||
|
|
||||||
\section{PhpScriptProvider}
|
\section{PhpScriptProvider}
|
||||||
|
|
||||||
At the beginning of this section, we introduce the main component parts, which gives us an overview of the component composition.
|
The beginning of this section introduces the main component parts, which gives us an overview of the component composition.
|
||||||
We divide component duties like navigation or script execution into subsections because the component consists of many processes, which are complex to describe at once in the structure.
|
Component duties like navigation or script execution are divided into subsections because the component consists of many processes, which are complex to describe at once in the structure.
|
||||||
The component functionality will be explained in these sections.
|
The component functionality will be explained in these sections.
|
||||||
\par
|
\par
|
||||||
\begin{figure}[b!]
|
\begin{figure}[b!]
|
||||||
|
@ -207,7 +207,7 @@ The component functionality will be explained in these sections.
|
||||||
\label{img18:provider}
|
\label{img18:provider}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
\par
|
\par
|
||||||
We start with Figure \ref{img18:provider} describing the connections between the main parts.
|
Figure \ref{img18:provider} describes the connections between the main parts.
|
||||||
\texttt{PhpScriptProvider} is a class, representing a Blazor component.
|
\texttt{PhpScriptProvider} is a class, representing a Blazor component.
|
||||||
The component manages the following features.
|
The component manages the following features.
|
||||||
\par
|
\par
|
||||||
|
@ -226,7 +226,7 @@ The context constructor accepts several Blazor services like \texttt{IJSRuntime}
|
||||||
The context initializes superglobals based on URL and submitted forms, manages files uploaded by a form, and controls \texttt{BlazorWriter} which redirects the script output to the render tree.
|
The context initializes superglobals based on URL and submitted forms, manages files uploaded by a form, and controls \texttt{BlazorWriter} which redirects the script output to the render tree.
|
||||||
Lastly, \texttt{FileManager} reads submitted files, downloads them, or deletes them from Browser memory.
|
Lastly, \texttt{FileManager} reads submitted files, downloads them, or deletes them from Browser memory.
|
||||||
\par
|
\par
|
||||||
We zoom in on \texttt{PhpScriptProvider} structure in order to better understand processes maintaining the features.
|
The following paragraph zooms in \texttt{PhpScriptProvider} structure in order to better understand processes maintaining the features.
|
||||||
The provider contains of many properties.
|
The provider contains of many properties.
|
||||||
Some of them are injected by the dispatcher like \texttt{NavigationManager} or \texttt{IJSRuntime}, which is a service providing interoperability with Javascript.
|
Some of them are injected by the dispatcher like \texttt{NavigationManager} or \texttt{IJSRuntime}, which is a service providing interoperability with Javascript.
|
||||||
Others can be parametrized, like \texttt{Type} determining the mode of provider, \texttt{ContextLifetime} determining the persistency of the script context, or \texttt{ScriptName} determining the executing script when the mode \textit{Script} is set.
|
Others can be parametrized, like \texttt{Type} determining the mode of provider, \texttt{ContextLifetime} determining the persistency of the script context, or \texttt{ScriptName} determining the executing script when the mode \textit{Script} is set.
|
||||||
|
@ -239,7 +239,7 @@ Some of these methods are called by Blazor framework providing the component lif
|
||||||
|
|
||||||
\subsection{Navigation}
|
\subsection{Navigation}
|
||||||
|
|
||||||
Now, we explain navigation in \texttt{PhpScriptProvider} for each of its modes.
|
The section explains navigation in \texttt{PhpScriptProvider} for each of provider modes.
|
||||||
We have to clarify how the component is instantiated and maintained by Blazor.
|
We have to clarify how the component is instantiated and maintained by Blazor.
|
||||||
There are two ways how to use the component.
|
There are two ways how to use the component.
|
||||||
The first of them is to set it in \texttt{WebAssemblyBuilder} as a root component,
|
The first of them is to set it in \texttt{WebAssemblyBuilder} as a root component,
|
||||||
|
@ -253,34 +253,35 @@ Then, when the parameters are changed, Blazor automatically calls the inner comp
|
||||||
This fact is because the Blazor framework can not decide if the parameters, which are complex types, were changed.
|
This fact is because the Blazor framework can not decide if the parameters, which are complex types, were changed.
|
||||||
\par
|
\par
|
||||||
The \textit{Router} mode is designed to be used when the component is a root component.
|
The \textit{Router} mode is designed to be used when the component is a root component.
|
||||||
Then we are sure, that \texttt{Attach} and \texttt{SetParameters} methods are called only once.
|
Then, it is certain that \texttt{Attach} and \texttt{SetParameters} methods are called only once.
|
||||||
Thus, we register navigation handler in the \texttt{Attach} method, which should handle further navigation.
|
Thus, navigation handler is registered in the \texttt{Attach} method, which should handle further navigation.
|
||||||
When the navigation occurs, we create a new context if the context should not be persistent and call \texttt{Refresh}.
|
When the navigation occurs, a new context is created if the context should not be persistent, then the \texttt{Refresh} method is called.
|
||||||
We create a new context and call \texttt{Refresh} method in \texttt{SetParameters} as well, but the method is called only once at the beginning of the application.
|
\texttt{SetParameters} creates a new context and calls the \texttt{Refresh} method as well, but the method is called only once at the beginning of the application.
|
||||||
Then the \texttt{Refresh} method parses the query part of URL \cite{online:querryStrings}, obtained from \texttt{NavigationManager} and gets the script name from the URL.
|
Then the \texttt{Refresh} method parses the query part of URL \cite{online:querryStrings}, obtained from \texttt{NavigationManager} and gets the script name from the URL.
|
||||||
When we determine the script name, we call the \texttt{Render} method, where we decide if it is a script or a component defined in a script based on \texttt{.php} extension.
|
When the script name is determined, the method calls the \texttt{Render} method, where it decides if it is a script or a component defined in a script based on \texttt{.php} extension.
|
||||||
If the extension is missing, we try to find a component defined in scripts, which has correct \texttt{RouteAttribute} by \texttt{PhpComponentRouteManager}.
|
If the extension is missing, it tries to find a component defined in scripts, which has correct \texttt{RouteAttribute} by \texttt{PhpComponentRouteManager}.
|
||||||
Otherwise, we ask the Peachpie context for obtaining the script representation as \texttt{ScriptInfo}.
|
Otherwise, it asks the Peachpie context for obtaining the script representation as \texttt{ScriptInfo}.
|
||||||
Additional manager duty is to assign assembly references containing scripts, to the context, at the beginning of the application.
|
Additional manager duty is to assign assembly references containing scripts, to the context, at the beginning of the application.
|
||||||
The context does not have to know the script name, or the component does not have to exist.
|
The context does not have to know the script name, or the component does not have to exist.
|
||||||
Then we render predefined \textit{not found} page, which can be set by \texttt{PhpScriptProvider} parameters.
|
Then, the \texttt{Render} method renders predefined \textit{not found} page, which can be set by \texttt{PhpScriptProvider} parameters.
|
||||||
Otherwise, we render the script or the component.
|
Otherwise, it renders the script or the component.
|
||||||
Additionally, when we navigate the component, we set its context by our context.
|
Additionally, when the component is navigated, the method sets its context by the current provider context.
|
||||||
It results in using the interoperability by either provider or the component because we can use the same context reference in Javascript code.
|
It results in using the interoperability by either provider or the component because there is the same context reference in Javascript code.
|
||||||
\par
|
\par
|
||||||
Next modes, \textit{ScriptProvider} and \textit{Script}, are similar.
|
Next modes, \textit{ScriptProvider} and \textit{Script}, are similar.
|
||||||
They are defined in a Razor page and initialized when the page is navigated.
|
They are defined in a Razor page and initialized when the page is navigated.
|
||||||
The difference is finding the script by name, where the \textit{Script} always uses the name defined in the component parameter and \textit{ScriptProvider} finds script based on URL.
|
The difference is finding the script by name, where the \textit{Script} always uses the name defined in the component parameter and \textit{ScriptProvider} finds script based on URL.
|
||||||
As we said, the \texttt{SetParameters} can be called multiple times, so we call \texttt{Refresh} only by the first time in the method.
|
As we said, the \texttt{SetParameters} can be called multiple times, so the method calls \texttt{Refresh} only by the first time.
|
||||||
Additional rendering is initiated by the navigation handler.
|
Additional rendering is initiated by the navigation handler.
|
||||||
Thus, when the navigation occurs, we find and update the page, or the component is disposed if \texttt{Router} matches another Razor page.
|
Thus, when the navigation occurs, it finds and update the page, or the component is disposed if \texttt{Router} matches another Razor page.
|
||||||
We create the new context based on the \texttt{ContextLifetime} mode.
|
A new context is created based on the \texttt{ContextLifetime} mode.
|
||||||
It differs from common PHP behavior, where the context is disposed after scritps handles the request.
|
It differs from common PHP behavior, where the context is disposed after scritps handles the request.
|
||||||
This unusual approach allows calling functions defined in the context after the component is rendered, which is a part of Javascript interoperability when we can call PHP functions by Javascript.
|
This unusual approach allows calling functions defined in the context after the component is rendered, which is a part of Javascript interoperability when PHP functions can by called by Javascript.
|
||||||
We should check if the component has not already been disposed by \texttt{Router} before calling the \texttt{Refresh}.
|
We should check if the component has not already been disposed by \texttt{Router} before calling the \texttt{Refresh}.
|
||||||
Obtaining the script is similar to \textit{Router} mode.
|
Obtaining the script is similar to \textit{Router} mode.
|
||||||
|
|
||||||
\subsection{Script Execution}
|
\subsection{Script Execution}
|
||||||
|
|
||||||
We start with \texttt{BlazorWriter}, which inherits \texttt{TextWriter}.
|
We start with \texttt{BlazorWriter}, which inherits \texttt{TextWriter}.
|
||||||
The inheritance allows using the writer as \texttt{BlazorContext} output writer, which manipulates with script output.
|
The inheritance allows using the writer as \texttt{BlazorContext} output writer, which manipulates with script output.
|
||||||
The writer consists of a buffer and \texttt{RenderTreeBuilder}.
|
The writer consists of a buffer and \texttt{RenderTreeBuilder}.
|
||||||
|
@ -303,17 +304,17 @@ handling, which is described in the following section.
|
||||||
\subsection{Forms}
|
\subsection{Forms}
|
||||||
|
|
||||||
Typically, web forms are not handled by Blazor, and the are sent to the server.
|
Typically, web forms are not handled by Blazor, and the are sent to the server.
|
||||||
We use Javascript interoperability to evaluate them on the client side.
|
Javascript interoperability is used to evaluate them on the client side.
|
||||||
It starts in \texttt{AfterRender} method, where we call our Javascript function, which finds all already rendered forms and assigns them an event handler for submitting.
|
It starts in \texttt{AfterRender} method, where it calls our Javascript function, which finds all already rendered forms and assigns them an event handler for submitting.
|
||||||
When submit occurs, the handler collects all data from the form, does ordinary navigation to the page defined in \texttt{action} attribute, and prevents default behavior, which is sending the form to the server.
|
When submit occurs, the handler collects all data from the form, does ordinary navigation to the page defined in \texttt{action} attribute, and prevents default behavior, which is sending the form to the server.
|
||||||
When the navigation is handled by \texttt{PhpScriptProvider}, it gets all collected data and assigns the context superglobals by them.
|
When the navigation is handled by \texttt{PhpScriptProvider}, it gets all collected data and assigns the context superglobals by them.
|
||||||
Afterward, the script is executed, and it can access the superglobals.
|
Afterward, the script is executed, and it can access the superglobals.
|
||||||
\par
|
\par
|
||||||
In the previous paragraph, we did not explain the file management due to its complexity.
|
The previous paragraph did not explain the file management due to its complexity.
|
||||||
We describe it now.
|
We describe it now.
|
||||||
When a user loads files by form, Javascript obtains only the list of files.
|
When a user loads files by form, Javascript obtains only the list of files.
|
||||||
When we want to read the content, we have to use a reading operation, which is done asynchronously by \texttt{Promise} mentioned in the Javascript section.
|
When a programmer wants to read the content, he or she has to use a reading operation, which is done asynchronously by \texttt{Promise} mentioned in the Javascript section.
|
||||||
Thus, when we get the data during navigation, we have to wait until the content is read.
|
Thus, when we get the data during navigation, the page rendering has to wait until the content is read.
|
||||||
This operation could take a long time, so the page shows old content.
|
This operation could take a long time, so the page shows old content.
|
||||||
For this reason, we provide an additional parameter for defining the content, which is shown during navigation.
|
For this reason, we provide an additional parameter for defining the content, which is shown during navigation.
|
||||||
An alternative is initializing reading by a PHP script when it is executed.
|
An alternative is initializing reading by a PHP script when it is executed.
|
||||||
|
|
|
@ -4,13 +4,13 @@ This chapter demonstrates the usage of our solution by four examples, which are
|
||||||
We describe example structures, show important blocks of code, which have to be added to projects.
|
We describe example structures, show important blocks of code, which have to be added to projects.
|
||||||
Source code and binaries can be found in the attachments with build and run instructions.
|
Source code and binaries can be found in the attachments with build and run instructions.
|
||||||
The library offers debugging logs, which can be helpful to get a better insight into the architecture mechanisms.
|
The library offers debugging logs, which can be helpful to get a better insight into the architecture mechanisms.
|
||||||
We will show how to turn the logs on in the second example.
|
Instructions on how to turn the logs on are shown in the second example.
|
||||||
|
|
||||||
\section{WebGame}
|
\section{WebGame}
|
||||||
|
|
||||||
The example aims at the third use case.
|
The example aims at the third use case.
|
||||||
It contains a game where we have a rocket, which has to destroy falling asteroids with bullets, as we can see in Figure \ref{img28:game}.
|
It contains a game where a rocket has to destroy falling asteroids with bullets, as we can see in Figure \ref{img28:game}.
|
||||||
We can also see the current \ac{FPS} in the left corner of the screenshot.
|
The current \ac{FPS} is displayed in the left corner of the screenshot.
|
||||||
The rocket can be control by buttons in the bottom, or we can use a keyboard, where arrows determine the rocket movement and the \texttt{F} key fires a bullet.
|
The rocket can be control by buttons in the bottom, or we can use a keyboard, where arrows determine the rocket movement and the \texttt{F} key fires a bullet.
|
||||||
We will discuss the rendering time in the benchmark section.
|
We will discuss the rendering time in the benchmark section.
|
||||||
\par
|
\par
|
||||||
|
@ -25,16 +25,16 @@ The example is implemented as a .NET solution consisting of three projects.
|
||||||
\texttt{BlazorApp.Client} and \texttt{BlazorApp.Server} are pregenerated projects by the Blazor App template.
|
\texttt{BlazorApp.Client} and \texttt{BlazorApp.Server} are pregenerated projects by the Blazor App template.
|
||||||
The game is implemented in the Peachpie \texttt{PHPScripts} project.
|
The game is implemented in the Peachpie \texttt{PHPScripts} project.
|
||||||
These projects reference the \texttt{Peachpie.Blazor} library as a NuGet package containing all the necessary helper classes.
|
These projects reference the \texttt{Peachpie.Blazor} library as a NuGet package containing all the necessary helper classes.
|
||||||
We describe steps, which were necessary for making the game working.
|
The following paragraph consists of steps, which were necessary for making the game working.
|
||||||
\par
|
\par
|
||||||
We can find the game implementation in three PHP scripts and a CSS file defining game styles.
|
The game implementation is divided into three PHP scripts and a CSS file defining game styles.
|
||||||
The \textit{settings.php} script comprises default values of delay between game refreshing, an asteroids frequency, and additional settings.
|
The \textit{settings.php} script comprises default values of delay between game refreshing, an asteroids frequency, and additional settings.
|
||||||
The \textit{asteroids.php} script defines game entities like the rocket or an asteroid.
|
The \textit{asteroids.php} script defines game entities like the rocket or an asteroid.
|
||||||
These entities utilize the \texttt{Peachpie.Blazor} library, which provides helper classes representing HTML elements.
|
These entities utilize the \texttt{Peachpie.Blazor} library, which provides helper classes representing HTML elements.
|
||||||
At the bottom of the script is the \texttt{Application} class connecting all parts together.
|
At the bottom of the script is the \texttt{Application} class connecting all parts together.
|
||||||
The class uses HTML element events for interacting with a user due to the \texttt{PhpTreeBuilder} class providing an API targeting PHP usage.
|
The class uses HTML element events for interacting with a user due to the \texttt{PhpTreeBuilder} class providing an API targeting PHP usage.
|
||||||
The last script is \textit{main.php}, which contains the \texttt{AsteroidsComponent} class.
|
The last script is \textit{main.php}, which contains the \texttt{AsteroidsComponent} class.
|
||||||
We can navigate this class by \texttt{/Asteroids} path.
|
A user can navigate this class by \texttt{/Asteroids} path.
|
||||||
It initializes the game and uses \texttt{Timer} provided by \texttt{Peachpie.Blazor}, which enables to fire tick events updating the game and the screen.
|
It initializes the game and uses \texttt{Timer} provided by \texttt{Peachpie.Blazor}, which enables to fire tick events updating the game and the screen.
|
||||||
Because the \texttt{Application} class inherits the helper class \texttt{Tag}, \texttt{AsteroidsComponent} uses the \texttt{BlazorWritable} interface to format and render the game into HTML instead of formating and rendering the game by exposing the \texttt{Application} structure.
|
Because the \texttt{Application} class inherits the helper class \texttt{Tag}, \texttt{AsteroidsComponent} uses the \texttt{BlazorWritable} interface to format and render the game into HTML instead of formating and rendering the game by exposing the \texttt{Application} structure.
|
||||||
\par
|
\par
|
||||||
|
@ -77,7 +77,7 @@ The website contains images, which are downloaded from the server when they are
|
||||||
\par
|
\par
|
||||||
The whole application is implemented as .NET solution consisting of three projects.
|
The whole application is implemented as .NET solution consisting of three projects.
|
||||||
\texttt{BlazorApp.Client} represents the client application containing \texttt{Program.cs}, which sets \texttt{WebAssemblyBuilder} and a root component, \texttt{PhpScriptProvider}, as we can see in Figure \ref{img20:program}.
|
\texttt{BlazorApp.Client} represents the client application containing \texttt{Program.cs}, which sets \texttt{WebAssemblyBuilder} and a root component, \texttt{PhpScriptProvider}, as we can see in Figure \ref{img20:program}.
|
||||||
We can turn debug logs by setting the minimum level of logging to Debug.
|
Debug logs can be turned on by setting the minimum level of logging to Debug.
|
||||||
\texttt{Blazor.Server} has the same role as in the previous example.
|
\texttt{Blazor.Server} has the same role as in the previous example.
|
||||||
\par
|
\par
|
||||||
\begin{figure}
|
\begin{figure}
|
||||||
|
@ -121,13 +121,14 @@ We can see the \textit{force.php} script containing empty \texttt{force} class,
|
||||||
An interesting page is \textit{developers.php}, which displays information about developers working in the company.
|
An interesting page is \textit{developers.php}, which displays information about developers working in the company.
|
||||||
We can see the script in Figure \ref{img25:developer}
|
We can see the script in Figure \ref{img25:developer}
|
||||||
It uses script inclusion to add the head section.
|
It uses script inclusion to add the head section.
|
||||||
Then, we make a Javascript call by using our predefined API, which causes the alert with the message when the page loads.
|
Then, there is a Javascript call using our predefined API, which causes the alert with the message when the page loads.
|
||||||
The whole page uses HTML interleaving.
|
The whole page uses HTML interleaving.
|
||||||
We can see using \texttt{\$\_GET} superglobal in the script, where we decide to show its content based on the URL query.
|
The \texttt{\$\_GET} superglobal is used to make a decision on which content to display based on the URL query.
|
||||||
The default mode for the context is \texttt{OnNavigationChanged}.
|
The default mode for the context is \texttt{OnNavigationChanged}.
|
||||||
When we refresh the page after navigation to a developer, we can see the anchors to developers.
|
When a user refreshes the page after navigation to a developer, he or she can see the anchors to developers.
|
||||||
It is caused by creating a new context between navigation, so the variables are disposed.
|
It is caused by creating a new context between navigation, so the variables are disposed.
|
||||||
If we want to change the mode to \texttt{Persistant}, we just set the component parameter,\texttt{ContextLifetime}, to \texttt{Persistant}, which we show in the next example.
|
If we want to change the mode to \texttt{Persistant}, we just set the component parameter,\texttt{ContextLifetime}, to \texttt{Persistant}.
|
||||||
|
It is shown in the next example.
|
||||||
This page is transparently rendered by our \texttt{PhpScriptProvider}, which evaluates the whole script and adds the output as a markup text to the builder.
|
This page is transparently rendered by our \texttt{PhpScriptProvider}, which evaluates the whole script and adds the output as a markup text to the builder.
|
||||||
\par
|
\par
|
||||||
\begin{figure}
|
\begin{figure}
|
||||||
|
@ -158,9 +159,9 @@ if (isset($_GET["developer"])) {
|
||||||
|
|
||||||
\section{OneScript}
|
\section{OneScript}
|
||||||
|
|
||||||
In this example, we aim at the second use case.
|
This example aims at the second use case.
|
||||||
The website contains several pages which demonstrates an insertion of page fragments, written in PHP, to the Blazor website.
|
The website contains several pages which demonstrates an insertion of page fragments, written in PHP, to the Blazor website.
|
||||||
When we navigate the page, we can see a button, which utilizes interoperability between PHP and Javascript provided by our solution.
|
When we navigate the page, there is a button, which utilizes interoperability between PHP and Javascript provided by our solution.
|
||||||
When we click on it, the javascript code calls PHP code, which writes a message to a browser console.
|
When we click on it, the javascript code calls PHP code, which writes a message to a browser console.
|
||||||
Next examples referred as \textit{Example 1}, \textit{Example 2}, \textit{Example 3} show working with forms.
|
Next examples referred as \textit{Example 1}, \textit{Example 2}, \textit{Example 3} show working with forms.
|
||||||
The first example uses a simple form with the \texttt{GET} method.
|
The first example uses a simple form with the \texttt{GET} method.
|
||||||
|
@ -170,7 +171,7 @@ We can also try to load a file to the form in the last example.
|
||||||
After the submit, the page displays its file contect encoded into \textit{base64} encoding.
|
After the submit, the page displays its file contect encoded into \textit{base64} encoding.
|
||||||
\textit{Example 4} uses previously mentioned features to enable displaying user defined graphs.
|
\textit{Example 4} uses previously mentioned features to enable displaying user defined graphs.
|
||||||
We can upload a file containing the graph, or the application will generate it.
|
We can upload a file containing the graph, or the application will generate it.
|
||||||
Then the graph is displayed, and we can download the points defining it, as we can see in Figure \ref{img27:graph}.
|
Then the graph is displayed, and the points defining it can downloaded, as we can see in Figure \ref{img27:graph}.
|
||||||
\par
|
\par
|
||||||
\begin{figure}[b!]
|
\begin{figure}[b!]
|
||||||
\centering
|
\centering
|
||||||
|
@ -187,12 +188,12 @@ The website contains three Razor pages: \textit{Index.razor}, \textit{PhpGateway
|
||||||
The first page uses \texttt{PhpScriptProvider} to navigate \texttt{index.php}.
|
The first page uses \texttt{PhpScriptProvider} to navigate \texttt{index.php}.
|
||||||
Using the provider is straightforward.
|
Using the provider is straightforward.
|
||||||
\par
|
\par
|
||||||
We want to show the call of PHP function from Javascript in Figure \ref{img26:index}.
|
Figure \ref{img26:index} shows the call of PHP function from Javascript.
|
||||||
As we can see, it is effortless to call it.
|
As we can see, it is effortless to call it.
|
||||||
The \texttt{callPHP} function accepts the function name and object to serialize as a function parameter.
|
The \texttt{callPHP} function accepts the function name and object to serialize as a function parameter.
|
||||||
When the script is rendered, the context contains defined \texttt{CallPHP} function.
|
When the script is rendered, the context contains defined \texttt{CallPHP} function.
|
||||||
We click on the button, which invokes \texttt{Call} method on the context, which invokes the desired function.
|
We click on the button, which invokes \texttt{Call} method on the context, which invokes the desired function.
|
||||||
Then, we deserialize the parameter.
|
Then, the parameter is deserialized.
|
||||||
There is an interesting thing about using \texttt{echo}, \texttt{print}, etc. when the script is not rendered.
|
There is an interesting thing about using \texttt{echo}, \texttt{print}, etc. when the script is not rendered.
|
||||||
The context provides the second writer, which uses \texttt{Console} as the output.
|
The context provides the second writer, which uses \texttt{Console} as the output.
|
||||||
It causes printing the message into the web browser console.
|
It causes printing the message into the web browser console.
|
||||||
|
@ -248,10 +249,10 @@ Afterward, we can see a graph, which contains a score generated by the game.
|
||||||
\par
|
\par
|
||||||
The .NET solution contains three projects \texttt{BlazorApp.Client}, \texttt{BlazorApp.Server}, and \texttt{PHPScripts}.
|
The .NET solution contains three projects \texttt{BlazorApp.Client}, \texttt{BlazorApp.Server}, and \texttt{PHPScripts}.
|
||||||
\texttt{PHPScripts} consists of \textit{Game}, \textit{Graph}, \textit{Web}, and \textit{wwwroot} folders.
|
\texttt{PHPScripts} consists of \textit{Game}, \textit{Graph}, \textit{Web}, and \textit{wwwroot} folders.
|
||||||
We already know the implementation of these parts.
|
The implementation of these parts is explained in previous examples.
|
||||||
An interesting collaboration is between the game and the graph, where we save a global variable containing the graph in \texttt{AsteroidsComponent} and uses it later in \textit{main.php}, which provides the graph visualization.
|
An interesting collaboration is between the game and the graph, where a global variable containing the graph is saved in \texttt{AsteroidsComponent} and it is used later in \textit{main.php} providing the graph visualization.
|
||||||
It works due to \texttt{PhpScriptProvider}, where we navigate either \textit{main.php} or \texttt{AsteroidsComponent}.
|
It works due to \texttt{PhpScriptProvider}, where we navigate either \textit{main.php} or \texttt{AsteroidsComponent}.
|
||||||
Because the context can be persistent, we share global variables between these parts, and we can communicate through them.
|
Because the context can be persistent, global variables are shared between these parts, and they can communicate through them.
|
||||||
We choose between navigated parts by submitting a form containing one button, which navigates the game, and an anchor containing a reference to \textit{main.php}.
|
We choose between navigated parts by submitting a form containing one button, which navigates the game, and an anchor containing a reference to \textit{main.php}.
|
||||||
Because default \texttt{Router} can navigate \texttt{AsteroidsComponent}, we don't add the \texttt{PHPScripts} assembly to the router additional assemblies in order to let the provider navigate the component.
|
Because default \texttt{Router} can navigate \texttt{AsteroidsComponent}, we don't add the \texttt{PHPScripts} assembly to the router additional assemblies in order to let the provider navigate the component.
|
||||||
The navigation, maintained by the provider, shares the provider content with the game component, which is a reason for keeping the provider alive and hiding the game component before the default router.
|
The navigation, maintained by the provider, shares the provider content with the game component, which is a reason for keeping the provider alive and hiding the game component before the default router.
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
\chapter{Benchmarks}
|
\chapter{Benchmarks}
|
||||||
|
|
||||||
In this chapter, we show the difference between using \texttt{PhpTreeBuilder} properly and only the \texttt{AddMarkupContent} method.
|
This chapter shows the difference between using \texttt{PhpTreeBuilder} properly and only the \texttt{AddMarkupContent} method.
|
||||||
Then, we test the speed of three PHP library functions in the Blazor and desktop environments.
|
Then, it tests the speed of three PHP library functions in the Blazor and desktop environments.
|
||||||
These benchmarks are available as .NET solutions in the attachment.
|
These benchmarks are available as .NET solutions in the attachment.
|
||||||
We introduce the background of the benchmarks, execute them and then evaluate the results.
|
The following sections introduce the background of the benchmarks, execute them and then evaluate the results.
|
||||||
\par
|
\par
|
||||||
The tests were executed on a HP Spectre x360 Convertible laptop with Intel(R) Core(TM) i7-8550U CPU, 8GB RAM, and NVIDIA GeForce MX150.
|
The tests were executed on a HP Spectre x360 Convertible laptop with Intel(R) Core(TM) i7-8550U CPU, 8GB RAM, and NVIDIA GeForce MX150.
|
||||||
They used Google Chrome (version: 90.0.4430.93) browser and Apache server.
|
They used Google Chrome (version: 90.0.4430.93) browser and Apache server.
|
||||||
|
@ -11,11 +11,11 @@ They used Google Chrome (version: 90.0.4430.93) browser and Apache server.
|
||||||
\section{Rendering}
|
\section{Rendering}
|
||||||
|
|
||||||
This benchmark observes the refreshing speed of a page using two ways for rendering a page content.
|
This benchmark observes the refreshing speed of a page using two ways for rendering a page content.
|
||||||
We modify the \texttt{Asteroids} game, mentioned earlier, to explore FPS during rendering.
|
The \texttt{Asteroids} game, mentioned earlier, is modified to explore FPS during rendering.
|
||||||
The modified application generates asteroids, represented by \texttt{<div>} element with CSS styles, and lets them fall until they reach the bottom, as we can see in Figure \ref{img33:benchmark}.
|
The modified application generates asteroids, represented by \texttt{<div>} element with CSS styles, and lets them fall until they reach the bottom, as we can see in Figure \ref{img33:benchmark}.
|
||||||
Then, they are removed.
|
Then, they are removed.
|
||||||
We log the current FPS, count of elements generated by the application, and time from starting the measurement every second.
|
The current FPS, count of elements generated by the application, and time from starting the measurement are logged every second.
|
||||||
Then, we evaluate the results.
|
Then, there are result evaluations.
|
||||||
\par
|
\par
|
||||||
\begin{figure}[t]\centering
|
\begin{figure}[t]\centering
|
||||||
\includegraphics[scale=0.7]{./img/BenchmarkRendering}
|
\includegraphics[scale=0.7]{./img/BenchmarkRendering}
|
||||||
|
@ -27,8 +27,8 @@ The .NET solution comprises three projects: \texttt{BlazorApp.Client}, \texttt{B
|
||||||
The setting of BlazorApp is similar to the previous examples.
|
The setting of BlazorApp is similar to the previous examples.
|
||||||
\texttt{PHPScripts} contains the modified game together with additional scripts providing the interactive setting for the benchmark in a browser.
|
\texttt{PHPScripts} contains the modified game together with additional scripts providing the interactive setting for the benchmark in a browser.
|
||||||
When we start the server and navigate the website, we can set various properties of measurement like an upper bound of FPS, a frequency of asteroids, or dimensions of background.
|
When we start the server and navigate the website, we can set various properties of measurement like an upper bound of FPS, a frequency of asteroids, or dimensions of background.
|
||||||
We will explain only the \textit{Rendering} property because the rest of the properties are self-explanatory.
|
We explain only the \textit{Rendering} property because the rest of the properties are self-explanatory.
|
||||||
We have two options for the property.
|
There are two options for the property.
|
||||||
We call the first one \texttt{String} rendering because it uses \texttt{AddMarkup} method for updating the page content.
|
We call the first one \texttt{String} rendering because it uses \texttt{AddMarkup} method for updating the page content.
|
||||||
This method accumulates the generated HTML entities into a single string and adds it into \texttt{PhpTreeBuilder}.
|
This method accumulates the generated HTML entities into a single string and adds it into \texttt{PhpTreeBuilder}.
|
||||||
We call the second one \texttt{Diff} rendering because it utilizes specialized builder interface for adding HTML entities, which includes \texttt{AddAttribute} for example.
|
We call the second one \texttt{Diff} rendering because it utilizes specialized builder interface for adding HTML entities, which includes \texttt{AddAttribute} for example.
|
||||||
|
|
Двоичные данные
docs/thesis/thesis.pdf
Двоичные данные
docs/thesis/thesis.pdf
Двоичный файл не отображается.
Двоичные данные
docs/thesis/thesis.synctex.gz
Двоичные данные
docs/thesis/thesis.synctex.gz
Двоичный файл не отображается.
|
@ -194,30 +194,31 @@ The attachments contain a user manual that helps to get familiar with the librar
|
||||||
|
|
||||||
The library, examples, and benchmarks are .NET solutions, which can be opened by \ac{VS} 2019.
|
The library, examples, and benchmarks are .NET solutions, which can be opened by \ac{VS} 2019.
|
||||||
The \texttt{bin} folder consists of compiled examples with supports for various OS and architectures like Windows (x86, x64), Unix, OSX, or Linux (x86, x64, arm).
|
The \texttt{bin} folder consists of compiled examples with supports for various OS and architectures like Windows (x86, x64), Unix, OSX, or Linux (x86, x64, arm).
|
||||||
We need only a .NET 5.0 runtime, which is available from \url{https://dotnet.microsoft.com/download/dotnet/5.0}, to run binaries.
|
The .NET 5.0 runtime, which is available from \url{https://dotnet.microsoft.com/download/dotnet/5.0}, is required to run binaries.
|
||||||
After the installation, we launch the particular example by moving to the \texttt{bin/NameOfExample} directory and run the command line below:
|
After the installation, the particular example can be run by moving to the \texttt{bin/NameOfExample} directory and run the command line below:
|
||||||
\par
|
\par
|
||||||
\begin{code}[frame=none]
|
\begin{code}[frame=none]
|
||||||
dotnet BlazorApp.Server.dll
|
dotnet BlazorApp.Server.dll
|
||||||
\end{code}
|
\end{code}
|
||||||
\par
|
\par
|
||||||
Then, we can navigate \url{https://localhost:5001}, or \url{http://localhost:5000} to reach the website.
|
Then, the website can be accesed by navigation to \url{https://localhost:5001}, or \url{http://localhost:5000}.
|
||||||
\par
|
\par
|
||||||
We need .NET 5.0 SDK, which is available from the same website as the runtime, to build solutions.
|
The .NET 5.0 SDK, which is available from the same website as the runtime, is required to build solutions.
|
||||||
After the installation, we compile and pack the \texttt{Peachpie.Blazor} library by moving to the \texttt{src/Peachpie.Blazor/Peachpie.Blazor} directory and run the commands below:
|
After the installation, the \texttt{Peachpie.Blazor} library has to be compiled and packed.
|
||||||
|
This is done by moving to the \texttt{src/Peachpie.Blazor/Peachpie.Blazor} directory and run the commands below:
|
||||||
\par
|
\par
|
||||||
\begin{code}[frame=none]
|
\begin{code}[frame=none]
|
||||||
dotnet build --configuration Release
|
dotnet build --configuration Release
|
||||||
dotnet pack --configuration Release
|
dotnet pack --configuration Release
|
||||||
\end{code}
|
\end{code}
|
||||||
\par
|
\par
|
||||||
Then, we compile an example by moving to its directory containing the \texttt{BlazorApp.Server} project and run the command below using the NuGet generated by the previous step:
|
Then, an example can be compiled by moving to its directory containing the \texttt{BlazorApp.Server} project and run the command below using the NuGet generated by the previous step:
|
||||||
\par
|
\par
|
||||||
\begin{code}[frame=none]
|
\begin{code}[frame=none]
|
||||||
dotnet build --configuration Release --source PathToTheLibraryNuGet
|
dotnet build --configuration Release --source PathToTheLibraryNuGet
|
||||||
\end{code}
|
\end{code}
|
||||||
\par
|
\par
|
||||||
After the compilation, we can launch the server by the instructions mentioned at the beginning of this section.
|
After the compilation, the server can be launched by the instructions mentioned at the beginning of this section.
|
||||||
\par
|
\par
|
||||||
The template compilation can be done by running a PowerShell command \texttt{./build/build.ps1} in the template folder.
|
The template compilation can be done by running a PowerShell command \texttt{./build/build.ps1} in the template folder.
|
||||||
It results in a NuGet package, which can be added to VS template collection.
|
It results in a NuGet package, which can be added to VS template collection.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче