Debugging relative links in php

First I should mention that I’ve gotten good results when using the get_cwd() function.  With it, I can tell what directory I am starting from, and from there build the appropriate relative paths.

It’s simple to use.

echo getcwd();

Run the script, and you’ll know where your starting point is.

That said, beware of the register_shutdown_function().  I noticed the get_cwd() result changed while inside of this function.  I found a link with a workaround, but the gist of it is that the working directory of the script can change.

http://stackoverflow.com/questions/10861606/write-to-file-with-register-shutdown-function

Here’s a sample you can use:

<?php

        echo "Using Dir: " . __DIR__;
        echo "\n\n";
        echo "Using Get Current Working Directory: " . getcwd();
        echo "\n\n";
        echo "Using Get Include Path: " . get_include_path();
        echo "\n\n";

        $cwd = getcwd();

        register_shutdown_function(function(){
            echo "GetCWD inside of register_shutdown_function:" . getcwd();
               exit(1);
        });

        function throw_error($message)
        {
            trigger_error($message, E_USER_ERROR);
            exit(1);
        }
?>

Arguments against exposing auto-incrementing numbers for SQL queries

This link had some good arguments against exposing auto-incrementing numbers on a web page.

http://stackoverflow.com/questions/8078912/is-mysql-auto-increment-safe-to-use-as-userid

But generally, web developers feel uncomfortable exposing IDs that allow guessing other IDs by just incrementing or decrementing a number. Many resort to random, multi-digit IDs instead.

On a more obscure note, numeric IDs may also allow competitors to estimate your growth by keeping track of how the incremental value increases.

Find the Bug!

Here’s the query to troubleshoot:

UPDATE `Items` SET ( `Date_Acquired`=STR_TO_DATE('1/22/2012', '%c/%e/%Y') ) WHERE ( `Serial`=33 );

When you run the above query, you’ll get a funny message:

 #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '( `Date_Acquired`=STR_TO_DATE('1/22/2012', '%c/%e/%Y') ) WHERE ( `Serial`=33 )' at line 1

So where’s the syntax error?

It turns out that the parenthesis within the SET statement is a syntax error.  I’m currently not sure why the parenthesis cause problems, but you need to take them out in order to run the above query.

So, the working query would be:

UPDATE `Items` SET `Date_Acquired`=STR_TO_DATE('1/22/2012', '%c/%e/%Y') WHERE ( `Serial`=33 );

Starting and Ending Transactions

Following the spirit of atomic operations, I found a link on starting and ending a transaction.

http://stackoverflow.com/questions/12091971/how-to-start-and-end-transaction-in-mysqli

And this might be a good link for figuring out where to place the commit statement when using prepared statements.

http://stackoverflow.com/questions/10642635/how-can-i-use-prepared-statements-combined-with-transactions-with-php

Atomic operations and trying to report the right quantities.

A peeve of mine is trying to purchase something online from an e-commerce site which specifically states In Stock, and then waiting for weeks only to discover I’ve been back-ordered.  It’s doubly bad when I’m trying to buy myself a christmas present.  Yup, myself.

I haven’t tried the method listed in the below link yet, but I’m setting it aside in case I need it in the future.

http://stackoverflow.com/questions/11278494/mysql-atomic-operations-and-table-locking

 

Names, ID’s, Classes, and whatnot

When working with an HTML page, the attributes that you need depend on the plugins that you’re using.

Name Attribute:
Used when submitting a post.

ID Attribute:
Used by Jquery to find an element when doing a $(#id_name).
Used by CSS.  Prefixed by (#)

Class Attribute:
Used by CSS.  Prefixed by (.)

I didn’t cover all of the cases, since I jotted down what I remembered, but it is a good idea to create a table for this stuff.

 

Automatic Dates

It’s easier if you don’t have to use a query to insert the current time and date.  This is particularly useful for “date created” and “date modified” columns. MySQL doesn’t let you do both at the same time for one table, but there are ways around it.

http://joegornick.com/2009/12/30/mysql-created-and-modified-date-fields/

I used the second option, inserting a null into the column.  I read somewhere that it’s sort of hacky, however it appears to be legitimate behavior as seen in below link.

http://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html (Scroll to the bottom)

Personally, I prefer to insert a NOW() value instead of NULL since it’s more intuitive.

SSL theory

When preparing a site for Secure Socket Layer (SSL), it’s been said that you need to use relative paths on the website.

http://stackoverflow.com/questions/64631/what-does-a-php-developer-need-to-know-about-https-secure-socket-layer-connect

I believe that this is mainly because if you used absolute paths, you would usually throw an http:// in front of the path.  Or even if you don’t, you could be pulling the images from an external source that defaults to an unsecure service.

That being said, I was trying to keep paths relative on the php server itself.  I know why I was doing it, but if you think about it carefully…doing so does not achieve the same result as above.

 

See if you can spot the error!

$ControlColumns = array("col1", "col2", "col3", "col4", "col5");
$params = array();
$cols = array();
$colnames = array_column($ControlColumns, 1);

$bindtypes = "sssss";

foreach ($colnames as $col)
{
    $params[] = &$cols[$col];
}

$result = mysqli_stmt_bind_param($stmt, $bindtypes, $params);

Here’s the error:

Number of elements in type definition string doesn’t match number of bind variables in E:\XAMPP\xampp\htdocs\PHPTest\insert.php

And assume that the $stmt is a perfectly prepared statement with multiple parameters. In other words, it works fine.

Give up?

I guess I’m just stupid, but it took me an hour of messing around before I finally remembered that mysqli_stmt_bind_param was not designed to take an array input.

Use call_user_func_array to call that function instead.  Remember to reference the variables.

$params = array();
$params[] = $stmt;
$params[] = &$bindtype;

$result = call_user_func_array('mysqli_stmt_bind_param', $params);

 

No placeholders to bind to in MySQL prepared statements.

I suppose this is just common sense, but I really couldn’t find anything on the subject. I had a situation where I wanted to list everything in the database. In this case, there was no need for a WHERE clause in my query.

Binding an empty string using mysqli_stmt_bind_param($stmt, “”, array()); will throw an error. So I added a check to see if there are any parameters to bind. If not, don’t call this function. It seems to work and I’m still waiting for the other shoe to drop.