Odd Thing About Symlinks

I refactored a site recently and rather than having a bunch of files with identical headers and footers, I created an index.php file with conditionals to create the meta data and then include the content. To preserve the existing file structure, I just created symlinks to the index.php file. So I did something like this:


ln -s index.php oldname1.php
ln -s index.php oldname2.php

This works great and is pretty easy to implement. (Yes there are other ways to do it.)

I ran into a problem when I tried to create symlinks in some subdirectories to prevent the “You don’t have permission to access /include.php/ on this server.” error message. I turns out that you have to be in the subdirectory where you want the alias to reside. This works:


cd Guides
ln -s ../manuals/index.php index.php

This does not:

cd manuals
ln -s index.php Guides/index.php

Getting the position of elements on the screen

I have a game where I move a target and drop it on foils. I know where I put the foils, but I wanted to know where they are in relation to the window if the window is scrolled or resized. This isn’t exactly what I was needing, but it’s useful enough that I might need it in the future.


// Find the position of elements
function getOffset(element) {
    element = element.getBoundingClientRect();
  return {
    left: element.left + window.scrollX,
    right: element.right + window.scrollX,
    top: element.top + window.scrollY,
    bottom: element.bottom + window.scrollY
  }
}
function whereAreTheFoils() {
    // Find out where things are for initial setup and debugging
    var foil0 = document.getElementById('foil_0');
    var foil1 = document.getElementById('foil_1');
    var foil2 = document.getElementById('foil_2');
    var foil3 = document.getElementById('foil_3');
    console.log('Foil 0 is at LR ' + getOffset(foil0).left + ', ' + getOffset(foil0).right );
    console.log('Foil 0 is at TB ' + getOffset(foil0).top + ', ' + getOffset(foil0).bottom );

    console.log('Foil 1 is at ' + getOffset(foil1).left + ', ' + getOffset(foil1).top );
    console.log('Foil 2 is at ' + getOffset(foil2).left + ', ' + getOffset(foil2).top );
    console.log('Foil 3 is at ' + getOffset(foil3).left + ', ' + getOffset(foil3).top );
}

Redirecting missing links

I just updated a site so that it works better on phones and tablets. While updating I also cleaned up a lot of old code. In the process of cleaning up many of the old pages are no longer valid. Rather than redirecting to a generic page, I can redirect certain links to specific missing link pages. This is what I did for old manuals pages that I moved.


<?php
$oldurl = $_SERVER['REQUEST_URI'];
// Redirect requests for manuals
switch ($oldurl) {
  case '/products/mobile/manual_1.php';
  case '/products/mobile/manual_2.php';
  case '/products/mobile/manual_3.php';
  case '/products/mobile/manual_4.php';
  etc.

    header("Location: https://www.wellgolly.com/products/manuals_mobile.php",TRUE,301);
    break;
}
?>
<div  class="centered">
<h1>Error 404<br />Document not found</h1>
    <img class='pure-img-responsive centered' src='/images/sad.png' alt='Sad' />
    <p>We’re sorry, but the page you requested could not be found.<br />
    Please use the menus at the top or bottom of this page to find what you are looking for.</p>

</div>

By parsing the $oldurl, you can redirect missing files from sections of your site to a missing page that can help your visitors find what they are looking for rather than just a generic page.

Apache error.log Warning

I get a bunch of these warnings in my logs and wondered what they were.


Command line: '/usr/sbin/apache2'
Loading CGI at runtime.  You could increase shared memory between Apache processes by preloading it in your httpd.conf or handler.pl file

From a Mason mailing list it looks like it is caused when Mason is loaded each time it is needed rather than when Apache starts.
“may be a recommendation that comes from HTML::Mason::ApacheHandler2.”

I have one set of pages only site that use Mason so I’m not going to worry about it.

A note on PDO prepared statements

It wasn’t obvious to me that you need to have a different bindParameter statement each time you use a variable in the query. This won’t work.


// query for title information
$qry  = "SELECT * ";
$qry .= "FROM `website_database`.`product`, `website_database`.`product_instance` ";
$qry .= "WHERE product.id = :productID ";
$qry .= "AND product_instance.product_id = :productID";

$stmt = $dbWG->prepare($qry);
$stmt->bindParam(':productID', $productID);
$stmt->execute();

MySql doesn’t look for every instance of :productID in the query and substitute $productID. This is how you do it:


// query for title information
$qry  = "SELECT * ";
$qry .= "FROM `website_database`.`product`, `website_database`.`product_instance` ";
$qry .= "WHERE product.id = :productID1 ";
$qry .= "AND product_instance.product_id = :productID2";

$stmt = $dbWG->prepare($qry);
$stmt->bindParam(':productID1', $productID);
$stmt->bindParam(':productID2', $productID);
$stmt->execute();