php scraps
we've written various small scripts for our personal site to add a little more dynamism and utility to the pages. here they are in case you'd like to use them too. consider them public domain.
each script contains its own style block at the bottom so they're nice and self-contained.
how to use them
first of all, you need to be able to execute server-side scripts. at present, many people on the indie web are using static site hosting, which means that they can't do that. if you'd like to get a smidge more technical with your site, leprd.space and teacake.org allow server-side scripting but otherwise provide a similar experience to sites like neocities and nekoweb.
to get the scripts on your site, copy and paste the code you want into a file and save it with the .php
extension. any page you want to use them on must also have the .php
extension; you can replace the .html
part with this and it won't affect the regular html content. include the script in the page by adding the following where you want it to display:
<?php include("/path/to/script.php"); ?>
...where "/path/to/script.php"
is replaced with the actual path to your script, obviously.
first steps: modular pages
not really a script, but a hot tip for people new to being able to run php. any .html
file can have its extension replaced with .php
. and now, if you do this:
<?php include("mypage.php"); ?>
...the contents of that file will be included in the page where you added it. this is infinitely useful for including, say, the same header and footer, the same navbar, or the same metadata in your <head>
on multiple pages. you only have to edit the one file, and the change will be reflected everywhere. maybe php is worth it for that alone.
crumbs.php
displays the file path that leads to the page you're currently on, with hyperlinks to take you to pages further up the chain. it doesn't include the root/home page because it's conventional to link back to the home page from either a title or image in the header or a navbar.
<?php
$crumbs = explode("/",$_SERVER['REQUEST_URI']);
array_shift($crumbs); //remove the leading space
if (end($crumbs) == "") {
array_pop($crumbs); //remove the trailing space that happens on index pages
}
$last = array_pop($crumbs); //then store the last item to be handled differently
$last = str_replace(array(".php", ".html"), "", $last); //remove the file extension from the page name
$bread = "";
echo "<div id='crumbs'>";
foreach($crumbs as $crumb){
$bread .= "/$crumb"; //change the characters before and after $crumb if you'd like different decorations between the page names
echo "<a href='$bread'>" . str_replace(array(".php","_"),array(""," "),$crumb) . "</a>/";
}
echo $last;
echo "</div>";
?>
<style>
#crumbs {
width: 100%;
margin-bottom: 2em;
font-size:small;
}
</style>
see an example on literally any page on our personal site that's more than a couple links deep.
splash.php
displays a random string from a list. styled after the minecraft menu splash texts by default, but you can do anything you like with them.
<?php
$splash = [
"splash 1",
"splash 2",
"you should replace these with your own things btw"
]
function print_splash() {
echo $splash[array_rand($splash)];
}
?>
<style>
#splash {
width: 51%;
float: right;
text-align: center;
margin-top: -1rem;
margin-right: -2.4rem;
font-family: "Courier";
font-size: 1.2rem;
color: #f1ba51;
font-weight: bolder;
text-shadow: -1px -1px 0 #333, 1px 1px 0 #333, -1px 1px 0 #333, 1px -1px 0 #333;
z-index: 6;
}
</style>
when you use this, you need to add the function after the include, like this:
<?php include("/path/to/splash.php"); print_splash(); ?>
see an example on our hub page.
randimg.php
displays a random image from a folder. by default, they're styled like little polaroid photos.
<?php
function rand_img($subdir) {
$basedir = "../resources/imgs/"; //change this to whatever folder your images are in
$dir = $basedir . $subdir;
$files = glob($dir . "/*");
$file = array_rand($files);
echo "<div class='photograph'><img src='$files[$file]' /></div>";
}
?>
<style>
.photograph {
transform: rotate(-0.01turn);
display:inline-block;
background-color: white;
padding:9px;
border: 1px solid #d3d3d3;
}
</style>
when you use this, you need to add the function to pass in the specific directory you want to pull images from, like this:
<?php include("/path/to/randimg.php"); rand_img("my_photos"); ?>
it's set up this way so you can use it in multiple places and/or with multiple different image collections.
see an example on mord's main page.
celestial.php
displays the current moon phase, current astrological sign, and next sabbat or esbat. this one's a doozy! it's also dependant on a third party website's API to get moon phase info, so if that breaks in the future, that part will stop working. we'll try to keep abreast of that.
<?php
$today = new DateTime(date("Y-m-d")); //prefer over 'now' to make whole-day intervals correct
$thisYear = date("Y"); //i broke free on a saturday morning etc
//the API can only get the upcoming phase, not the actual closest, so we check a week in the past
$lastPhasePeriod = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") - 7, date("Y")));
//files to store the results of the API calls so we don't have to ask every time the page is reloaded
//they're deleted every day at midnight by a cron job, amounting to 1 API call per day
$moonPhaseCache = "moonPhaseCache.json";
$quarterDaysCache = "quarterDaysCache.json";
if (!is_file($moonPhaseCache)) {
//get current closest major moon phase
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://aa.usno.navy.mil/api/moon/phases/date?date=$lastPhasePeriod&nump=1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$moonjson = curl_exec($ch);
curl_close($ch);
file_put_contents($moonPhaseCache, $moonjson);
} else {
$moonjson = file_get_contents($moonPhaseCache);
}
$moonPhaseData = json_decode($moonjson);
if (!is_file($quarterDaysCache)) {
//get the unfixed quarter days
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://aa.usno.navy.mil/api/seasons?year=$thisYear");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$quartjson = curl_exec($ch);
curl_close($ch);
file_put_contents($quarterDaysCache, $quartjson);
} else {
$quartjson = file_get_contents($quarterDaysCache);
}
$quarterDaysData = json_decode($quartjson);
function GetZodiac($today)
{
//unix timestamps are the easiest way to check a date falls within a range
$timestamp = $today->getTimestamp();
if (
$timestamp >= strtotime(date("Y-03-21")) &&
$timestamp <= strtotime(date("Y-04-19"))
) {
$zodiacInfo = "Current sign: Aries β";
} elseif (
$timestamp >= strtotime(date("Y-04-20")) &&
$timestamp <= strtotime(date("Y-04-20"))
) {
$zodiacInfo = "Current sign: Taurus β";
} elseif (
$timestamp >= strtotime(date("Y-05-21")) &&
$timestamp <= strtotime(date("Y-06-20"))
) {
$zodiacInfo = "Current sign: Gemini β";
} elseif (
$timestamp >= strtotime(date("Y-06-21")) &&
$timestamp <= strtotime(date("Y-07-22"))
) {
$zodiacInfo = "Current sign: Cancer β";
} elseif (
$timestamp >= strtotime(date("Y-07-23")) &&
$timestamp <= strtotime(date("Y-08-22"))
) {
$zodiacInfo = "Current sign: Leo β";
} elseif (
$timestamp >= strtotime(date("Y-08-23")) &&
$timestamp <= strtotime(date("Y-09-22"))
) {
$zodiacInfo = "Current sign: Virgo β";
} elseif (
$timestamp >= strtotime(date("Y-09-23")) &&
$timestamp <= strtotime(date("Y-10-22"))
) {
$zodiacInfo = "Current sign: Libra β";
} elseif (
$timestamp >= strtotime(date("Y-10-23")) &&
$timestamp <= strtotime(date("Y-11-21"))
) {
$zodiacInfo = "Current sign: Scorpio β";
} elseif (
$timestamp >= strtotime(date("Y-11-22")) &&
$timestamp <= strtotime(date("Y-12-21"))
) {
$zodiacInfo = "Current sign: Saggitarius β";
} elseif (
($timestamp >= strtotime(date("Y-12-21")) &&
$timestamp <= strtotime(date("Y-12-31"))) ||
($timestamp >= strtotime(date("Y-01-01")) &&
$timestamp <= strtotime(date("Y-01-20")))
) {
$zodiacInfo = "Current sign: Capricorn β";
} elseif (
$timestamp >= strtotime(date("Y-01-21")) &&
$timestamp <= strtotime(date("Y-02-18"))
) {
$zodiacInfo = "Current sign: Aquarius β";
} elseif (
$timestamp >= strtotime(date("Y-02-19")) &&
$timestamp <= strtotime(date("Y-0-18"))
) {
$zodiacInfo = "Current sign: Pisces β";
}
return $zodiacInfo;
}
function GetNextFestival($today, $obj)
{
//populate the array with the fixed-date esbats
$festivals = [
date("Y-02-01"), //Imbolc
date("Y-05-01"), //Beltane
date("Y-08-01"), //Lunastal
date("Y-11-01"), //Samhain
date("Y-02-01", strtotime("+1 year")), //Imbolc of the next year
];
//the quarter days are 1, 2, 4 and 5 in the array - 0 & 3 are the apsides
$ostara = date(
$obj->data[1]->year .
"-" .
$obj->data[1]->month .
"-" .
$obj->data[1]->day
);
$litha = date(
$obj->data[2]->year .
"-" .
$obj->data[2]->month .
"-" .
$obj->data[2]->day
);
$mabon = date(
$obj->data[4]->year .
"-" .
$obj->data[4]->month .
"-" .
$obj->data[4]->day
);
$yule = date(
$obj->data[5]->year .
"-" .
$obj->data[5]->month .
"-" .
$obj->data[5]->day
);
array_push($festivals, $ostara, $litha, $mabon, $yule);
$interval = null;
$smallestInterval = 365;
$nextDate = null;
foreach ($festivals as $d) {
if (strtotime($d) < $today->getTimestamp()) {
continue;
}
$compTime = new DateTime($d);
$interval = $compTime->diff($today);
if ($interval->days < $smallestInterval) {
$smallestInterval = $interval->days;
$nextDate = $d;
}
}
switch ($nextDate) {
case date("Y-02-01"):
if ($smallestInterval == 0) {
$festInfo = "Today is Imbolc! βοΈβ¨";
} else {
$festInfo = "Next sabbat: Imbolc βοΈ";
}
break;
case $ostara:
if ($smallestInterval == 0) {
$festInfo = "Today is the Spring Equinox! πΈβ¨";
} else {
$festInfo = "Next sabbat: Spring Equinox πΈ";
}
break;
case date("Y-05-01"):
if ($smallestInterval == 0) {
$festInfo = "Today is Beltane! π₯β¨";
} else {
$festInfo = "Next sabbat: Beltane π₯";
}
break;
case $litha:
if ($smallestInterval == 0) {
$festInfo = "Today is the Summer Solstice! βοΈβ¨";
} else {
$festInfo = "Next sabbat: Summer Solstice βοΈ";
}
break;
case date("Y-08-01"):
if ($smallestInterval == 0) {
$festInfo = "Today is Lunasatal! πΎβ¨";
} else {
$festInfo = "Next sabbat: Lunasatal πΎ";
}
break;
case $mabon:
if ($smallestInterval == 0) {
$festInfo = "Today is the Autumn Equinox! πβ¨";
} else {
$festInfo = "Next sabbat: Autumn Equinox π";
}
break;
case date("Y-11-01"):
if ($smallestInterval == 0) {
$festInfo = "Today is Samhain! πβ¨";
} else {
$festInfo = "Next sabbat: Samhain π";
}
break;
case $yule:
if ($smallestInterval == 0) {
$festInfo = "Today is the Winter Solstice! π―οΈβ¨";
} else {
$festInfo = "Next sabbat: Winter Solstice π―οΈ";
}
break;
case date("Y-02-01", strtotime("+1 year")):
$festInfo = "Next sabbat: Imbolc βοΈ";
break;
}
return $festInfo;
}
function GetMoonPhase($today, $obj)
{
$majorPhase = $obj->phasedata[0]->phase;
//take a day off the actual date to account for the fact that the moon approaches the appearance of a phase before its specific point
$majorPhaseDate = new DateTime(
$obj->phasedata[0]->year .
"-" .
$obj->phasedata[0]->month .
"-" .
$obj->phasedata[0]->day -
1
);
//since the api only reports full, new and quarters, we have to fill in the crescents and gibbouses ourselves by checking elapsed time
$interval = $today->diff($majorPhaseDate);
switch ($majorPhase) {
case "New Moon":
if ($interval->days == 0) {
$phaseInfo = "Today is the New Moon! πβ¨";
} elseif ($interval->days < 3) {
$phaseInfo = "Current moon phase: New Moon π";
} else {
$phaseInfo = "Current moon phase: Waxing Crescent π";
}
break;
case "First Quarter":
if ($interval->days == 0) {
$phaseInfo = "Today is the First Quarter Moon! πβ¨";
} elseif ($interval->days < 3) {
$phaseInfo = "Current moon phase: First Quarter π";
} else {
$phaseInfo = "Current moon phase: Waxing Gibbous π";
}
break;
case "Full Moon":
if ($interval->days == 0) {
$phaseInfo = "Today is the Full Moon! πβ¨";
} elseif ($interval->days < 3) {
$phaseInfo = "Current moon phase: Full Moon π";
} else {
$phaseInfo = "Current moon phase: Waning Gibbous π";
}
break;
case "Last Quarter":
if ($interval->days == 0) {
$phaseInfo = "Today is the Last Quarter Moon! πβ¨";
} elseif ($interval->days < 3) {
$phaseInfo = "Current moon phase: Last Quarter π";
} else {
$phaseInfo = "Current moon phase: Waning Crescent π";
}
break;
}
return $phaseInfo;
}
print "<div id='celestial-dash'>" .
GetZodiac($today) .
" | " .
GetNextFestival($today, $quarterDaysData) .
" | " .
GetMoonPhase($today, $moonPhaseData) .
"</div>";
?>
<style>
#celestial-dash {
margin-bottom:30px;
padding:6px;
border-bottom: 1px solid #333;
font-size: small;
text-align: center;
}
</style>
see an example on mord's main page.
getgit.php
displays the most recent git commit to your website (assuming you use git to manage it). this only works on servers where you can execute terminal commands! if you don't know what that means, it's probably not for you!
<?php
// cribbing from Ngo Minh Nam's code here: https://gist.github.com/geeknam/961488
$output = array();
// 'commit' is a file containing the results of git log -1 which is sent here by the post-receive hook
exec("cat ../commit", $output); //change this to the path of your 'commit' file
//map the array output to named variables for readability
$dtInfo = $output[2];
$commitMessage = $output[4];
//remove extra datetime info from the string that we don't want.
//there are almost certainly better ways to do this
$dtInfo = substr($dtInfo, 11);
$dtInfo = substr($dtInfo, 0, 21);
print("<div id='last_commit'><b>Last commit:</b> " . $dtInfo . " - <i>" . $commitMessage . "</i></div>");
?>
<style>
#last_commit {
margin: 2em auto 1em;
font-size: small;
}
</style>
to use this, you must add the following to /hooks/post-receive
inside your git repo (create the folder + file if they don't exist):
git log -1 > /var/www/html/commit
the path should point to wherever you want you 'commit' file to live. it will be created if it doesn't exist already.
see an example at the bottom of our hub page.