Designing Code
An insider's view into the dark world of marketing and how to design code with the right side of your brain.
|
Refactoring
I've been looking into what paths to take to refactor my communityCMS from procedural to OOP. I'm setting up the code base to be below the web root as well as the uploads folder (having the file uploads below the web root plugs a common security hole). This comes from reading the PHP In Action book. I'm finding that, while there are some new and strange (to me) concepts, OOP is quite doable and very interesting. The more I read, the more I want to tinker and build!
I'm building a basic DB connection class that will enable you to use the same class with different Database engines (MySQL, Postgres, MSSQL). Of course, this is standard on alot of modern systems, but it's new in my system, which has mysql calls hard coded in.
Th uploads folder being moved to below the web root will mean some changes to the current upload function (thank God I thought to make it a centrally located function!), but I thought it was time to update the WYSIWYG editor. I'm moving from Innova Studio (http://www.innovastudio.com/editor.asp) to tinyMCE. The downside is that, while the editor is free, the uploaded media center isn't. Seeing as I'm a cheap bastard and I love to build apps, I'm building a media manager to plug into it.
I'm finding that code writing is alot like home remodeling- when you think it's going to take a couple of hours, count on 3 weeks!
|
old->new site mapping
Two years ago while working at Sea Grant, Dan and I were creating the new mdsg site. Sea Grant had hundreds of pages of existing content in static html. The main concern was that many in the community had bookmarked alot of the content and when we launched the new site, those bookmarks would generate 404's (a very unhelpful content dead end).
Since we were porting the exact same content into a database served by a PHP CMS, we devised a fairly elegant (by "elegant", I mean simple) solution.
At launch time, we moved the old site to a hidden URL as a reference. This was so the script that we'd create could reference the old site, parse the title, search the current db of titles and return a list of suggested pages they were looking for. When a person chose the correct page, it would map that choice to the requested url and learn what page went where. The next time a person hit that link, the error page would forward them to the mapped page.
Of course, we knew that this kind of relied on the person choosing the correct link in the first place, but it was close enough for government work (being an educational institution) and the site had a search feature to help them should they be lead astray.
Click to see Code
Tell Apache to go to a custom errorpage.php page which has the following code:
--errorpage.php--
include_once("includes/config.php");
//see if the site is setup for transistiong from an old version of the site //$_SESSION[old_site_url] is set in the config file- this is were the old copy of the site can be accessed //$_SESSION[enable_old_site_matching] is a boolean var I've set up to see if we're running this site mapping script
if($_SESSION[enable_old_site_matching]==1 && $_SESSION[old_site_url]) { $oldsitepath = str_replace("http://".$_SERVER['HTTP_HOST'],$_SESSION[old_site_url],$_SERVER['SCRIPT_URI']); //see if this page has been mapped already $query = "SELECT * FROM site_old_new_mapping WHERE old_link = '$oldsitepath' "; $result = mysql_query($query,$_GET[dbh]) OR die(mysql_error()); $row=mysql_fetch_assoc($result); if($row[sm_id]) { if($row[page_id]) { //we found an entry, now send them to the previously mapped page header("HTTP/1.1 301 Moved Permanently"); header("Location: /goto.php?page_id=$row[page_id]"); } } else //if this page hasn't been mapped yet, add it! { $INquery = "INSERT INTO site_old_new_mapping(old_link) VALUES('$oldsitepath')"; mysql_query($INquery,$_GET[dbh]) OR die(mysql_error()); //save this ID for the goto.php, where we will map this person's selection $sitemap_id = mysql_insert_id($_GET[dbh]); } //read the old page, from the old site, into an array $phile = @file($oldsitepath); if(is_array($phile)) { $page = implode('',$phile); $title = pagesTextBetween(":", "",pagesTextBetween("title>", "
//function pagesTextBetween(); located in an included file of your choice
function pagesTextBetween($from,$to,$content,$firstoccur=1,$allownomatch=1,$debug=0) { $content = str_replace("r","",stripslashes($content)); $contentcheck = $content; $from = str_replace("r","",$from); $to = str_replace("r","",$to); $from = strtolower($from); $to = strtolower($to); $L1 = strlen($from); $contentcheck = strtolower($contentcheck); if($L1>0) { if($firstoccur==1) $pos1 = strpos($contentcheck,$from); else $pos1 = strrpos($contentcheck,$from); } else { $pos1=0; } if(isset($pos1)) { if($to == '') return substr($content,$pos1+$L1); if($firstoccur) $pos2 = strpos(substr($contentcheck,$pos1+$L1),$to); else $pos2 = strrpos(substr($contentcheck,$pos1+$L1),$to); if(isset($pos2)) return substr($content,$pos1+$L1,$pos2); } else { if($allownomatch==1) return $content; } }
} else $nosuchfile = 1; if($title) { //perform search $searchwords = str_replace(""",""",$title); $query = "SELECT page_title,page_url,page_id FROM page WHERE (MATCH(page_title) AGAINST('$title')) GROUP BY page_id"; $result = mysql_query($query) OR die(mysql_error()); $num = mysql_num_rows($result);
if($num < 1) { $note = "
There are no items that fit your search. Try using different search words."; } else { $cnote = 1; $row[page_title] = stripslashes($row[page_title]); $row[page_summary] = stripslashes($row[page_summary]); while($row=mysql_fetch_array($result)) { $possibilities[] = "
$row[page_title] ($row[page_url])
"; } } } }
?>
--body of page--
I'm sorry, the page you're looking for ( echo $_SERVER['SCRIPT_URI'] ?>) no longer exists in that location. if(is_array($possibilities)) { ?>
Here are some possible matches:
echo implode('',$possibilities); ?>
} elseif($nosuchfile) { ?>
The page also doesn't seem to appear to be in our old site. Check that you have typed in the correct address. } ?>
Here is the goto.php page that inserts the selected page into the site mapping table:
--goto.php page--
//goto.php //takes a page_id, looks up the url path and sends them on their way include_once("includes/config.php"); if($_GET[page_id] || $_GET[page]) { $page_id = $_GET[page_id]; if($_GET[anchor]) $extra = "#$_GET[anchor]"; if($_GET[queri]) $queri = "?" . base64_decode(urldecode($_GET[queri])); //get page location if($_GET[page_id]) $query = "SELECT page_url, external_url FROM page WHERE page_id = '$page_id' "; elseif($_GET[page]) $query = "SELECT page_url, external_url FROM page WHERE page_url LIKE '%$_GET[page]%' "; $result = mysql_query($query,$_GET[dbh]) OR die(mysql_error()); $row=mysql_fetch_assoc($result); if(is_array($row)) { if($_SESSION[user_level]<2) $url = "$_GET[url]/$row[page_url]/index.php"; else $url = "$_GET[url]/$row[page_url]/";
//check if this is sitemapping link. If so, insert the selection if($_GET[updatemapping]) { //update URL in site_old_new_mapping table $Uq = "UPDATE site_old_new_mapping SET page_id = $_GET[updatemapping] "; mysql_query($Uq,$_GET[dbh]); }
if($row[external_url]>'') header("Location: $row[external_url]".$queri.$extra); else header("Location: $url".$queri.$extra); } else header("Location: /index.php?page_id=$page_id".$queri.$extra); } ?>
Here is the DB table for learning the site page mapping:
--MySQL table `site_old_new_mapping`--
CREATE TABLE `site_old_new_mapping` ( `sm_id` bigint(20) NOT NULL auto_increment, `old_link` varchar(200) NOT NULL default '', `page_id` bigint(20) NOT NULL default '0', `manual_link` varchar(200) NOT NULL default '', `ignored` tinyint(1) NOT NULL default '0', `pages_with_old_link` varchar(255) NOT NULL default '', PRIMARY KEY (`sm_id`), KEY `old_link` (`old_link`), KEY `page_id` (`page_id`), KEY `ignore` (`ignored`), KEY `pages_with_old_link` (`pages_with_old_link`), KEY `manual_link` (`manual_link`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='maps 404 pages to existing pages' AUTO_INCREMENT=31415 ;
This is all procedural and has no real error handling, but it illustrates a possible solution to a common site upgrade issue. This was robust enough to handle hundreds of pages to be mapped permanently.
|
GEEK GEEK GEEK!
Oh, how I envy the attendees of the PHPUK conference! All day today, there's been geek chatter on Twitter from the attendees. For those of us that wear multiple hats and duties at work, such a narrowly focused conference is out of the question. Hell, in these times it would be, even if my job was pure PHP! Most people hate going to trade shows and conferences, but for me- I love them! It's a chance to see what others in your industry are doing. A chance to meet other fellow PHP geeks, compare geek notes and carry on geeky conversations that would make a mear mortal's eyes roll back in their heads before collapsing in a paralytic state of boredom! Those same conversations are electric for coders. To discuss the myrid ways to come to a solution through simple lines of text! You will never see such a display of geeky gadgetry as at a tech conference, and not on display by the vendors- but being carried around by the attendees. iPhones, Blackberries, netbooks and the latest laptops- not to mention a few prototypes! Don't be fooled by the outer casings though- that MacBook Pro is running CentOS and that Acer netbook is running Ubuntu- Now that's cool! I hope to go to another conference soon, but til then I get to hear the lucky bastards that are actually at one now... BTW- Whoever took the "PHP Women's" elePHPant, please return it! Not cool!
|
|
|