1
0
mirror of https://github.com/restoreddev/phpapprentice.git synced 2025-08-15 11:14:26 +02:00

Initial commit for public repo

This commit is contained in:
Andrew Davis
2018-09-02 10:57:36 -05:00
commit cb5d7c2386
79 changed files with 14644 additions and 0 deletions

217
assets/css/site.css Normal file
View File

@@ -0,0 +1,217 @@
@import "prismjs/themes/prism-solarizedlight.css";
$primary-color: #2AA198;
$primary-color-dark: #1D6E68;
$white: #FFF;
$drop-shadow: rgba(0, 0, 0, 0.4);
$code-background: #FDF6E3;
body {
font-family: Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
font-size: 16px;
padding-top: 1em;
padding-bottom: 1em;
}
pre, code {
font-family: Consolas, monaco, monospace;
font-size: 16px;
margin: 0 !important;
border-radius: 0 !important;
padding-top: 0.5em !important;
padding-bottom: 0.5em !important;
}
a {
color: $primary-color; /* #4078f2 */
text-decoration: none;
}
a:hover {
text-decoration: underline;
color: $primary-color-dark;
}
p {
max-width: 40em;
line-height: 1.5;
}
h1, h2, h3, h4 {
margin: 1.414em 0 0.5em;
font-weight: inherit;
line-height: 1.2;
}
h1 {
margin-top: 0;
font-size: 2.441em;
}
h2 {font-size: 1.953em;}
h3 {font-size: 1.563em;}
h4 {font-size: 1.25em;}
small, .font_small {font-size: 0.8em;}
button {
font-size: 1em;
background-color: transparent;
border: 0;
cursor: pointer;
padding: 0;
color: $primary-color;
}
button:hover {
color: $primary-color-dark;
}
button .icon {
vertical-align: middle;
}
button .icon svg {
fill: $primary-color;
}
button:hover .icon svg {
fill: $primary-color-dark;
}
.button {
background-color: $primary-color;
color: $white;
padding: 0.5em 1em;
border-radius: 1em;
}
.button:hover {
color: $white;
background-color: $primary-color-dark;
text-decoration: none;
}
.button .icon {
vertical-align: middle;
}
.button .icon svg {
fill: $white;
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
.container {
width: 90%;
margin-left: auto;
margin-right: auto;
}
@media only screen and (min-width: 33.75em) { /* 540px */
.container {
width: 80%;
}
}
.center {
margin-left: auto;
margin-right: auto;
}
.right {
float: right;
}
.doc {
padding: 0.5em 0;
}
.subtitle {
margin-top: 0;
}
.description {
max-width: 25em;
}
.grid-code {
display: grid;
grid-template-columns: 400px 1fr;
grid-column-gap: 3em;
}
.grid-code .code {
background-color: $code-background;
}
.grid-toc {
display: grid;
grid-template-columns: 2fr 1fr;
grid-column-gap: 3em;
}
.navigate-links {
margin: 1em 0;
float: right;
}
.navigate-links .icon {
vertical-align: middle;
}
.navigate-links .icon svg {
fill: $primary-color;
}
.navigate-links:hover .icon svg {
fill: $primary-color-dark;
}
.navigate-links a {
margin-left: 1em;
}
.navigate-links a:hover {
text-decoration: none;
}
.table-of-contents {
padding: 2em;
}
.table-of-contents ol {
margin: 1em 0;
padding-left: 1em;
}
.table-of-contents .section-title {
font-weight: bold;
font-size: 0.8em;
margin-top: 1em;
}
.icon {
width: 1em;
display: inline-block;
}
.home-title-wrapper {
display: grid;
grid-template-columns: 175px 1fr;
grid-template-rows: 1fr 1fr;
}
.home-title {
}
.home-subtitle {
margin-top: 0;
grid-column-start: 2;
grid-column-end: 3;
}
.home-logo {
grid-row-start: 1;
grid-row-end: 3;
}
.home-logo svg {
width: 150px;
height: 100px;
}
.menu {
margin-left: 2em;
margin-bottom: 1em;
}
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 50;
overflow: auto;
background-color: rgba(0, 0, 0, .4);
}
.modal-content {
display: block;
position: relative;
padding: 1em;
background-color: $white;
max-width: 15em;
height: 100%;
animation-name: animateleft;
animation-duration: .4s;
overflow: scroll;
box-shadow: 0 0 10px 0 $drop-shadow;
}
.closed {
display: none;
}
@keyframes animateleft {
from {left: -300px; opacity: 0}
to {left: 0; opacity: 1}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9 16.172l-6.071-6.071-1.414 1.414L10 20l.707-.707 7.778-7.778-1.414-1.414L11 16.172V0H9z"/></svg>

After

Width:  |  Height:  |  Size: 167 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M3.828 9l6.071-6.071-1.414-1.414L0 10l.707.707 7.778 7.778 1.414-1.414L3.828 11H20V9H3.828z"/></svg>

After

Width:  |  Height:  |  Size: 169 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M16.172 9l-6.071-6.071 1.414-1.414L20 10l-.707.707-7.778 7.778-1.414-1.414L16.172 11H0V9z"/></svg>

After

Width:  |  Height:  |  Size: 167 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9 3.828L2.929 9.899 1.515 8.485 10 0l.707.707 7.778 7.778-1.414 1.414L11 3.828V20H9V3.828z"/></svg>

After

Width:  |  Height:  |  Size: 169 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M6 4H5a1 1 0 1 1 0-2h11V1a1 1 0 0 0-1-1H4a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V5a1 1 0 0 0-1-1h-7v8l-2-2-2 2V4z"/></svg>

After

Width:  |  Height:  |  Size: 200 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M20 10a10 10 0 1 1-20 0 10 10 0 0 1 20 0zM10 2a8 8 0 1 0 0 16 8 8 0 0 0 0-16zm-.7 10.54L5.75 9l1.41-1.41L10 10.4l2.83-2.82L14.24 9 10 13.24l-.7-.7z"/></svg>

After

Width:  |  Height:  |  Size: 225 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 20a10 10 0 1 1 0-20 10 10 0 0 1 0 20zm8-10a8 8 0 1 0-16 0 8 8 0 0 0 16 0zM7.46 9.3L11 5.75l1.41 1.41L9.6 10l2.82 2.83L11 14.24 6.76 10l.7-.7z"/></svg>

After

Width:  |  Height:  |  Size: 223 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 0a10 10 0 1 1 0 20 10 10 0 0 1 0-20zM2 10a8 8 0 1 0 16 0 8 8 0 0 0-16 0zm10.54.7L9 14.25l-1.41-1.41L10.4 10 7.6 7.17 9 5.76 13.24 10l-.7.7z"/></svg>

After

Width:  |  Height:  |  Size: 221 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M0 10a10 10 0 1 1 20 0 10 10 0 0 1-20 0zm10 8a8 8 0 1 0 0-16 8 8 0 0 0 0 16zm.7-10.54L14.25 11l-1.41 1.41L10 9.6l-2.83 2.8L5.76 11 10 6.76l.7.7z"/></svg>

After

Width:  |  Height:  |  Size: 222 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z"/></svg>

After

Width:  |  Height:  |  Size: 314 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zM11.4 10l2.83-2.83-1.41-1.41L10 8.59 7.17 5.76 5.76 7.17 8.59 10l-2.83 2.83 1.41 1.41L10 11.41l2.83 2.83 1.41-1.41L11.41 10z"/></svg>

After

Width:  |  Height:  |  Size: 260 B

1
assets/icons/close.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z"/></svg>

After

Width:  |  Height:  |  Size: 223 B

42
assets/icons/elephant.svg Normal file
View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="404px" height="249px" viewBox="0 0 404 249" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 49.3 (51167) - http://www.bohemiancoding.com/sketch -->
<title>elephant</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M114.406262,33.0409234 C116.906654,33.0409234 198.587086,33.0409234 212.851562,33.0409234 C236.23173,33.0409234 290.966457,24.8360253 302.9375,21.828125 C322.709617,16.8600902 345.780295,41.1710486 350.739426,66.2834373 C355.388936,89.8279414 351.557615,107.060167 350.739426,117.478001 C348.492267,146.090655 340.913827,171.751032 340.913827,188.521289 C340.913827,211.397578 342.398654,228.60813 345.368307,240.152946 C338.345502,243.384315 332.63113,245 328.225191,245 C323.819252,245 319.466187,243.384315 315.165998,240.152946 C315.165998,212.852821 315.165998,195.642269 315.165998,188.521289 C315.165998,182.659437 313.041474,171.488839 308.792425,155.009494 C278.81585,157.935469 251.486979,159.893283 226.805814,160.882937 C202.124648,161.87259 177.935757,159.914776 154.23914,155.009494 C151.904793,170.439973 150.468074,183.375856 149.928982,193.817144 C149.389891,204.258431 148.391339,219.703699 146.933325,240.152946 C138.57305,243.384315 132.573934,245 128.935979,245 C125.298024,245 120.454785,243.384315 114.406262,240.152946 C121.029663,211.242836 124.190445,189.722491 123.888609,175.59191 C122.851956,127.060632 111.761968,33.0409234 114.406262,33.0409234 Z" id="path-1"></path>
<filter x="-2.7%" y="-2.0%" width="103.8%" height="104.0%" filterUnits="objectBoundingBox" id="filter-2">
<feMorphology radius="0.5" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1"></feMorphology>
<feOffset dx="-2" dy="0" in="shadowSpreadOuter1" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1"></feComposite>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
<path d="M123.708835,0.204671096 C110.38422,-0.782948431 96.8541352,1.80367512 83.1185794,7.96454174 C70.5914337,12.5905258 61.8564763,19.2306573 56.9137071,27.8849362 C45.3780726,48.0826419 45.2190029,54.1139776 45.2190029,74.89832 C45.2190029,80.5496319 45.2190029,94.2775295 45.2190029,116.082013 C44.8941776,135.814054 42.9028153,149.847335 39.2449159,158.181856 C35.7666671,166.107044 22.7617193,171.939345 0.23007254,175.678759 C0.0766908466,178.530744 -4.04672828e-16,180.785883 0,182.444176 C-4.04672828e-16,184.102469 0.742211413,186.619924 2.22663424,189.996543 C19.3683356,190.134613 33.6991251,186.137222 45.2190029,178.004371 C58.0689401,168.932519 56.2252902,163.797983 62.486142,147.454285 C66.2191971,137.709297 68.3704403,127.251873 68.9398717,116.082013 C98.4645478,120.955097 116.720869,123.391639 123.708835,123.391639 C134.190784,123.391639 148.793717,120.923091 160.10709,103.338129 C171.533853,85.5769196 172.420694,75.0592376 174.453335,67.1621734 C177.277215,56.1910529 186,34.1766174 186,21.1547558 C186,8.13289413 144.421355,1.73988173 123.708835,0.204671096 Z" id="path-3"></path>
<filter x="-1.9%" y="-1.3%" width="104.8%" height="104.7%" filterUnits="objectBoundingBox" id="filter-4">
<feMorphology radius="0.5" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1"></feMorphology>
<feOffset dx="1" dy="2" in="shadowSpreadOuter1" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feComposite in="shadowBlurOuter1" in2="SourceAlpha" operator="out" result="shadowBlurOuter1"></feComposite>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Elephant" transform="translate(-120.000000, -62.000000)">
<g id="elephant" transform="translate(122.000000, 63.000000)">
<path d="M292,154 L292,229.687017 C297.80012,232.562339 302.466787,234 306,234 C309.533213,234 314.19988,232.562339 320,229.687017 L320,154 L292,154 Z" id="Path-3" stroke="#979797" fill="#D8D8D8"></path>
<path d="M113.089613,112 C112.215697,146.301082 110.868891,171.05041 109.049195,186.247987 C107.229499,201.445563 103.879767,215.920359 99,229.672376 C104.837247,232.557459 109.533784,234 113.089613,234 C116.645442,234 121.34198,232.557459 127.179226,229.672376 L134,112 L113.089613,112 Z" id="Path-3-Copy" stroke="#979797" fill="#D8D8D8"></path>
<g id="Path">
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
<use stroke="#979797" stroke-width="1" fill="#D8D8D8" fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
<g id="Path-2">
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-3"></use>
<use stroke="#979797" stroke-width="1" fill="#D8D8D8" fill-rule="evenodd" xlink:href="#path-3"></use>
</g>
<circle id="Oval" fill="#000000" cx="77" cy="76" r="5"></circle>
<path d="M394.04451,154.695284 C387.335643,135.817928 382.463422,123.3603 379.427845,117.322398 C376.392268,111.284497 366.955141,94.8960125 351.116464,68.1569449 L353,83.4050009 C362.468082,99.4723027 368.913046,110.778102 372.334893,117.322398 C380.679064,133.280662 386.198146,152.11787 388.617876,158.078886 C390.422602,162.524839 392.314008,171.103712 394.04451,185.164806 C394.940381,192.444154 397.167522,203.5 399.948259,203.5 C402.726203,203.5 400.982103,193.180619 399.948259,185.164806 C399.25903,179.820931 397.291114,169.664424 394.04451,154.695284 Z" id="Path-4" stroke="#979797" fill="#D8D8D8"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M1 4h2v2H1V4zm4 0h14v2H5V4zM1 9h2v2H1V9zm4 0h14v2H5V9zm-4 5h2v2H1v-2zm4 0h14v2H5v-2z"/></svg>

After

Width:  |  Height:  |  Size: 162 B

1
assets/icons/menu.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>

After

Width:  |  Height:  |  Size: 121 B

63
assets/js/site.js Normal file
View File

@@ -0,0 +1,63 @@
import Prism from 'prismjs';
var onLoad = function () {
Prism.highlightAll();
var menuButton = document.querySelector('.menu-button');
// stop execution if menu button does not exist on page
if (!menuButton) {
return;
}
var modalButton = document.querySelector('.modal-button');
var modal = document.querySelector('.modal');
var modalContent = document.querySelector('.modal-content');
var clickEvent = function (e) {
var modal = document.querySelector('.modal');
if (modal.classList.contains('closed')) {
modal.classList.remove('closed')
} else {
modal.classList.add('closed')
}
};
menuButton.addEventListener('click', clickEvent);
modalButton.addEventListener('click', clickEvent);
modal.addEventListener('click', function (e) {
var target = e.target
do {
if (target == modalContent) {
return;
}
target = target.parentNode;
} while (target);
modal.classList.add('closed')
});
};
document.onkeydown = function (e) {
e = e || window.event;
var isEscape = false;
if ("key" in e) {
isEscape = (e.key == "Escape" || e.key == "Esc");
} else {
isEscape = (e.keyCode == 27);
}
if (isEscape) {
var modal = document.querySelector('.modal');
if (modal && !modal.classList.contains('closed')) {
modal.classList.add('closed');
}
}
};
if (document.readyState !== 'loading') {
onLoad();
} else {
document.addEventListener('DOMContentLoaded', onLoad);
}

View File

@@ -0,0 +1,3 @@
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><?= $title ?? 'PHP Apprentice' ?></title>
<meta name="description" content="<?= $description ?? 'A site for learning how to use PHP'?>">
<link rel="stylesheet" href="/css/site.css">
<link rel="icon" href="/favicon-32.png">
<script src="/js/site.js"></script>
</head>
<body>

View File

@@ -0,0 +1,17 @@
<div class="table-of-contents">
<h4>Table of Contents</h4>
<a href="<?= page_path('index') ?>">Preface</a>
<ol>
<li><a href="<?= page_path('basics') ?>">Basics</a></li>
<li><a href="<?= page_path('variables') ?>">Variables</a></li>
<li><a href="<?= page_path('arithmetic') ?>">Arithmetic</a></li>
<li><a href="<?= page_path('comparisons') ?>">Comparisons</a></li>
<li><a href="<?= page_path('boolean-logic') ?>">Boolean Logic</a></li>
<li><a href="<?= page_path('conditionals') ?>">Conditionals</a></li>
<li><a href="<?= page_path('loops') ?>">Loops</a></li>
<li><a href="<?= page_path('arrays') ?>">Arrays</a></li>
<li><a href="<?= page_path('functions') ?>">Functions</a></li>
<li><a href="<?= page_path('classes') ?>">Classes</a></li>
</ol>
<a href="<?= page_path('credits') ?>">Credits</a>
</div>

View File

@@ -0,0 +1,19 @@
<?php partial('header', ['title' => 'PHP Apprentice - Credits']) ?>
<div class="container center">
<div class="grid-toc">
<div>
<h1>Credits</h1>
<p>
PHP Apprentice was inspired by
<a href="https://gobyexample.com/">Go By Example</a> and by <a href="https://elixirschool.com/">Elixir School</a>. Both sites offer excellent, quality documentation in Go and Elixir and I want PHP Apprentice to provide the same
experience for the PHP programming language.
</p>
</div>
<div>
<?php partial('table_of_contents') ?>
</div>
</div>
</div>
<?php partial('footer') ?>

View File

@@ -0,0 +1,41 @@
<?php partial('header', ['title' => $title, 'description' => $description]) ?>
<div class="menu">
<button class="menu-button" title="Open Menu">
<div class="icon"><?= icon('menu') ?></div>
Menu
</button>
</div>
<div class="container center">
<h1><?= escape($title) ?></h1>
<h3 class="subtitle"><?= escape($subtitle) ?></h3>
<?= code_table($code) ?>
<div class="clearfix"></div>
<div class="navigate-links">
<?php if (!empty($previous)): ?>
<a href="<?= page_path($previous) ?>" title="Previous">
<div class="icon"><?= icon('cheveron-outline-left') ?></div>
Previous
</a>
<?php endif ?>
<?php if (!empty($next)): ?>
<a href="<?= page_path($next) ?>" title="Next">
Next
<div class="icon"><?= icon('cheveron-outline-right') ?></div>
</a>
<?php endif ?>
</div>
</div>
<div class="modal closed">
<div class="modal-content">
<button class="modal-button right" title="Close">
<div class="icon"><?= icon('close-outline') ?></div>
</button>
<?php partial('table_of_contents') ?>
</div>
</div>
<?php partial('footer') ?>

View File

@@ -0,0 +1,36 @@
<?php partial('header', ['title' => 'PHP Apprentice']) ?>
<div class="container center">
<div class="grid-toc">
<div>
<div class="home-title-wrapper">
<div class="home-logo"><?= icon('elephant') ?></div>
<h1 class="home-title">PHP Apprentice <em>(beta)</em></h1>
<h3 class="home-subtitle">A site for learning how to use PHP</h3>
</div>
<p>
The goal of PHP Apprentice is to be an easy to understand resource for learning how to write good code in the PHP programming language. There are a lot of PHP tutorials on the internet that use outdated libraries, insecure programming practices or inefficient code. I want this site to show how to write PHP code with quality.
</p>
<p>
The site currently has content for learning the basics of PHP. In the future, more pages will be added for more advanced topics like building websites, database integration and security.
</p>
<p>
PHP Apprentice is currently a work in progress (hence "beta" is included in the title). If you would like to contribute or request a certain discussion topic, checkout the <a href="https://github.com/restoreddev/php-apprentice" target="_blank">GitHub repository</a>.
</p>
<p>
To get started, you will need to install PHP 7.1, have a text editor and open your terminal.
Each example in PHP Apprentice can by typed into a PHP file and executed in the terminal.
Let's get started! 😃
</p>
<a href="<?= page_path('basics') ?>" class="button">
<div class="icon"><?= icon('book-reference') ?></div>
Open First Chapter
</a>
</div>
<div>
<?php partial('table_of_contents') ?>
</div>
</div>
</div>
<?php partial('footer') ?>