Tag: Programming

  • PHP Suggest

    Over on php.net, they announced a full implementation of a search field suggestion box:

    The function list suggestions we started to test a year ago seemed to be working better as some bugs were found and fixed, so it was time to make the result available on all php.net pages.

     

    Whenever you type something into the search field, while having the function list search option selected, you will get a list of suggested functions starting with the letters you typed in. You can browse the list with the up/down keys, and you will be able to autocomplete the function name with the spacebar.

    Couple things I find interesting about this. First, it predates Google Suggest by a year (prior art that everyone heralding Google Suggest seemed not to notice); did Google get the idea from the PHP site, or is this more common?

    The second point is a bit more trivial, but I noticed when I was trying it out by typing in “date” that there are two additional PHP date functions that appeared in the list: date_sunrise() and date_sunset(). These are new to PHP 5. They take a timestamp, latitude, and longitude and return the respective time of day for sunrise or sunset. What’s interesting is that they are remarkably similar to two functions I had written well before PHP 5 came out. (“Written” is subjective, more like “adapted,” probably from a Java function somewhere.) However, from the looks of the manual, these new built-in functions only take a Unix timestamp, which limits the results to dates between 1970 and 2038, while my functions take any combination of month, day and year. The point? I just like to toot my own horn sometimes. :)

  • PHP code rant

    This is a mini-rant on PHP that can be safely avoided by non geek types.

    This post over on PHP Everywhere caught my attention, vis-a-vis programming semantics and practice. Basically, inside a switch statement, someone placed the default block before the case blocks and was surprised when that default condition executed, and the “expected” case did not.

    Some are calling this a bug; I do not. This is the exact behavior I expect switch and default to display, and I always place any default blocks last in the statement, because that makes the most sense semantically and logically. I expect this because that’s how I learned it when learning C years ago; it’s the way the switch construct works and why it’s so fast.

    Relevant snippage from the PHP manual:

    The switch statement executes line by line (actually, statement by statement). In the beginning, no code is executed. Only when a case statement is found with a value that matches the value of the switch expression does PHP begin to execute the statements. PHP continues to execute the statements until the end of the switch block, or the first time it sees a break statement. If you don’t write a break statement at the end of a case’s statement list, PHP will go on executing the statements of the following case….

    A special case is the default case. This case matches anything that wasn’t matched by the other cases, and should be the last case statement.

    Seems pretty clear to me. I would expect PHP to immediately execute the default block as soon as it encounters it, even if this “cuts off” remaining case blocks below it. So quit complaining and write cleaner code.

    Okay, done ranting.

  • COBOL

    From Tim Bray tonight comes this amazing fact:

    There are five billion new lines of COBOL getting created every year, and there are (wait for it) 220 billion lines of COBOL in production. (Holy cow, now that I think about it, I bet I wrote ten or twenty thousand of them).

  • overLIB

    Pointer to a totally excellent JavaScript library for creating popups: overLIB. I’ve been using it the last few days to put together a dynamic drop-down menu for a Web project at work. And I’ve used it before to create popup context menus and tooltips. It’s simply one of the best JavaScript tools out there that I’ve come across—it’s clever, simple to use, and it just works, period.

  • Search Patch

    While waiting to find out if my hosting provider will change the minimum fulltext word length for MySQL, here’s what I’ve done in the meantime to deal with viable three-character search terms.

    First, I split the search string into the component words (an array). I subtract any stopwords (I’ve got a big list) and for any remaining words that are under four characters long, I add to the SQL query I’m running.

    Here’s the basic form of the query that I’m running, say searching for “porter”:

    SELECT *,
    MATCH(body) AGAINST('porter') AS relevance
    FROM content
    WHERE MATCH(body) AGAINST('porter')
    AND [additional conditions]
    ORDER BY relevance DESC
    LIMIT 10

    This uses fulltext indexing to search for “porter” with weighted relevance, and returns the appropriate content and its relevance score. Pretty straightforward, and it works really well.

    Here’s what the modified query looks like, if there’s short words present, for the search “porter php”:

    SELECT *,
    MATCH(body) AGAINST('porter') +
      (1 / INSTR(body, 'php') + 1 / 2[position of word in string])
    AS relevance
    FROM content
    WHERE ( MATCH(body) AGAINST('porter')
      OR body REGEXP '[^a-zA-Z]php[^a-zA-Z]'
      )
    AND [additional conditions]
    ORDER BY relevance DESC
    LIMIT 10

    Two new things are happening. First, in the WHERE clause, I’m using both the fulltext system to find “porter” and using a regular expression search for “php.” Why REGEXP and not LIKE? Because if I write LIKE '%cow%' for instance, I’ll not only get “cow” but also “coworker” and other wrong matches. A regular expression lets me filter those scenarios out.

    That takes care of finding the words, but I also wanted to tie them into relevance, somehow. The solution I hit upon in the above SQL is relatively simple, and does the trick well enough for my tastes. Basically, the sooner the word appears in the content, the higher its relevance, which is reflected in the inverse of the number of characters “deep” in the content it appears. And I wanted to fudge the number a bit more by weighting the position of the keyword in the search string; the sooner the keyword appears, the higher the relative score it gets.

    It’s not perfect, and I definitely wouldn’t recommend using this method on a sufficiently large dataset, but for my short-term needs it works just fine. The only thing really missing in the relevance factoring is how many times the keyword appeared in the content, but I can live without that for now.

  • PHP Development Hint

    Here’s a general hint for PHP development: A quick and easy way to check for syntax or compile errors without uploading the PHP script to the Web server and testing online through a browser is via the command line. It’s obvious, and I don’t know why I didn’t think of this sooner, but I’ve been doing more and more of it lately.

    I develop primarily under Windows (with PHP installed) and upload to a Unix-variant server, and this what I’ve been doing to run a PHP script on the command line on my Windows system:

    php-cli -l filename.php

    You could omit the -l option (it’s a syntax check option only) to parse and run the code, if you like. Either way, it’s an easy way to check your code without uploading it and potentially breaking your site.

  • Computer Languages History Timeline

    From the Computer Languages History site comes an impressive computer languages timeline chart. It’s as much a language family tree as it is a timeline. Very nice, though a little hard to read.

  • Rasmus is the Man

    Rasmus Lerdorf, that is, the creator and godfather of PHP. He’s got an article on the Oracle Technology Network titled “Do You PHP?” that’s definitely worth a read. Here’s a sample:

    What it all boils down to is that PHP was never meant to win any beauty contests. It wasn’t designed to introduce any new revolutionary programming paradigms. It was designed to solve a single problem: the Web problem. That problem can get quite ugly, and sometimes you need an ugly tool to solve your ugly problem. Although a pretty tool may, in fact, be able to solve the problem as well, chances are that an ugly PHP solution can be implemented much quicker and with many fewer resources. That generally sums up PHP’s stubborn function-over-form approach throughout the years….

    Despite what the future may hold for PHP, one thing will remain constant. We will continue to fight the complexity to which so many people seem to be addicted. The most complex solution is rarely the right one. Our single-minded direct approach to solving the Web problem is what has set PHP apart from the start, and while other solutions around us seem to get bigger and more complex, we are striving to simplify and streamline PHP and its approach to solving the Web problem.

    The guy just oozes common sense. Here’s another bit about PHP that he wrote on the PHP-DEV mailing list about two years ago, one of my favorites that just sums up beautifully the philosophy of PHP:

    The golden rules of PHP are to keep the WTF(*) factor low and the POTFP(**) factor high.

    (*) What The Fuck
    (**) Piss Off The Fewest People

    No two ways about it: he’s one of my heroes.

  • Formatting changes

    I love templates. I was able to make some changes to the site formatting in mere minutes thanks to templates. Change two files, and it all propagates throughout the site. Lovely.

    I use a modified version of the Template class from the PHP Base Library for just about any PHP programming project I work on any more. I’ve looked into other, similar classes for PHP but haven’t really found anything that comes close to the PHP Base Library Template.

    I’ve never gotten into using Smarty largely because from what I know of it, it doesn’t fit my needs—it’s overkill for a templating system. (Caveat emptor. I could very well be wrong here.) Here’s a hint: not everything you use a template for needs to be/should be/can be compiled into PHP, which is what Smarty does. I can use my hacked Template class to build any kind of files, like my RSS file—not just PHP and HTML. Plus it’s very easy to use and it’s not burdened down with all the additional template scripting code (yeah, code) that Smarty allows.

    For my money, if you’re working with Smarty, you might as well just forego it entirely and code in native PHP. But that’s just me.

  • Thoughts on Content Management

    I’ve been thinking a long time about content management systems (which isn’t surprising considering developing various types of website CMSes is what I do for a living), how they pertain to weblogs and similar types of content, how to implement them in PHP and MySQL, and what type of system I would really like to have. Now, content management is a big topic, so let me clarify and narrow down what I’m talking about before I go on.

    Some definitions
    A piece of content can be anything—a blog entry, a fragment of text, a photo, an MP3 file, a recipe for carrot cake, a Palm Reader ebook, a scrap of a note written on a yellow sticky pad. A lot of what defines and contextualizes the content is the metadata that goes along with it—the date it was created, the size of the file, the author, the image format, where it was created, etc. Now, granted, different types of content can have vastly different types of metadata; for instance, a JPEG image taken with a digital camera will have attributes attached to it describing its resolution, compression quality, file size, camera specs, and date and time it was taken, while a piece of GIS data will have, say, latitude and longitude attributes, elevation, and place name information (which could be any or all of street name, city name, county name, etc.).

    Some requirements
    After using and extending my own homebrewed blog software for over a year and half, examining other systems like Movable Type, and getting lots of ideas from other blogs and smart folks online, I’ve decided that what I’m thinking about is what I call a Personal Publishing System (PPS?), which could be considered a subset of a CMS. The PPS should have some features of a CMS, but certainly doesn’t need all of them; allowing multiple users to manage content is okay, for instance, but a comprehensive workflow system is unnecessary—just being able to flag a content item as a draft or final version, and perhaps an approval tag, is all that’s needed. Here’s a list of some requirements I’d like to see in my PPS:

    • Web based.
    • Any type of content and its metadata can be handled.
    • Each piece of content has a globally unique identifier (“guid”) of some kind.
    • Each piece of content can be access/retrieved via a URL (probably incorporating the guid).
    • Content can be published in any format: HTML (browsers), RSS (syndication/aggregators), PDF, etc. etc.
    • Content can be categorized based on a hierarchical tree of categories. In fact, content can be assigned to multiple categories.

    My general philosophy here is that I want to challenge my own notions about what constitutes a blog and see how far I can take it. Hubris, probably.

    Database theory
    A well-formed and normalized database would rightly split different types of content into their own properly modeled tables, which is the sane, efficient and right thing to do. I love data normalization, and I take a particular joy in modeling a data structure to a relational database and normalizing the hell out of its elements.

    In fact, as any Web application developer using a relational database will tell you, this is critical; the database is one of the biggest bottlenecks in the entire system, and it can be Web suicide for even a moderately-loaded site to have unoptimized tables behind your code.

    On the other hand, there is a drawback in trying to run a content management system this way: for every new type of content you want the system to handle, you have to create a new table (or several, depending on how normalized you want to get) and then add code into your system for handling the new table(s). (Okay, astute PHP programmers will realize you could create a master table that contains information and metadata about the new tables, and have PHP code that automagically handles the new tables based on this master table info—so you would only have to create the new tables and the system auto-populates the master table info and knows how to deal with that content in a general way. You wouldn’t have to recode for new additions. I’ve done this. It works reasonably well, considering.) Pretty soon, you’ve got so many tables handling every different case you can think of, that database performance degrades regardless of how optimized each table is. And managing potentially hundreds of tables becomes a nightmare in logistics.

    Left field
    So of course, in imagining a theoretical structure for my PPS, I went slightly insane and threw this stuff out the window. Here’s the gist of it:

    Treat every piece of content as the same as every other, and store it all in a single table. Preposterous? Probably. But bear in mind that there will be a common set of metadata attributes that every piece of content will have (at least in this context): a unique name or identifier (the guid), a date it was created, a title, a description. And of course, there would have to be a “body” field for the content itself. Roll those into the table structure.

    What about different types of content—text versus images? Easy—include a MIME type field in the table, that defines the content type—”text/html” or “image/jpeg,” for instance. (You could store the actual binary data of an image in a file somewhere, linked to by the guid stored in the name field.)

    Let’s look at this real quick in the context of a MySQL table:

       content_id -> Primary key
       name -> varchar (unique key)
       title -> varchar
       description -> text (probably will be >255 characters)
       date_created -> datetime
       mime_type -> varchar (possibly enum?)
       body -> mediumtext (large data sets, up to 16MB)
    

    That handles the basic metadata, and could be sufficient for something like a weblog. But what if I want to add some content that has additional metadata that the table doesn’t account for—like a geocaching record, and I want to track latitude and longitude coordinates somewhere? I can’t add more fields to the table—that’s a loser’s game for (I hope) obvious reasons. Once I had settled on the idea of a MIME type field, the answer seemed clear: XML. Bake XML into the database structure as content.

    To be clearer: set the MIME type of that piece of content to “text/xml” and the populate the body field with XML data of the content in question, with the extra metadata fields rolled into it as part of its XML definition. So, you might populate the body field with something like:

       <content type="geocache">
          <latitude>45.6684776</latitude>
          <longitude>-121.3394771</longitude>
          <dateHidden>2003-12-05</dateHidden>
          <cache type="traditional" name="coffee can">
             <item>Spiral-bound logbook</item>
             <item>Yo-yo</item>
             <item>Deck of cards</item>
          </cache>
       </content>
    

    What I like about this idea is its object-oriented analogy: start with a basic definition for content—a “class”—and each instance of content inherits from the base class and, via XML, can extend the base class for itself.

    There’s limitations to account for, as well. Not all types of data can be easily shoehorned into this model, so it shouldn’t be attempted. For instance, a voting system: you need a table to store the poll topics, one to store each option/answer, and at least one more for storing user votes. There would be no sense in trying to hack this into the content table, and the system would suffer if it was. So there’s always room for specialized functionality.

    And, I’ve modeled some compromises. Rather than trying to manage the category system as just another type of content (so that you’d end up with parent-child content relationships), I pulled the categories out into another table. It’s cleaner and there’s more benefit to the system this way—I can add a many-to-many lookup table to allow for multiple categorization. (Incidentally, in my PPS, I call these channels, because they might fulfill a purpose beyond that of a traditional category system.)

    Another compromise is the concept of content nodes. A content node is basically a grouping that content can be classified into—another lookup table. All the content I write for my blog would be assigned to the “chuggnutt.com blog” node, for instance.

    Oops, and don’t forget about a commenting system—user comments (and perhaps ratings?) are a valuable source of metadata for any given piece of content. So I’ve allowed for another table to store comments, rather than making them another type of content, because I want to stay away from the parent-child relationship situation I alluded to above.

    Will it all work? I don’t know. The proof is in the pudding, though—I’m working to convert my own blog to this system, so I’ll find out firsthand just how good (or bad) my ideas are. I really don’t think this system is viable to run as a large-scale, enterprise-style content management solution—hence the reason I’m calling this a Personal Publishing System. Incidentally, the working name (or code name, if you will) in the back of my mind for this system is “Spokane.”

    I’m making this an open process, too, to solicit comments on my ideas, and hopefully to give ideas to any other people out there looking to write their own systems in PHP. To that end, the next article I’ll post on this topic will move from theory to practice, and I’ll publish the MySQL database schema I’ve been developing (with comments). Exciting stuff!