Web Dev: Power of the Forward Slash “/”
(Warning: this is kind of like blathering mixed with ranting, may be hard to follow, im no professional writer)
I swear to god this is one of the industries for well-kept secrets and sadly, I don’t think it’s on purpose. I think as mentors and newbies alike, we need to do out best to describe to people the ins and outs of how the web works and whats going to ultimately stop making so many young developers go bald with stress.
What im here to talk about today, is the power of the Relative, Absolute, and Semi-Absolute paths. This includes deep document roots as well.
Im going to come out and say it, this is what I do and its caused me a LOT less stress: Use Document Roots on Server Side resource management, use Semi-Absolute for everything else.
I have never failed with this, and this includes SSL Certificate Pathing (more on this in a sec if you dont know what it means)
Heres what I do in a breakdown:
I do PHP so I will be providing PHP examples, if you use ASP or Perl, translate accordingly!
Ever come across a piece of HTML that looks like this:
<img src=”<?php echo $dir; ?>/images/funnycats.jpg” />
Chances are when you check the source your going to see something loopy. $dir might be relative “../”, might be “../../”, it could be an absolute path “http://www.mysite.com/”. What either of these arent is efficient, in any way.
Truth is, a lot of developers tend to go the way to the Absolute path because then theres control over what is placed in the whole link. While just as popular, “../” type links are finally starting to see the way of the dodo. But still, meh.
I like to use the single Forward-Slash “/” for internal page usage.
Why? Ill tell you.
When you use a single / at the beginning of a HREF or SRC attribute, it drives itself all the way back to the root of the site automatically. From here, its just a matter of working your way back up to the resource, so having a well thought out file structure would help wonders. But which looks better to you:
<img src=”http://www.somesite.com/images/interface/icon.png” /> (Absolute)
or
<img src=”../../images/interface/icon.png” /> (Relative)
or
<img src=”/images/interface/icon.png” /> (Semi-Absolute)
?
The Pros and Cons of Absolute
Pros
- Complete control of the URL path
Cons
- Will have to update each link path (if not set dynamically) if the site URL ever changes
- Will have to manually manage switches between HTTP and HTTPS when dealing with SSL certificates (trust me, on partially secure sites, this is a HUGE pain in the ass) less you dont mind your userbase having to close popup windows informing them that the secure page has non-secure content!
- no PHP/ServerSide formatting required (usually)
- Does not have to deal with SSL Madness (inherits)
- If anything about the resulting folder structure changes, have to update every single link
- if using Apache or IIS RewriteRule’s, using these is a dangerous dangerous and frustrating game.
- Direct control of the URL path
- Easy to update and understand
- Bypasses SSL madness
- Apache and IIS RewriteRule friendly
- Template Friendly
- Google and Search Engine Friendly (everything’s contained, yet easy to access, read, and parse)
- If using a partial-secure site, may have to write a global switch to jump between HTTP and HTTPS
ASP and Me
Throughout my life, I panned ASP. At least, the original incarnation of it. I criticized its slowness, its convoluted nature, and its sheer inability to be used practically by every ASP developer I saw.
When I made the decision to sign under the PHP camp, I was choosing between ASP, PHP and Perl. I will always be grateful of my decision.
Now comes the time where I am trying to branch into something of a software developer. I’ve been freakishly excited at about every prospect I have to dive into Microsofts C# and while I havent had too much exposure to it, I always remained giddy. I dunno, something about the language just “clicks” with me, and was actually one of the sole basis on why I wanted to get a Windows Phone 7 device as opposed to Android (..I eventually went with Android anyway… stupid Java..)
With ASP .NET 4.0 having been released, and C# being mature enough as part of the .NET family for a while now, I decided to install MonoDevelop and the mono_mod for apache2 and give this ASP thing a try.
It was DEFINITELY different.
I’m used to creating a “project” with an IDE (which basically means a file somewhere thats a reference point to a folder that contains all my files) or just outright making a .php file in a directory on my server and loading it up. No fuss no muss.
Getting past the point where I seemingly cannot just make a .aspx file and be on my way took some mental fortitude to break and reassemble. In fact, I could NOT understand why perfectly legit sample code just wouldn’t run until I found out that I actually have to “compile” the site first.
And that felt weird to say.. “compile the site”. Its still a bit of a mind-job but once i work around these concepts, and thats all it is is a different concept of development, I plan on making a makeshift Job Listings type site as a test.
Who knows, maybe it’ll go somewhere. That’s how POF started anyways.
I dont have much else more pressing on the matter so im just gonna get going here.
Got some.. black berry .. porting to do…
oh joy…
Reminiscing
I remember, less than a year ago, when code like this would scare the crap out of me:
private function slug($text) { return preg_replace(array( "/([^a-z0-9-])/", "/-{1,10}/" ), "-", strtolower(trim($text))); }
Now there’s obviously better ways to do this type of method, but this works exactly how it needs to for the site i made it for. But I wrote this in 25 seconds, and it worked without error exactly how i wanted it to work.
I am the type of person who would seriously scare myself back in 2010.
~k
Do you SEE this?! (Android Java – MapView Idiocracy)
Witness this please:
Log.d("MAPVIEW", "1:"+(maxLat + minLat)/2+", 2:"+(maxLon + minLon)/2); //mapController.zoomToSpan((int)Math.abs(maxLat - minLat), (int)Math.abs(maxLon - minLon)); mapController.zoomToSpan((int)((maxLat - minLat) * 1E6), (int)((maxLon - minLon)*1E6)); //mapController.animateTo(new GeoPoint( (maxLat + minLat)/2, (maxLon + minLon)/2 )); //mapController.zoomToSpan((int)Math.abs(0.5 * 1E6), (int)Math.abs(4 * 1E6)); //mapController.animateTo(new GeoPoint(-49, -115)); //mapController.animateTo(new GeoPoint( (maxLat + minLat)/2, (maxLon + minLon)/2 )); //Log.d("MAPVIWE", "animating to: " + (int)Math.abs(49 * 1E6) + " / " + (int)Math.abs(-116 * 1E6)); //mapController.animateTo(new GeoPoint((int)Math.abs(49 * 1E6), (int)Math.abs(-116 * 1E6))); //Log.d("MAPVIWE", "animating to: " + (int)(((maxLat + minLat)/2)*1E6) + " / " + (int)(((maxLon + minLon)/2)*1E6)); mapController.animateTo(new GeoPoint((int)(((maxLat + minLat)/2)*1E6), (int)(((maxLon + minLon)/2)*1E6)));
this is the amalgamation of 3 days of tinkering with zoomToSpan and animateTo methods for the MapView.
What you can see here is a mess working with these methods. Were looking at trials and errors of figuring out these fussy functions in exactly what kind of data they are looking for. And of course were talking Lats and Longs here, this isn’t exactly “tolerant” data, this is micro precision numbers.
Ultimately heres the formula to work with these things, despite the documentation at google and the examples found at stackoverflow:
For zoomToSpan:
This method only takes two ints that have been converted to 1E6 microdegrees. Thats pretty much the only rule, but you will never know that looking at the documentation.
mapController.zoomToSpan((int)((maxLat - minLat) * 1E6), (int)((maxLon - minLon)*1E6));
for animateTo
This method takes a single GeoPoint that follows the exact same rules as zoomToSpan. Except instead of just throwing in a + or – operator between the two pieces of data, we need to also divide by 2 to grab the center most point.
mapController.animateTo(new GeoPoint((int)(((maxLat + minLat)/2)*1E6), (int)(((maxLon + minLon)/2)*1E6)));
Just LOOK at all of those brackets. Disgusting. I’m sure i could remove one or two tops, but as far as im concerned, this works, and im now leaving it alone :\
CodeIgniter: Proper Use of Models?
Is it wrong of me to use my CI Models as Managers instead of storage objects?
In my pursuit of knowledge, I have come across Code Igniter thanks to some ingenous folks at my job. With this incredibly powerful toolset i see infinite possibilities but thats also kind of the problem. With a framework, one is usually locked down into a specific practice and therefore anyone whos used to that framework will know where to look and what to do if anything need sto change for whatever reason.
I’ve noticed that the main reason Code Igniter is so popular is its ability to be as useful as you want it to be, and thats it. It doesnt get in your way, in fact you barely have to use ANY of the features it provides (though doing that would be kind of pointless).
I’ve come under a couple debates with some collegues and the likes about how to use the Models in the MVC workflow that CI introduces.
For those who dont know, MVC = Model/View/Controller and its a structure that separates logic from design (as much as possible anyways). Models interface with the database or other sources to manipulate raw data from those sources, Controllers interface with Models to request the information needed, and injects them into Views which is the interface sliced up into logical bits.
A “Class” in PHP is typically used as both a storage for a single object and a set of methods (aka functions) to manipulate the properties of that object, or as a set of common methods that help manipulate data you pump into it (here, think of a Class that, for example, has a large set of common Form helpers, like =Forms::Text("first_name");?> would spit out a text input box to the screen, with the name and id of “first_name”).
However I tend to look at “Models” a little differently, and I classify them less like “Classes” and more as “Managers” that have the ability to manipulate or retreive large scales of like data under a common structure.
Inside a common CodeIgniter Model for myself, lets pretend its called “NewsManager”, in here i have it setup to “Fetch” the data ofg a specific ad, and return it, yet store it in a property called “Article” within the model. So to retrieve the information inside the article, itd be something like =$news->Article->Content;?>.
I also have a pluralized version of that property for grabbing and storing entire lists of the same data as the singular property.
To cope with all this and make it all common place (so properties are not getting rewritten as something different), I typically take great care about how i create the tables of my database, and structure database queries through CodeIgniters ActiveRecord system so that the whole thing gets returned as a properly structured object, using the column names as the property names and their values directly.
The most work I ever have to do, is for such activities liek parsing the raw data and returned into the newly grabbed object. This is where CodeIgniter Helpers come into play for me, as I have a ton of parsing functions! For example: Emoticons.
I would take, at time of database fetch, run a for loop after and go through each object, I then run the “Content” (for example) data through the ParseEmoticons() function defined in my helper (and autoloaded in the config), and slam the return back into the object, replacing the old unparsed value.\
This workflow is very smooth for me, because if i ever change anything its generally pretty lightweight code to alter (because im not passing things around like a bong at a weed convention), and for anything that requires other models to do things, the $CI =& get_instance(); line becomes a life saver and fixes everything, though i try my best to keep that to a minimum.
I have since had folk look at this and wonder what crack I’ve been smoking as apparently I’m supposed to treat Models just like classes, and use Controllers to call multiple iterations of that class (using “new”) for each new item (for lists of items for example).
Both work, but each time I try to take Models like raw Classes seriously, I actually end up getting frustrated and annoyed that im implementing each iteration with a set of methods that are supposed to do specific things. This workflow makes sense to me as something ultimately very simple and easy to see whats going on…
// News Controller public function index() { $this->load->model("NewsManager"); $newsman = new NewsManager(); $data['articles'] = $newsman->FetchArticles(5); // Fetch the latest 5 articles of page 1 (as no page specified) $this->load->view("header"); $this->load->view("news/list", $data); $this->load->view("footer"); }
But i still have it setup that upon instantiation of the NewsManager, if i provide an ID or a Slug, it will fetch that article and return it right away:
public function article($reference) { $this->load->model("NewsManager"); $data['article'] = new NewsManager($reference); $this->load->view("header"); $this->load->view("news/view", $data); $this->load->view("footer"); }
as inside my news manager its setup like this
class NewsManager extends CI_model { public $Article; public $Articles; private $table = "news"; public function __construct($ref = null) { parent::__construct(); if($ref !== null) return $this->FetchArticle($ref); } public function FetchArticle($ref) { if(preg_match("/([a-zA-Z])/")) // this is a slug as theres letters in it $this->db->where("slug", $ref); else // this is trying to be an ID number $this->db->where("id", $ref); // using * for quickness here, otherwise id normally list out what i want to grab exactly. OR KEEP IT AUTOMATIC. WHO REALLY CARES. HONESTLY. $this->Article = $this->db->select("*")->from($this->table)->get()->row(); // Parsing $this->Article->Content = ParseEmoticons($this->Article->Content); return $this->Article; } public function FetchArticles($limit, $page = 1) { $this->Articles = $this->db->select("*")->from($this->table)->order_by("date_published DESC")->limit($limit)->get()->result(); // i dont feel like doing pagination for this example // Parsing foreach($this->Articles as &$article) { $article->Content = ParseEmoticons($article->Content); } return $this->Articles; } }
AND THATS IT. I love this workflow, theres literally nothing to it! I wrote this out for this article, in less than 7 minutes tops.
Thats how i develop codeigniter websites using its MVC. It works for me, its still pretty quick, and theres barely anything to it, so long as my database is logically designed (which it SHOULD BE ANYWAYS, IM LOOKING AT YOU ASSHOLWS WHO KEEP CALLING DATABASE FIELDS “lol” and “asd”!!!!)
These Eclipse shortcuts save my life
These Eclipse shortcuts save my life (my cheat sheet to efficient programming in Eclipse):
1. Ctrl+Shift+R: Open Resource
This allows you to incrementally type in a file name, it will filter out a list of possible matches, even allowed special characters like ? and * for wildcards.
You cna manipulate the selected object in the lsit with the arrow keys, pressing Enter will open the file.
2. Ctrl+Shift+T: Open Type
Same as Resource, except dives into existing files that have declated classes. So if youve got a class named “JerkyMcJerkface”, while counter intuitive, Eclispe can see it. Hit this shortcut and type “Je” and you will see the class show up in the list, select it and it will open the file and select the class.
3. Ctrl+Shift+M: Open Method
Very similar to Open Type, except will search for all methods (functions within a class) throughout your project. Selecting one will open the file and select the method name, taking you directly there.
—-
In combination after these, if i know exactly what im looking for, egenerally i do not even need to touch the mouse.
Heres some great companion shortcuts:
1. Ctrl+F: “Find in Document” Basic yes, but very useful. With incremental turned on, will search you active document in real time, you may only need to type a charater or two to get to where you need to do
2. Ctrl+L: “Go to Line” This is less obvious but nonetheless very useful. Instead of scrubbing through your file to get to the line thats causing an error, just feed it the line to go to.
3. Ctrl+H: (last resort) “Search”, in this window unless you have a specific need for the other search options, feel free to turn them all off besides “File Search”, here you can feed Eclipse a straight search query or a regular expression and it will search based on a few criteria: Workspace wide, Selected Resources Wide, or a Working Set. A working set is great if you wish to be choosey with where eclipse searches through things. For example, say you have a huge site that uses a lot of third party plugins, chances are you dont need Eclipse continuously searching through those every time (especially behemoths like WordPress directories or even CKEditor) so you can explicity tell Eclipse where it should be looking through.
—-
Combined with these, a couple notes for really fast clickty clacking:
1. Home and End keys (on a mac: Command+Left or Command+Right). These are instrumental when surfing through code. They do exactly as youd expect, being your cursor to the beginnign and end of a line. But Eclipse tends to take this a step or two further.
For example, you have a commented out piece of code
// doSomething();
and you wish to uncomment this (for example), without hitting too many keys:
Ctrl+F, type “doSo” to be brought right to the function, press “Home”, and you will see Eclipse places your cursor to just after the comment symbol, press delete twice, or use my next favorite keyboard navigation:
2. Ctrl+<- and Ctrl+->
We all know that using your arrow keys will guide your cursor through individual characters, pressing Ctrl+<- or Ctrl+-> will jump entire sets of related characters.
If you have
thisIsAFunction();
you get to the bracket from the beginning of the function name without ctrl+f (incremental) youd have to hit the arrow key 16 times or hold it down and adjust a bit afterwards. Using Ctrl modifyer, only 4 taps.
of course holding shift down while using either of these little tricks will also select the text being covered. Can get some getting used to, but youll get it eventually.
Another way to surf around code is to jump to declaring functions/methods/variables/etc.
We all know you can use Ctrl+LeftCLick to do this, but if your feeling a little allergic to the mouse, get your cursor to it somehow and press F3. Done and Done.
Got a troublesome “unexpect $eof (end of file)” error? You know its an open bracket.
Eclipse by default will hilight matching brackets as your cursor walks over them, but sometimes code can get a little long and you wont be able to see which brackets are matching up, especially in a jungle of brackets. No fear, Ctrl+Shift+P will save the day. Easily one of the fastest ways of figuring out mismatching brackets.
This isn’t more efficient but its definitely useful for code documentation.
In Eclipse, the documentation mode is very handy. You use
/**
* Description
* @param
*/
styled comments to document your methods, classes and properties. Well while your typing away or coming close to polishing off that function, it comes down to informing others of how to use it. While ANYWHERE in the method, just hit Ctrl+Shift+J. This will jump your cursor above the method and insert a, whats known as an “Element Comment”
—-
Now for some mouse stuff
Ctrl+LeftClick on any variable or function call, to be brought to the “Defintion”
Hover over a function/method or variable/property to see the associated element documentation, including acceptable properties
Hover your mouse over the opening or closing circle bracket to get a sneak peek at the code of the actual function from anywhere in your code. This only works by hovering ON the bracket.
Double click on any bracket to select everything inbetween the opening and closing bracket (this goes for circle ( square [ and curly { )
—-
When used appropriately and with eachother in clever combinations, you can get to ANYWHERE in your source code with less than 5-10 keyboard strokes.
Starting it all off
There comes a time in every man’s life, when their website undergoes an unexpected change in servers and ends up losing all of their hard earned history in databases.
So were starting fresh here now, feels kind of good actually.
Also, join our forums, its good for your health, I promise*
*this promise is not a guarantee and BlackJaguarStudios is not liable if your health condition gets any worse at the exact moment in time one registers for the forum upon reading the above message.