It took about 2 working weeks to finish the app. I made 4 iterations of the app, and each duration mentioned on each step reflects this. Most of my time went into styling the application since I opted to use raw CSS. The hosted solution can be found here: https://expensify.fly.dev/
The project was quite simple to start since the project development steps were pretty much predetermined.
Duration: Approximately 2 hours
Since I’m a MacOS user, installing PHP was quite straightforward:
# don't skip this otherwise, you'll be stuck for hours trying to figure out what the bash errors mean. 😢
brew update
brew install
I used the PHP Server VScode extension to serve my app and PHP DEVSENSE VScode extension for PHP development tools like code completion.
Duration: Approximately 4 days
I liked that my choices were narrowed down for me. Otherwise, I would’ve been paralyzed by the tons of choices not only in the JavaScript ecosystem but also in PHP.
This is the tech stack I used for the app:
Building the PHP proxy file took longer than I’d liked:
// proxy.php
<?php
// 1.
$url = $_REQUEST["url"];
if (!$url) {
echo "You need to pass in a target URL.";
return;
}
// 2.
$response = "";
switch (getMethod()) {
case 'POST':
$response = makePostRequest(getPostData(), $url);
break;
case 'GET':
$response = makeGetRequest(getGetData($url), $url);
break;
default:
echo "This proxy only supports POST AND GET REQUESTS.";
return;
}
echo $response;
function getMethod()
{
return $_SERVER["REQUEST_METHOD"];
}
// 3.
function makePostRequest($data, $url)
{
$httpHeader = array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data)
);
return makePostCurl('POST', $data, true, $httpHeader, $url);
}
// 4.
function makeGetRequest($data, $url)
{
$ch = initCurl($url);
curl_setopt($ch, CURLOPT_URL, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
// 5.
function getPostData()
{
return http_build_query($_POST);
}
// 6.
function getGetData($url)
{
$daurl = http_build_query($_GET);
$daurl = urldecode($daurl);
return substr($daurl, 4);
}
// 7.
function initCurl($url)
{
$httpHeader = array(
'Content-Type: application/x-www-form-urlencoded'
);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36');
return $ch;
}
// 8.
function makePostCurl($type, $data, $returnTransfer, $httpHeader, $url)
{
$ch = initCurl($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, $returnTransfer);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
?>
url.