A page's PHP reads what the request brought, keeps what has to outlive it in the session, and builds the address the visitor goes to next. The engine already turns request values into variables - $padRequestVars - and keeps the $padSessionVars names in the session; these helpers do the same by name, from PHP, whatever those settings let through.

functionwhat it does
padRequest ( $key, $default )one value of the input by name or dot path - a post over the query, the body of a JSON request - or all of it
padRequestHas ( $keys )whether every name was sent - an emptied field was
padRequestFilled ( $key )whether it was sent and is not blank
padRequestOnly ( $keys )the input with these names only
padRequestExcept ( $keys )the input without these names
padRequestMethod ()GET, POST, PUT ... - GET on the command line
padRequestIs ( $method )whether the method is this one, or one of a list
padSession ( $key, $default )one value of the session, or all of it - never starts a session
padSessionPut ( $key, $value )keeps a value in the session, which starts on demand
padSessionHas ( $keys )whether every name is in the session
padSessionPull ( $key, $default )a value of the session, taken out of it
padSessionForget ( $keys )removes names from the session
padSessionRegenerate ()a new session id, the data kept - after a login
padFlashInput ( $except )keeps this request's input for the next request only
padOld ( $key, $default )reads that input there
padUrl ( $page, $vars, $absolute )a link to a page of this application
padBack ( $fallback )redirects to the page the visitor came from - never off-site
padAbort ( $status, $message )ends the request with an error status

The input

padRequest reads a value by the name the form gave it, a dot path into an array - customer.name for a field named customer[name] - and answers the default when the request did not bring it. A posted value wins over a query value of the same name, the body of a request sent as application/json is input too, and every text is trimmed. The query key that names the page is no input.

PHP
fragments/requests_and_sessions_1.php
HTML
fragments/requests_and_sessions_1.pad
Result
<?php

// As if a form had been posted to ?orders&sort=date with these
// values.

$_SERVER ['REQUEST_METHOD'] = 'POST';
$_GET ['sort'] = 'date';
$_POST = [ 'customer' => [ 'name' => ' Ann ',
'email' => 'ann@example.com' ],
'note' => '',
'password'=> '*REDACTED*' ];

$name = padRequest ( 'customer.name' );
$sort = padRequest ( 'sort', 'number' );
$pageNo = padRequest ( 'page', 1 );
$note = padRequestHas ( 'note' ) ? 'sent' : 'not sent';
$filled = padRequestFilled ( 'note' ) ? 'filled' : 'blank';
$only = padRequestOnly ( 'customer.email, note' );
$saved = json_encode ( $only );
$method = padRequestMethod ();
$posted = padRequestIs ( 'post' ) ? 'yes' : 'no';

?>
<ul>
<li>customer.name: {$name}</li>
<li>sort: {$sort}, page: {$pageNo}</li>
<li>note: {$note}, {$filled}</li>
<li>only: {$saved}</li>
<li>method: {$method}, a post: {$posted}</li>
</ul>
  • customer.name: Ann
  • sort: date, page: 1
  • note: sent, blank
  • only: {"customer":{"email":"ann@example.com"},"note":""}
  • method: POST, a post: yes

The session

padSessionPut starts the session when there is none yet; reading never does - a visitor without a session cookie gets the default, and no session is made to find that out. Dot paths work here too:

PHP
fragments/requests_and_sessions_2.php
HTML
fragments/requests_and_sessions_2.pad
Result
<?php

padSessionPut
( 'cart.items', [ 'apple', 'pear' ] );
padSessionPut ( 'cart.coupon', 'SPRING' );

$items = implode ( ', ', padSession ( 'cart.items' ) );

// Read, and forget.

$coupon = padSessionPull ( 'cart.coupon' );
$again = padSessionHas ( 'cart.coupon' ) ? 'yes' : 'no';

// Not there: the default.

$theme = padSession ( 'theme', 'light' );

padSessionForget ( 'cart' );

?>
<ul>
<li>items: {$items}</li>
<li>coupon: {$coupon}, still there: {$again}</li>
<li>theme: {$theme}</li>
</ul>
  • items: apple, pear
  • coupon: SPRING, still there: no
  • theme: light

