Mirror Remote Server With Linux FTP Commands

A client of mine called me last night around 8:00pm a little worried. I had recently setup a hosting account for her on my server, so that she would be able to switch from her current FTP-only solution to a full hosting account with a domain and everything for when she makes a webstie in the future (she only needs the FTP to share files for now). On the phone, she said:>The guy who hosts my files just called me. He got in a disagreement with the guy who manages his servers, and told me to back everything up because it might not be there tomorrow

Wow. In a split second, all your data can be gone. The forever kind of gone. The problem was – and the reason she called me – was that she had amassed so many files over the years, that it would take days to backup using her internet connection, and she only had hours to get it done. Okay, relax, I told her – I’ve got it taken care of. I can use linux shell commands to download all the files to my server from yours. It will be much faster, and the files will go directly to the new server instead of having to be re-uploaded there, saving some very time-consuming steps.

Okay, I thought. I’ll just login, make a big tarball of all the files and grab that with my server. But her file hosting account did not allow shell access, and probably didn’t have the extra space for an additional tarball of all the files anyway. So I’m stuck with the linux ftp commands – or so I thought. Turns out, the mget ftp command does not recursively download folders on most servers. So the best function to use on a remote linux server that you can’t run shell commands on is wget, because wget also supports the FTP protocol. The usage goes like this:

wget -r ftp://user:pass@domain.com

That was going fine, and then the connection was cut-off by the remote server a short way through getting all the files, probably due to some data transfer cap or something. I re-started it, and it cut off again near the same place. So this isn’t enough either, and I still don’t want to do it manually. Luckily, there is a wget flag to ignore already existing files – ‘-nc’. So the whole command to download everything recursively and not re-download files you already have is:

wget -nc -r ftp://user:pass@domain.com

Remember to back up often. You never know when you might find yourself in a sudden and unexpected data loss situation, like Ma.Gnolia did Friday, January 30th. There’s a good discussion happening on the SitePoint open thread on data loss that same some good backup ideas and methods, too.

PHP array_merge – Preserving Numeric Keys

This is just a quick post on PHP’s default behavior of re-indexing numeric keys when using PHP’s internal array_merge and array_merge_recursive functions, because it’s a problem I recently ran into, and was unable to find a quick solution to online.

Basically, the problem is that if you’re using numerically-indexed arrays with a set number that you don’t want to change (like an ID or some other unique identifier), you can’t use array_merge, because it automatically re-indexes all the numeric keys in the array to start with 0 on down in order.  There is no flag or option for the function to NOT do this, but there is another way to achieve the same result using PHP’s little-documented overridden plus operator ‘+’ for appending an array to another array.

So just replace this:

$destinationArray = array_merge($array1, $array2);

With this instead:

$destinationArray = $array1 + $array2;

Both $array1 and $array2 MUST be arrays or a fatal error will be thrown, so you may want to do some type checking or casting before that line of code. The difference is that instead of merging the arrays together, the second array will simply be appended to the first one with no changes.

Note that the plus operator for arrays ‘+’ is only one-dimensional, and is only suitable for simple arrays. If you need a multi-dimensional or complex solution, Keith Devens has a custom merge function that might work for you.

Get the Most From Your Google Analytics Dashboard

main_logoI’m a big fan of Google Analytics.  The service is free, can go on multiple websites using just one account, and displays and processes stats beautifully. But the one thing that’s always annoyed me about Google Analytics is the default dashboard setup when you create a new website profile.

The dashboard is the place for the most important things to be. it should be the single place you can view to and get an overview of all the most important things about your website regarding your visitors without having to drill deeper or go through multiple pages or sub-sections.  But the default dashboard Analytics starts you off with is all wrong, and is almost never the information I really want to see.  Let’s see how we can fix this. Continue reading

Deleting Duplicate Rows in MySQL With ONE Query

So you have a MySQL table that, somehow or another (usually on many-to-many relation tables), winds up having rows with duplicate data. Trouble is, finding and deleting these rows most of the time involves several steps that could leave your website with a few errors showing here and here if you don’t perform the updates fast enough. So is deleting multiple duplicate rows in mysql without deleting the first original row possible with just ONE query? Turns out, it is with subqueries, a MySQL feature available since the 4.1 branch. The steps are bit tricky and the query is complex, so I’ve broken it down into several steps that should make it easier to follow. Continue reading

IE6 and Multiple Button Submit Elements

I stumbled across yet another weird issue in Internet Explorer 6 today.  This time it has to do with <button type="submit"> elements and how data is sent back to the server.

