~~NOTOC~~
~~NOCACHE~~
{{page>css&nodate&noeditbtn&nofooter}}
0
0
0
0
0
0
php --version
If your shell says "''command not found''" then expand the instructions below to learn how to install it.
++++ Installing PHP |
** MacOS ** should already have PHP installed. If you are sure it is not there,
you can install it using [[https://www.macports.org/|MacPorts]] (or [[http://www.finkproject.org/|Fink]] or [[https://github.com/Homebrew/brew|Homebrew]]).
** Linux and WSL ** should have a package containing PHP. Run this command to install it:
sudo apt install php php-cgi
(Note that it is important to install both ''php'' and ''php-cgi'' //at the same time//.)
** Windows ** users can download a zip file containing PHP from here: https://windows.php.net/download#php-8.0
I recommend the "VS16 x64 Thread Safe" version.
(Download just the "Zip" file; you can ignore the "Debug Pack" and "SDK" downloads.)
Once downloaded...
- In Explorer, right-click on the zip file and select "Extract All..." .
- De-select "Show extracted files when complete".
- Click "Extract"
This will create a directory called something like ''php-8.0.0-Win32-vs16-x64''.
Rename that directory to something simple, like ''PHP'', and then move it to somewhere very convenient.
For example, the root of your ''C:'' drive would be OK, after which you can test it works using one of these commands:
* (from a shell): ''%%/mnt/c/PHP/php.exe --version%%''
* (from a ''Cmd'' window): ''%%C:\PHP\php.exe --version%%''
If you move the ''PHP'' directory to somewhere else, you'll have to modify the path to ''php.exe'' in your commands appropriately.
In the rest of the instructions below, you will have to replace the command ''php'' with the full path, e.g., ''C:\PHP\php.exe''.
++++
/**
=== ===
https://www.youtube.com/watch?v=J8hzJxb0rpc (4 minutes)
* the Web can be used for any activity built around organising or exchanging data
* the Web is accessible from computers, smart phones, and even cars
**/
==== Web projects ====
The following two mini-projects illustrate
(A) how to run a program in the client Web browser when displaying a page, and
(B) how to run a program in the server to generate parts of a Web page dynamically.
These techniques are the foundations of Web and cloud apps.
=== Project A: Create a small 'click counter' Web app that runs in your browser ===
We have already seen some of the necessary parts for making a small Web app:
* making an input element, e.g., a button,
* running JavaScript in response to an event. e.g., clicking the button, and
* identifying elements by name using the ''id'' property and the ''getElementById()'' JavaScript function.
To make a small 'app' such as a click counter requires just a few additional things, which we will investigate soon:
* persistent state, i.e., somewhere to store the 'state' of the application, and
* a way to modify the content of an element, e.g., the text inside a paragraph (''p'').
== 1. Create a file containing just the structure of the web page ==
Let's begin very simply and create a file containing just the HTML describing the visible structure of the application.
(You can call the file anything you like, including "''index.html''".)
The structure will have the following parts:
* a heading (so we know what the application does),
* a paragraph displaying the current value of the counter, which should initially be ''0'', and
* a paragraph containing a clickable button that increases the counter.
== 2. Modify the content of the first paragraph when the button is pressed ==
The text content of a paragraph is stored in the ''innerHTML'' property of the ''p'' element.
Assigning a new value to the ''innerHTML'' property of a paragraph will dynamically change what is displayed inside that paragraph.
For example, this will remove the old content of a ''p'' whose ''id'' is ''my-paragraph'' and replace it with a 'Welcome' message:
Click counter
document.getElementById('my-paragraph').innerHTML = 'Welcome to some new content!'
To run this code whenever a button is clicked, put the code in the ''onclick'' property of the ''button'' element.
The first time the button is clicked, the ''0'' that is initially in the paragraph will be replaced by a longer message.
Let's add the two things we need which are
an ''id'' for the paragraph (we'll call it ''display'')
and the ''onclick'' property for the button (containing the code that updates the paragraph's content).
++++ Click here to see the updated Web app code |
++++
== 3. Increment the counter when the button is clicked ==
The ''innerHTML'' property of an element can also be read, so we can also store information there.
Let's store the value of the counter in the ''innerHTML'' property of the ''display'' paragraph.
One of the interesting things about JavaScript is that values can be used very freely.
If a string 'looks like' a number then you can treat it as a number (and perform arithmetic on it).
This means we can use the string stored in the ''innerHTML'' of the ''display'' paragraph to remember the numeric value of the counter
//and// to represent the string that should be displayed in the paragraph.
The ''+='' operator will increment its left-hand side by its right-hand side.
For example, ''x += 42'' will increment ''x'' by ''42''.
Instead of assigning a new string to the ''display'', we'll use the ''+='' operator to add ''1'' to it.
Click counter
++++ Click here to see the updated Web site code |
++++
Click counter
x + 1
will be ''%%"411"%%'', whereas
+x + 1
will be ''42'', which is exactly the effect we want when incrementing our counter.
++++ Click here to see the updated Web app code |
++++
Click counter
The first line of this script creates the global variable ''display'' and assigns to it the element whose ''id'' is ''display''.
(In other words, the variable will remember the ''p'' paragraph element that is holding and displaying the current counter value.)
The last four lines of this script declare a function called ''count'' with one parameter ''amount''.
When the function ''count'' is called with a numeric argument it first
converts ''display.innerHTML'' to an integer,
adds ''amount'' to that integer,
and then stores the result back in ''display.innerHTML''.
Storing the results back into the ''display.innerHTML'' has the side effect of causing the
browser to redraw the changed parts of the screen, thereby showing the updated counter.
The final Web app looks like this:
== Exercises and challenges ==
**1. ** Does it matter where you put the ''script'' element? What happens if you move it to the start of the ''body''?
**2. ** Add a second button that //decrements// the counter.
**3. ** Replace the buttons with a row of four buttons labelled ''-10'', ''-1'', ''+1'', and ''+10''. Make the buttons add the appropriate amount to the counter. Add another row containing just one button labelled ''reset'' that resets the counter to ''0'' when it is clicked.
**4. ** Explore some more pieces of JavaScript. Maybe start with the functions [[https://www.w3schools.com/jsref/met_win_setinterval.asp|''setInterval'']] and [[https://www.w3schools.com/jsref/met_win_clearinterval.asp|''clearInterval'']] which can be used to call a function regularly, for example, once every second. Use these functions to implement a stop watch with three buttons: "start", "stop", and "clear".
=== Project B: Create a simple 'text chat' Cloud app that executes on both server and client ===
Click counter
mkdir WebChat
cd WebChat
php -S localhost:8000
(If you want your friends to be able to connect to your server from their remote computers, run "''php -S 0.0.0.0:8000''" instead.)
== 1. Create a file containing just the structure of the web page ==
What is the simplest text chat app that you can imagine?
Obviously, at the very least, the client would need:
* an input field for you to enter a text message to send to the chat,
* a button to press to send the message, and
* a display area for the previously sent messages to be displayed.
echo gethostname()
Adding that code into the content of the ''title'' element, between '''' tags,
inserts the server name into the page title every time the client fetches the page.
PHP Chat @
== 3. Make the "send" button upload the text input area to the server ==
A ''form'' element collects input from one or more of its child ''input'' elements and then sends
the data entered into those inputs back to the server when the form is 'submitted'.
When the data is sent back, two things happen:
the data is included with the HTTP request, and the server responds with a new Web page
that will replace the original one in the browser.
This allows the server to change the content of the page every time the user submits data.
To send the form data back to the server, and also to see that data and confirm the upload worked, we have to do three things:
- tell the ''form'' how to reload the page when the submit button is pressed,
- tell the ''text'' ''input'' what name it should use to identify its content (the text the user entered) when the form data is sent back to the server, and
- insert the uploaded data into the ''textarea'' content as the page is reloading, to show the upload worked.
First, add two attributes to the ''form'' to make it reload the page when its data is submitted.
The ''method'' attribute says how to send the form data back to the server.
''GET'' and ''POST'' are the usual ways, and we'll use ''POST''.
The ''action'' attribute says what URL should be used to reload a 'result' Web page.
We will use the original chat app URL.
All variable names in PHP begin with a dollar sign "''$''".
The PHP variable ''$_PHP_SELF'' contains the URL of the app page.
The ''name'' attribute has been added to the ''text'' ''input'' element.
Setting that attribute to ''send'' allows the server to retrieve the content of the ''text'' ''input'' element using the
name ''send'' when the form data is uploaded to the server.
(I used ''send'' but you can use any name you like, as long as it is consistent between the ''input'' element and the PHP code that retrieves the data.)
If you reload the page you should now find that clicking the ''send'' button,
or pressing ''Enter'' in the text input field, will cause the page to reload.
== 4. Echo the uploaded data in the text area ==
The input text is currently being thrown away by the server.
Let's instead insert that text into the text area, so that we can see the data is being uploaded properly.
To do this we will insert some PHP code into the ''textarea'' content.
This code has to
- retrieve the data from the ''text'' ''input'' that was uploaded along with the page request (under the name ''send''), and
- if the uploaded data is not empty, ''echo'' it to provide new content for the ''textarea''.
When the page is reloaded the PHP variable ''$_REQUEST'' contains all the information about the request sent by the client,
including any data that was uploaded from ''form''s on the page.
''$_REQUEST'' behaves like an array, indexed by the name of the data you want.
The data sent from the ''input'' ''text'' is included in the ''$_REQUEST'' array using the name ''send''.
(We told the ''form'' element to call that data ''send'', using the ''name'' attribute of the text input.)
The server can therefore access that data as ''%%$_REQUEST["send"]%%''.
Inside the ''textarea'' we will add some PHP code to retrieves the ''%%$_REQUEST["send"]%%'' data,
store it in the variable ''$send'', and then (if it is not empty) ''echo'' it (to make it become the content of the ''textarea'' element).
We now have a working Web chat app! Your complete app should look like this:
PHP Chat @
== Excercises and challenges ==
**1. ** Automatically set the focus to the text input area when the page (re)loads.
Currently it is necessary to click in the text input area to begin typing into it.
It would be a better user experience if the text input area were automatically focused when the page (re)loads.
Let's set the focus to the correct element when the page has finished loading.
Similarly to the ''onclick'' attribute for ''button'' elements,
you can use the ''onload'' attribute of the ''body'' element to run some JavaScript
when the page has finished loading completely.
To do this:
* give the ''text'' ''input'' element an identifier (e.g, "''text''"), and then
* set the ''onload'' property of the ''body'' element to JavaScript that sets focus to the element with the identifier ''text''.
The code you need will look something like this:
document.getElementById('text').focus()
**2. ** Scroll the ''textarea'' element to the bottom when the page is (re)loaded.
When the chat ''textarea'' has more lines of content than space to display them,
it displays the oldest lines instead of the newest ones.
To fix this, you can
* give the ''textarea'' element an identifier (e.g., ''chat''), and
* scroll the ''chat'' area to the bottom using JavaScript.
The JavaScript to scroll a ''textarea'' to the bottom (most recent lines) looks like this:
var chat = document.getElementById('chat');
chat.scrollTop = chat.scrollHeight;
date("H:i:s")
If you prepend this to the message (in the same statement that appends the newline character to it)
you will get timestamps in the chat.
**4. ** Add each participant's name to their chat messages.
Add another text input field to the form that contains your name.
Automatically include your name at the start of the message.
The easiest way to do this is to send your name (in addition to the chat message text) to the server when the form is submitted,
include that "name" value both in the message stored in the chat log file,
and then also include the same "name" data in the generated page as the ''value'' attribute of the name text input field.
This sounds a bit 'circular' but it will work to both include your name in messages and preserve your chosen name across message submissions (page reloads).
/****
**5. ** Make the text area auto-updating.
Currently the text area only updates when you send a message.
Instead use https://www.w3schools.com/html/html5_serversentevents.asp
****/
== Is this a Web app or a cloud app? ==
Calling this a 'cloud app' is maybe debatable.
However, this app does do many of the things a Cloud app would do...
* store persistent data entered by the user on the server,
* modify what the user sees based on prior input, and
* allow multiple users to collaborate simultaneously from multiple remote clients.
The server-side data is stored in a simple text file and the server code runs only on one server.
If the persistent data were instead stored a distributed database,
and if multiple servers cooperated to share the work of handling thousands of simultaneous users,
then there would be no question at all that this qualifies as a 'cloud app'.