A name listed in $padSessionVars is a variable as well as a session value: the helpers keep the two in step, so a value put in is the one the end of the request writes back. After a login, padSessionRegenerate () moves the session to a new id, so an id someone learned before it is worth nothing.

The form after a failed post

The page a form posts to checks it; when something is wrong it keeps the input with padFlashInput () and sends the browser back to the form with padBack (). The form's page reads the input with padOld - on that one next request only, like a Flash messages message. Passwords and the CSRF token are left out unless another list is given.

Without a list, every field whose name looks like a password, a key, a token, a card's code or number or a one-time code stays out as well - new_password, user[password], api_key, card_number, otp_code. That is judged by the words of the name, and no word rule knows every name: a field it does not recognise, a stripe_key, is kept. For a form with such a field, give the list yourself - it replaces the default, so it names every field that stays out - or flash only the fields the form needs back: padFlashInput ( array_diff ( array_keys ( padRequestExcept ( [] ) ), [ 'name', 'email' ] ) ).

PHP
fragments/requests_and_sessions_3.php
HTML
fragments/requests_and_sessions_3.pad
Result
<?php

// As if a form had come back with a mistake in it: the page
// that took the post keeps the input - and would then send the
// browser back to the form with padBack ().

$_POST = [ 'email' => 'ann@example',
'name' => 'Ann',
'password'=> '*REDACTED*' ];

padFlashInput ();

// The form's page reads it on the next request - and this one
// already.

$email = padOld ( 'email' );
$name = padOld ( 'name' );
$password = padOld ( 'password', '(never kept)' );
$city = padOld ( 'city', 'Amsterdam' );

?>
<ul>
<li>email: {$email}</li>
<li>name: {$name}</li>
<li>password: {$password}</li>
<li>city: {$city}</li>
</ul>
  • email: ann@example
  • name: Ann
  • password: (never kept)
  • city: Amsterdam
// signup.php - the page the form posts to
$errors = padValidate ( [ 'email' => 'required|email' ] );

if ( $errors ) {
  padFlash ( 'Please check the form.', 'error' );
  padFlashInput ();
  padBack ( 'signup/form' );
}

// signup/form.php - the form, filled again
$email = padOld ( 'email' );        // {input 'email', value=$email}

Links

padUrl writes a link to a page of this application: the values as a query, arrays too, in the clean form /myapp/products/42 when $padCleanUrls is on (see Clean urls). Without a page it is the page the visitor asked for; a third argument TRUE makes it absolute, on $padHost, for a mail or a feed.

PHP
fragments/requests_and_sessions_4.php
HTML
fragments/requests_and_sessions_4.pad
Result
<?php

$product
= padUrl ( 'products/42' );
$orders = padUrl ( 'orders', [ 'sort' => 'date',
'page' => 2 ] );
$search = padUrl ( 'search', [ 'q' => 'red shoes',
'tags' => [ 'new', 'sale' ] ] );
$team = padUrl ( 'about#team' );

?>
<ul>
<li>{$product}</li>
<li>{$orders}</li>
<li>{$search}</li>
<li>{$team}</li>
</ul>
  • /pad/manual/?products/42
  • /pad/manual/?orders&sort=date&page=2
  • /pad/manual/?search&q=red+shoes&tags%5B0%5D=new&tags%5B1%5D=sale
  • /pad/manual/?about#team

Going back, and stopping

Both end the request, so they are shown here, not run. padBack follows the browser's Referer only when it is a page of this application on this host, and goes to the fallback page otherwise - the index when none is given. padAbort answers an error status, 400 to 599, with the message as plain text - or the status's own words - through the engine's exit, never PHP's (see Ending the request):

padBack ( 'orders' );                   // back where the visitor came from, else orders

if ( ! $order )
  padAbort ( 404 );                     // 404 Not Found

if ( padRequestIs ( 'delete' ) and ! $admin )
  padAbort ( 403, 'Only an administrator can delete an order.' );