<button type=”submit”> vs <input type=”submit”>

You would think both elements would behave exactly the same, because they’re both basically the same thing – the “submit” button on HTML forms.  Turns out that in Internet Explorer 6, they don’t behave the same at all.  Surprise, surprise.  The issue has to do with using multiple submit buttons on a form which can perform different actions:

[Displayed cart contents with editable quantity fields]

Update

Checkout >

Continue reading

Introducing… PHP DataMapper!

phpdatamapperPHP DataMapper is an open-source project I’ve been building and working on for a little while now.  It’s a lightweight Object-Relational Mapper based on the Data Mapper design pattern, setup using one mapper per table.  The primary goal is to make database access one of the easiest parts of building your application instead of the most tedious, and for PHP DataMapper itself to have no dependencies outside the default PHP5 installation so it can be used anywhere, in any application (no frameworks required!).

The project itself hasn’t changed too much recently, but I decided to finally formally introduce this project because I finally got some time to write some decent documentation on how to use PHP DataMapper in in your own application.  Head on over to the PHP DataMapper page to check it out, or just get right into the good stuff with the Getting Started tutorial or the
Usage – Finders example.

More updates and documentation will be coming soon.  If you’re interested in learning more about the project or contributing, please join the Google Group.

UPDATE: Links have been updated to the new home for the project – phpdatamapper.com

Early Performance Benchmarking is a Disease

Benchmarking and performance concerns should be one of the last things you address while building your application, but it seems as though, in the PHP community especially, it’s often one of the first things novice developers think about.

Any PHP developer who’s been in the community for a while has heard preposterous claims like “use single quotes (‘) for strings instead of double quotes (“), because it’s faster”. That is, faster over the 100,000 or so iterations it took the tester to generate a number sufficiently large enough to justify the claim, with a particular version of PHP, in a particular development environment in which it was tested.

Continue reading

Reading a FeedBurner Feed with PHP and cURL

Just thought I’d post a quick HOW-TO article on how to get the contents of a FeedBurner feed with PHP, because it’s something I was attempting to do last night that really annoyed me. Since I started this blog here, I decided to narrow another website of mine – czaries.net – to just distribute some PHP scripts I’ve made and take down the news that was there. I replaced it with a short paragraph explanation and a feed of the recent blog posts here. The problem was, the feed wasn’t displaying, and I couldn’t figure out why.

Continue reading

Building a Better Woot! Checker: Comparison is Key

The famous “one item per day” e-commerce store Woot! periodically holds a “woot-off”, where multiple different items are sold in quick succession, each item appearing as soon as the previous one sells out completely. The quick succession of potentially interesting items selling for steep discounts has created a proliferation of scripts and programs called “Woot checkers”, and has even lead to the creation of an official list of Woot-off checkers. All of this because of the potential of missing out on the opportunity to buy something great and get a great deal on it.

Continue reading

Fixing IE7 Z-Index Issues with jQuery

For some reason, Internet Explorer 7 does some pretty funky things, and has several known bugs with it’s rendering engine that drive web developers like me crazy.  While most of the known bugs occur in relatively obscure situations and go largely unnoticed, there are a few that really stick out and cause web developers to waste many hours trying to fix them.  The way IE7 renders z-index stacking orders is one of them.

One way to fix many of the issues with IE7 is to dynamically reverse the default z-index stacking order of the elements on your page. This will ensure the elements higher in your HTML source will also have a higher z-index order on your page, solving most of the IE stacking issues. more If you’re using jQuery (the best Javascript library there is), here’s the quick fix:

$(function() {
     var zIndexNumber = 1000;
     $('div').each(function() {
         $(this).css('zIndex', zIndexNumber);
         zIndexNumber -= 10;
     });
});

This code will start with a z-index of 1000, and decrement the z-index for each DIV element of the page by 10, giving the first DIV a z-index of 1000, the second, 990, the third 980, and so on. Notice that the selector will find all DIV elements with the code “$(‘div’)”, using the same syntax as CSS selectors. If your HTML code has different requirements, feel free to change the code or the selector to suit your needs by following jQuery’s documentation on selectors.

Update for MooTools

(04/14/2009):

A generous commenter has posted the code for fixing z-index issues with MooTools 1.2:

if (Browser.Engine.trident){
     var zIndexNumber = 1000;
     $$('div').each(function(el,i){
         el.setStyle('z-index',zIndexNumber);
         zIndexNumber -= 10;
     });
};