« February 2008 | Main | April 2008 »

March 31, 2008

Selling curry to the chinese takeaway

Have you ever walked into a Chinese Takeaway and sold them three chicken curries with rice? Or gone to your local station and bought three tickets for yesterday? I'll be you haven't - there are certain things that don't work quite the same way when you go negative. I can't carry on once my car has run out of petrol, secure in the knowledge that I can then put 11 gallons into my 10 gallon tank when I reach the next filling station.

But with some things, negative values ARE acceptable. What is the temperature today? 6? 4? -4? The only difference is that you'll want gloves and need to scrape ice in the latter case.

When writing code to establish the maximum of a series of numbers, it's very tempting to assume that the largest_so_far is zero, then compare each of your series with largest_so_far and note the new value if it's higher. Which works very well if you've got positive numbers. But what were the temperatures in Sptitzbergen last week? -15, -20, -15, a hot -8, and -14. So my tempting algorithm wouldn't work - it would give me a scorching zero degrees.

Solution? Don't start at zero ... start at the first value in the series. Here's an example of a part of that code in Tcl:

if {$count} {
  if {$biggest < $input} {set biggest $input}
  if {$smallest > $input} {set smallest $input}
} else {
  set biggest $input
  set smallest $input
  }

Posted by gje at 06:00 PM | Comments (0)

More about Graham Ellis of Well House Consultants

March 30, 2008

First Great Western Weekend

It has been a long - a VERY long - weekend and I've still got a huge pile of things I want to do. But it has been productive too.

When I set up the First Great Western Coffee Shop - a forum site for First Great Western Passengers - I wondered whether or not it would take off. Well - thanks (it must be admitted) to FGW themselves, who have managed to generate an incredible degree of dis-satisfaction in their customers and wannabe customers from whom they have withdrawn trains, our forum has flourished. People love talking when they have issues, but go quite quiet when they don't.

In fact - it flourished so much that I couldn't keep up with all the moderation that was needed - a very low proportion of posts need attention, but where the post level creeps up to 50 a day it's still a lot to look after. So I approached the steadier pairs of hands and appointed them as moderators. And still it grew, and the moderation and admin team grew with it.

We have excellent communications set up between the "mods" and they work well ... but there were some who had not met others, and this Friday evening and Saturday daytime, we had our first moderator's meeting. Truly excellent - and thanks to our guest speaker (I know she will read this) - and a lot of issues discussed and - today - tweaks made to the board. Onwards, upwards - whatever next? I don't know, but I sure know I've made a lot of very good friends, and learnt a very great deal too - through my "train experiences".

Posted by gje at 09:20 PM | Comments (0)

March 28, 2008

Please support improvements in our train service

Management overview

* Until 2006, TransWilts train services ran 5 times a day and rapidly grew

* First Great Western withdrew most trains - a decision based on incorrect forecasts - in December 2006. The remaining trains are poorly timed for the traffic on offer and of little practical use

* First have now prepared an alternative timetable which is
--- much more appropriate
--- financially very sensible indeed (NOT expensive)
--- for which train paths ARE available
--- for which (for most services) crew and train are earmarked.

BUT ... they do need to know it would be used, and political decision makers need reminding of the case too. Can I ask you - yes YOU - to sign up at:

http://www.savethetrain.org.uk/pledge.html

This site is only just starting up - the real push comes in April and May; I would really appreciate some early signatures from course delegates who have used the train (or would have used it if they could) and from all our friends and contacts in the area too.


Some Further Detail

Until 2006, 40% of our training course customers came to Melksham by train - travelling on the TransWilts line from Westbury or Swindon, at arriving at about 9 O'clock, then catching the 17:12 or 18:09 back at the end of their course.

And in 2006, you could catch the same line direct from Trowbridge to Swindon, a 35 minute journey ... or Chippenham to Salisbury in under an hour. And many, many people did - traffic grew year on year by 35% according to the office of the Rail Regulator.

I was on the 17:59 from Chippenham on 8th December that year. It was was what I call "NESTing" - "Nearly Every Seat Taken" in a two coach train and that's ideal. Most of the passengers were regulars ... but that was the last day that train ever ran. First Great Western's new service, starting the following Monday, scheduled just 2 trains a day at 6:30 in the morning and after 7 at night. All remaining trains withdrawn. And, no, there isn't much of a demand at the new times - I have seen the morning train with just five passengers.

In 2007, very few - less than 4% - of our training course customers came to Melksham by train. Some we pick up at Chippenham or get a taxi, but a lot simply drive all the way these days.

And in 2007, with no direct trains to Swindon between quarter past seven in the morning and quarter to eight at night, you could drive, do a dogleg train trip via Bath or catch the direct bus and take 95 minutes. Chippenham to Salisbury - where the train was under an hour, the bus takes well over two.

The "Save the Train" campaign, in association with many other groups, has been pressing for an improved service, and a timetable for such a service has been drawn up and validated for 2009 - but it needs your support. The current gap in service at Melksham - 07:17 to 19:11 - would be plugged by extra trains at 08:24, 09:28, 11:17, 12:28, 14:17, 15:28, 17:08 and 18:21.

See

Here to sign up
Here to see who has signed so far
Here for more information

Posted by gje at 03:54 PM | Comments (0)

March 27, 2008

Keep the client experience easy - single server contact point

Your company will have one or two web servers ... and you'll be visited by one or two million different clients. So it makes logical sense for all the complicated stuff to go on your one or two machines, and leave your clients with just a simple browser.

Have you even got on the phone ... to a utility, or travel company, or government office, or insurer or bank ... and found that you're referred on from one person to the next, to another and then to a fourth - who puts you on hold or tells you to call in again on another number? I have, and it makes sense - if you possibly can - when you're providing a service to provide a single point of contact. Not only to improve the experience of your customer, but also to make efficient use of you own resources.

Putting these thoughts together, it's logical to have a single web server program - such as Apache httpd - running on a server computer as the single point of contact for your organisation or web application. Then have that server, "silently" as far as the visitor is concerned - run scripts in Perl or PHP, which it turn refer on to databases using MySQL or some other technology - (Apache + Mysql + Perl / PHP = AMP). And then - with all this open source - what better operating system to oversee the whole than Linux, and you have your LAMP application.

There is a lot to deploying LAMP - but far better that than having to configure lots of machines and services or make life complex for your users. And you can learn just how the elements on the diagram that I've used to illustrate this article go together on our deploying LAMP training course

Posted by gje at 11:44 PM | Comments (0)

March 26, 2008

Setting up a new user - Linux or Unix

Creating a local user account on a Linux box:

1. Add an entry to /etc/passwd
2. Add an entry to /etc/shadow
3. Add an entry to /etc/group IF the user is in a new group
4. Use the passwd command to set the user's password
5. Create the user's home directory
6. Change the ownership of the user's home directory via the chown command
7. Login as the new user to check that the account works
8. Create a file via the new user's account to check he/she has write permission
9. Copy over any templates and startup files
10. Let the user know the account has been set up

The useradd command (adduser on Solaris) can take many steps out of this, and is also helpful if you're setting up an account that's to be shared between a number of Linux / Unix boxes.

As summarised on todays Linux Admin course

Posted by gje at 03:54 PM | Comments (0)


Useful link: Linux training

March 24, 2008

Easter Sunday at 404, The Spa

Easter has been a time to meet up with friends and family - old friends and new.

Here's our newest friend - Martin brought David Jonathan, not yet a week old, around to see meet us. David slept through, of course - but it was really great to see them, and to hear how Martin and Marta - proud parents - are getting on.

Dad, and Chris and Delene, also came around for a late afternoon Turkey dinner (we are not exactly ones for doing that traditional Christmas thing at Christmas!) and a fun afternoon had by all. REALLY good to catch up - almost an impromptu party!

See More Pictures

Posted by gje at 07:54 AM | Comments (0)

March 23, 2008

All Change, Portsmouth Harbour

It's so long since I was in Portsmouth that I was quite taken aback by the changes I found there yesterday - a trip to meet a friend of several years standing, and make two new ones. I learned that "The Pyramids" swimming pool, built just 20 years or so ago, has roof problems so severe that it's to be torn down, and I saw the new Spinnaker Tower and Gun Wharf areas.


The "Warrior" - the first iron clad warship - at Portsmouth


The spectacular Spinnaker Tower


View across Portsmouth Harbour to Gosport

Posted by gje at 11:07 AM | Comments (0)

March 22, 2008

Dynamic Memory Allocation in C - calloc, realloc

The Problem

The C programming language is a fixed array size language - you write the size of your variables into your code and that's how big they are. Overrun an array and you corrupt other memory - and it's up to you the programmer to ensure this doesn't happen. Many past security leaks, such as the codered virus and the Solaris Sendmail hole had as their root causes array overruns that were not checked.

There is a small help in compile time constants - #defines through the C pre-preprocessor which allow builds with different settings and array lengths (example here) but that isn't a true solution - what if you want to read a file with an indeterminate number of lines, all of which are of an unknown length? Surely there much be a better way that putting on an absurd-high limit? Well ... there is ...

The Solution

Malloc, calloc and realloc are standard C functions that let you allocate memory in a different area - know as the heap - dynamically at run time. Your variable names do NOT point directly at the memory allocated - instead you access the memory through pointers (lots of pointer examples here).

Taking my example problem above, I want to hold an unknown number of character strings in an array. I start by allocating a pointer to an array of strings which are themselves (you may recall) pointers / arrays. Thus

char ** info = NULL;

That's going to work well as it's a fixed size item, and it's the only memory we allocate in the main program area - the rest will be done through C's memory allocation functions.

We read a line in from the file (into, let's say, a single buffer called line which has a limit of 4k set on it). And if we have got a line, we then use realloc to allocate or expand the memory that infor points at:

info = realloc(info,(counter+1) * sizeof(char *));

In other words ... "take the old memory block at the info address, change its size to be one more than the number of lines that you've read so far, and return the new address into info". Oh - and the first time, info will start off as NULL so it will be a new allocation.

Very often, info will come back with the same value as it had before, but if the management algorithms in realloc have had to move it, you'll get a fresh pointer back. It's very clever!

Moving on, we use calloc - a single shot memory allocation function - to allocate the memory for each of the character strings within our array, based on the line length in each case:

llen = strlen(line);
info[counter] = calloc(sizeof(char),llen+1);

If we were storing just a fixed value for each line, we could do the whole thing with just a single realloc - but this is a complete and more realistic example of how, in C, you would slurp a whole file with no limit as to its size into an efficiently structured and allocated area of memory.

The complete working example from which I have taken the source code sample lines above is available here ... yet another new example, updated last week during our Public C Programming Course ... next course, June 2008 ... see our course index for later dates.

Posted by gje at 08:52 AM | Comments (0)

March 21, 2008

String interpretation in Ruby

Ruby's rather clever in terms or how it handles string interpretation. Since variable names only start with special characters sometimes, it can't use Perl's trick of making the $ and @ character special in a string. So instead it uses a #{.....} notation. For example:

puts "Tocker is #{tocker}"
uses a local variable.

puts "Ticker is #{$ticker}"
uses a global variable

and

puts "Sign #{noentrysign.colour} and area #{noentrysign.area}"
calls an instance or accessory method on the object. There is a complete example of that code here.

Posted by gje at 06:23 PM | Comments (0)

Some Ruby programming examples from our course

I was giving a Public Ruby Course to a small group at the end of last week ... and having a small group gave me the opportunity to write some demonstrations in front of them. I have now tidied these up and have pleasure in presenting to more Ruby demonstrations:

Ruby's BEGIN block

The compact method - strips out nil members from an array

Writing comparator methods such as "larger" and "smaller" in Ruby

Using a hash to provide a table of counters

Calling another process via a pipe in Ruby

Definition and use of a class in Ruby

Definition and the redefinition of the same function in Ruby

Posted by gje at 06:22 PM | Comments (0)

Variable types in Ruby

In Ruby:

* Variable with names starting with a lower case letter are local variables

* Names starting with a capital letter are constants - you can set them once each time you run a program and then they are fixed

* Names starting with a single @ character are object variables - in other words, you'll usually create one of each of the @ variables in an object for each object of the class you create. (I say "usually" as Ruby is dynamic and you can add variable to an object long after you have run the constructor if you really want to!)

* Names starting with two @ characters are class variables - so you create just one for the whole class which is shared between all instances.

* Names starting with a $ are global variables which you can refer to anywhere in your code.

You do NOT declare whether a variable is an int, a float or a scaly_anteater in Ruby, as all variables contain objects - and indeed a variable may contain a string at one point in your program, a cube at a later point and can finish up as a puff_of_smoke.

Here's an example piece of code.

def initialize(diameter,colour="white")
  @diam = diameter
  @colour = colour
  @@ndisc += 1
  $ticker += 1
  tocker = 17
  end

This is a constructor for an object for which who object variables are created - @colour and @diam. There is also a class variable called @@ndisc which is incremented every time this constructor is run, And $ticker is a global variable - it can be reference anywhere else in the code. The bare variables diameter, colour and tocker are local - and the tocker variable appears to be pointless (Ruby won't complain) as it is set then wasted as the method exits.

See a complete example that uses this code here

Posted by gje at 05:59 PM | Comments (0)

Well House Consultants / Manor - Staff

This Good Friday morning, I was serving breakfasts at 7 a.m. - truly the hotel business runs at all hours of the day and night, and 365 days a year (yes we did have breakfasts to serve and guests to check in on Christmas day!)

And so we need - and have - a strong team to cover 7 mornings and 7 evenings every week, through the year. I've introduced most of them to you in the past, but an update to the Staff Page this morning gave me a chance to come up with a picture of everyone - from the top to the bottom - to the same standard.


Sarah

Chris

Christine

Lisa

Jess

Martin

Graham

Leah

Charlotte

Posted by gje at 02:21 PM | Comments (0)

Using Structs and Unions together effectively in C

C's Structs allow you to define a number of different variables, of different types and sizes, sequentially within a collection - you could, for example, define an animal as being:

typedef struct {
  char name[15];
   float age;
   char breed[15];
  } animal;

But what if I wanted to have several structs which were similar to each other but not identical - that had many common elements but then varied. An example might be a range of products for sale at a shop, where some of the items are sold in int units (I'll sell you one or two motorbikes, but not 1.5) and others are sold in float units (kgs of apples, for example)?

A Union allows you to define a number of different variables, of different types and sizes, in parallel - i.e. sharing the same memory - within a collection.

Used carefully, a union within a struct can be used to produce a collection that can handle a whole family of slightly varied data types, such as the motorbikes and apples that I described just above. Here are the definitions:

typedef union {
   int units;
  float kgs;
   } amount ;
typedef struct {
   char selling[15];
   float unitprice;
  int unittype;
  amount howmuch;
   } product;

So that's a product which has a description, a unit price and a type (unit sales or sales per kg). It then has an amount union, allowing the same structure to store either a float or an int as appropriate. But it IS up to the programmer to ensure that the correct use is made of the unioned element.

On the Public C Course that finished yesterday (next one in June!), I wrote a new example to show this use of a union within a structure, and you can see the complete code here (opens in a new window).

You'll note the use of an array of pointers to product structs to allow me to loop through all the products easily, but the the great care I have to take within the loop to ensure that I use the integer or float member of the union as appropriate, based on the unittype variable I have provided for the purpose.

It's no co-incidence that there a great similarity here between the varied members of a combined structure / union and the varied data members of a series of classes that are all inherited from the same base class in C++, Java, etc - indeed, you could describe the use of structs and unions that I talk about here as a do-it-yourself form of inheritance and polymorphism.

Posted by gje at 10:58 AM | Comments (0)

March 20, 2008

Businesses in West Wiltshire - networking

Yesterday evening, we ran our first Speed Networking event of the year at Well House Manor. Over two one-hour sessions, each of 20 companies attended got to meet the other 19 companies who were with us, moving around the tables every five minutes. I find it a very educational excerise to provide an overview of what I do in just under 2 minutes - but it can be done ... and that leaves a couple of minutes for the companies to say "is it worth getting together later" - networking objective achieved!

It can be quite tiring networking with group after group - so the evening is split by a buffet supper - served last night by Chris and Sarah, and thoroughly enjoyed by the businesses attending. We had taken a considered decision not to serve free glasses of alcohol on this occasion - but rather we had a selection of fizzy and still soft drinks, tea and coffee, and they were enjoyed by all - with all being fresh and ready for the second (8 p.m. to 9 p.m.) session.

I was "Master of Ceremonies" for the evening; clearly a very good and productive time was being had by all, as I had to go into "Town Crier mode" - i.e. loud - to get people to move on.

And - look at this picture 20 minutes after the finish according to the clock - where people were moving around and spending longer networking long after the "round robin" had concluded. And this morning, my email box has been busy with questions and follow ups. Truly, a fruitful evening - and many thanks to Christine for organising all those busy business people to coma along!

The next Speed Networking Evening will be on Monday, 7th July 2008. Please email us if you're a business in the West Wiltshire area and we'll be delighted to have you along. There's a charge of £15.00 per business - £20.00 if you have two representatives - including the networking and the buffet.

Posted by gje at 03:05 PM | Comments (0)

March 19, 2008

Ruby, C, Java and more - getting out of loops

break and continue statements have been available for loop control for many years, and others functionallity has been added such as Perl's redo. From today's Ruby Course, here's a table that compares these loop controls in Ruby to similar commands in the other languages that I have been discussing with this week's course.

C/JavaPerlRubyeffect
breaklastlastGet me out the loop NOW!
continuenextnextgo for the next loop iteration
-redoredorerun current loop iteration
--retrylet's start the loop again, should we?

Posted by gje at 04:07 PM | Comments (0)


Useful link: Java training

March 18, 2008

What is an lvalue? (Perl, C)

An lvalue is an expression that you can write on the left hand side of an assignment statement - in other words an expression that defines a specific memory address of a variable.

The most common lvalues are simple variables or array / list / hash / dictionary members ... for example

$hello = "Hello World";
$greet[5] = "Hello World";
$greet{"UK"} = "Hello World"; # all these in Perl

val = 15;
jolly[posn] = 27; # These two in C

There are some surprises until you think about it.

In Perl you can write $lhs[$n+4] = 17; but not $lhs+4 = 17;. Yet in C, if vvv is a pointer to an array you can write vvv+4 = 15; quite happily - altering the fifth element of the array.

You'll find the term lvalue come up most usually for the programmer in a compiler error message - "invalid lvalue" you will be told. What the compiler really means is that the twit who wrote the code is trying to save a value into an expression that doesn't actually define the memory address of a variable.

Posted by gje at 06:48 PM | Comments (0)


Useful link: Perl training

March 17, 2008

Congratulations, Martin and Marta

Congratulations to Martin (our morning manager) and Marta on the arrival of David Jonathan - a son, born this morning at about a quarter past 10. The brief message I have tells me that mother and son are doing well.

Posted by gje at 06:48 PM | Comments (0)

Rome, and the faith of Rome

I have a number of sharp memories of Rome - a brief family visit there in July of 2004 (I think that was the year). Take a family group of somewhere between half a dozen and a dozen, all strong characters but with very different backgrounds and very different habits when holidaying / touring. Mix in what was - to me - an unbearable heat - and that made my wick somewhat short, shortened further by it being a very busy time so I was tired before the adventure started. You're probably getting the picture. And P, P and others - I probably owe you a very belated apology for any offense I may have caused.

Of all the sharp memories, the sharpest of the lot was of the Vatican. The queuing for what seemed like an eternity outside, a queue snaking around the wall with old, gnarled, crippled disabled women - all dressed in black - begging in their abject poverty from the tourists patiently inching forward for their visit. Then the offensive oppulance shown inside the Vatican itself - riches which I found obscene collected over centuries by the leaders of a religion of which the leader - in the last week or two - has just declared excessive wealth a new mortal sin. Interestingly, a quick search for the wording gave me a top hit in which someone else questions the hypocrisies of this.

Last week, I took my course delegates out into Melksham one blustery lunchtime. We gusted into a cafe in the Market Place, and found ourselves a table. The last one of the group failed to shut the door properly, and it blew ajar - at which one of the young ladies walked over from behind the counter and shut it with a scowl and needless venom. "Easter - From Attitude to Gratitude" said the card in the menu holder on our table.

So I guess it's all right, in their eyes, for these people to have excessive wealth or a sharp attitude that's clearly against others who make an innocent mistake. After all, all they need do is to confess their sins and they'll be able to sleep in peace at night. I don't share these beliefs, and I so I don't have such an easy time if I mess something up that effects others. But I do confess that I feel much happier with my own values and words that I do with the values and words that I see and hear when duty takes me to services, has me singing hymns, a couple of times in the last year. I go along out of respect for those around me who's decorum seems to indicate a deep belief. Yet sometimes I wonder.

I had a chance to take some wonderful pictures in Rome which I have had a brief looks through as I put this item together. I note that I didn't have the heart to photograph the beggar women.

See also: a random picture of Rome and the PHP script to display a random picture

Posted by gje at 12:36 AM | Comments (0)

March 16, 2008

Please don't shout at me!

From a forum I moderate:

xxxxx (a new poster) wrote
TALKING OF SHORT FORMED TRAINS DID ANYONE TRAVEL ON THE 17.02 FROM MELKSHAM 12/03/08 JUST A SINGLE 153, I THINK EVERONE GOT ON DONT KNOW WHAT HAPPENED UP THE LINE.

I'm not usually inclined to pull someone up in their first or second post - especially as some people just post a handful of times. But I do find the use of all capitals to be hard to read - as if I'm being shouted at, and I am tempted to ask the writer to modify the posts - or at least to add in lower case where appropriate on future contributions.

It reminds me uncomfortably of a time that I was a moderator on another board and we all (in the moderation team) getting a bit steamed up about the poor typing, use of English and pure stupidity (apparently) of some of the things that came from one particular poster. "Is she real? Is she a troll? Is she a [personal description deleted]?" we asked. And we darned nearly shut her account off. It turned out that she was nearly blind and (I think - it is a long time back) wheelchair bound or nearly so - every byte of her posts were a struggle and once you knew of her background, which she wasn't shouting about / asking sympathy for you understood why some things happened to her.

I'm not suggesting the same will turn out to be the case here - though we could have posts submitted through a very simple device where case-mixing is hard to this day ...

Location, time and date modified to protect the identity of the original poster ...

Posted by gje at 08:29 AM | Comments (0)

March 15, 2008

Spring and early summer training courses

There are a lot of training course products out there - but you're looking for the classes and tutoring that meet your needs - the one in a thousand that is right for you. At Well House Consultants we specialize in training niche IT topics to small groups - either on public courses at our training centre / hotel or on site at your offices. We're very familiar with the subjects we teach (after all, we write our own notes) so we're able to answer customer questions that stray a little off the syllabus, and we offer a guarantee that once you book a course, it will run on the dates you have chosen.

Spring 2008 Schedule

Public course this Spring ... from Easter to Midsummer

Linux Basics 25th March (also 19th May)
Linux Admin Overview 26th March (also 20th May)
Linux Web Server 27th and 28thMarch

The three courses above combine to form a Deploying Apache httpd under Linux / Unix course.

Technology for PHP 14th April
PHP Programming 15th to 18th April (also 16th to 19th June)
Object Oriented PHP 20th June

The "Technology for PHP" day is intended for novices to HTML, Programming, SQL or Web Structures - it's a starter day to ensure that delegates have the prerequisites for the following PHP Programming course. The extra day on "Object Oriented PHP" - running after the June course only - introduces you to Object Oriented techniques as they are used in PHP; that's great for medium sized to larger applications.

Python Programming 12th to 14th May

Deploying Java Applications under Linux or Unix 19th to 23rd May
Deploying Apache httpd and Tomcat 22nd and 23rd May

The Apache Tomcat and Apache httpd web servers form the bedrock server platform for many Java based web applications, and they are commonly deployed on Unix or Linux platforms. If you are already a Unix / Linux professional, come along on our 2 day course on 22nd and 23rd May. If you are not yet familiar with Linux or Unix, and are new to the Java world, the complete 5 day course will introduce you to all of these technologies and get you ready to deploy applications thereon.

C Programming 9th and 10th June
C and C++ Programming 9th to 12th June
C++ for C Programmers 11th and 12th June

These courses are fast-moving courses for delegates with prior programming knowledge. For C come along on 9th and 10th June, for C++, stay wih us from 9th to 12th. If you already have C skills and just need to add C++, your ideal course runs on 11th and 12th

Regular Expressions Day 13th June

Whether you're writing Perl, PHP or Python ... or setting up mod_rewrite under Apache httpd ... you'll want to use the power of pattern matching with regular expressions. Many people have experimented nervously with regular expressions - if you're one of those, come along on this day to learn how to make full use of their real power.

Next public Perl, MySQL and Tcl courses in July. Ruby Course runs just BEFORE Easter, then is available again in July.


Finally, if you have a group of 4 or more delegates who require the same course at the same time, we have diary openings in early May for some private course. Such courses can be tailored to meet your needs, and run at our place or yours. See our diary for available dates and here for details of private courses at our centre. For private courses at your office, see here.

Posted by gje at 11:05 AM | Comments (0)

Making PHP and MySQL training relevant to the course delegates

If I'm training on MySQL or PHP, I'll often come up with an example in front of the class - it's much more effective training to see HOW an answer is reached than to simply be presented with a pre-written example. And so it was yesterday that I wrote a small application to extract data from tables and display it ... with checkboxes provided to allow a filtering out on subsequent refreshes of the page to help supposed used display selectively what they require.

If the application sounds like the sort of thing you need, you can see the PHP / MySQL (HTML too) code here. You can try out the application here - yes, it is on our live server (the only change being account names and passwords!). And you can come along and learn php or MySQL on our public (open) courses where you'll be in the company of a handful of other people from different oranisations to bounce your ideas off, or book a private course at our centre which can be even more closely tailored to your needs. If you have a group of six or more delegates, we can also run a private course at your offices - that cuts out your staff travel and means they can sleep in their own beds and catch up on a little urgent work at the very start or very end of the day.

Our next public PHP course starts on Tuesday, 15th April 2008 and as I write we have space for three more delegates on the course and at our training centre / hotel. If you're reading this after that date has passed, look at our diary of upcoming courses for current / new dates - these course run quite regularly!

Posted by gje at 09:49 AM | Comments (0)


Useful link: PHP training

Database design for a shopping application (MySQL)

Here's a "proof of concept" demo from yesterday's MySQL session - a plan for the various tables that might be involved, and a few sample columns to see how "the whole" would work together.

On one side, you have a table of the shops that you're running the site for - the code is designed to be able to operate for multiple outlets with different products at the same time. On my diagram, that's called "takeaways" which may lead you to conclude we were talking about this just before lunch.

Each takeaway have a number of product groups - we used the term "aisles" to describe them as for ease of design we wanted each table name to start with a different letter and we didn't want to confuse categories with customers!

And then in each aisle you have a number of individual products.

That's the products for sale - those three tables are altered only by the system administrator as products and prices change.

Then on the other side, you have three tables which control the dynamics of the orders.

A customer table has a record for each customer.

Each order a customer places has a row in a separate table which can join back

And finally, there's an item table which lists all the items on each order. It also includes an id from the product table so that appropriate joins of the tables will identify what the products being bought actually are.

My habit of using a primary key called xid, where X is the first letter of the table name, should help to clarify the example - you can see where the joins need to be written using this technique, as you'll always want to link columns with the same names.

Comments / enhancements? Many! You'll want to add in all the extrafields for order stats and comments. A system that offers your repeat customers the ability to pick back through what they have bought before. Extra data to ensure that anyone who orders a curry is also offered rice or nan ...

The delegates on yesterday's course asked me to post this information up here - on all of our courses, we listen to our customers' specific needs and tailor the presentation to suit. It makes for much more relevant, effective training - even if the resultant proof-of-concept posts here make the graphic artists amongst us quake at the scruffy graphics!

Posted by gje at 09:19 AM | Comments (0)

Joining MySQL tables revisited - finding nonmatching records, etc

A join lets me connect two tables one to the right of the other. Here's an example. First table - estate agents:

mysql> select agent,town,aid from agents;
+--------------------------+------------------+-----+
| agent | town | aid |
+--------------------------+------------------+-----+
| Alder King | Trowbridge | 1 |
| Connells | Trowbridge | 2 |
| DK Residential | Trowbridge | 3 |
| Jayson Kent | Melksham | 4 |
| Halifax | Trowbridge | 5 |
| Halifax | Melksham | 6 |
| Greg Pullen | Devizes | 7 |
| Town and Country Estates | Westbury | 8 |
| Davies and Davies | Bradford on Avon | 9 |
| Kavanaghs | Melksham | 10 |
+--------------------------+------------------+-----+
10 rows in set (0.17 sec)

And second table - homes for sale:

mysql> select agid,locate,asking,sid from sales;
+------+------------+--------+-----+
| agid | locate | asking | sid |
+------+------------+--------+-----+
| 10 | Semington | 225000 | 1 |
| 10 | Melksham | 195000 | 2 |
| 10 | Atworth | 237500 | 3 |
| 8 | Westbury | 152000 | 4 |
| 8 | Trowbridge | 205000 | 5 |
| 6 | Melksham | 229950 | 6 |
| 5 | Trowbridge | 335000 | 7 |
| 1 | Trowbridge | 96950 | 17 |
| 5 | Hilperton | 279950 | 8 |
| 4 | Melksham | 149950 | 9 |
| 1 | Trowbridge | 220000 | 18 |
| 4 | Melksham | 127500 | 10 |
| 11 | Melksham | 465000 | 11 |
| 3 | Semington | 222000 | 12 |
| 3 | Hilperton | 465000 | 13 |
| 2 | Westbury | 140000 | 14 |
| 2 | Trowbridge | 116000 | 15 |
| 11 | Melksham | 275000 | 16 |
| 4 | Semington | 250000 | 20 |
+------+------------+--------+-----+
19 rows in set (0.17 sec)

By default, a join connects all records in the first table with all records in the second table , so with 19 rows in one and 10 rows in the other, a joine gives me no less that 190 records!

(If the following outputs clip or folds - see here for an alternative display)

mysql> select agid,locate,asking,sid,agent,town,aid 
from sales join agents;

+------+------------+--------+-----+--------------------------+------------------+-----+
| agid | locate | asking | sid | agent | town | aid |
+------+------------+--------+-----+--------------------------+------------------+-----+
| 10 | Semington | 225000 | 1 | Alder King | Trowbridge | 1 |
| 10 | Melksham | 195000 | 2 | Alder King | Trowbridge | 1 |
| 10 | Atworth | 237500 | 3 | Alder King | Trowbridge | 1 |
| 8 | Westbury | 152000 | 4 | Alder King | Trowbridge | 1 |
| 8 | Trowbridge | 205000 | 5 | Alder King | Trowbridge | 1 |
| 6 | Melksham | 229950 | 6 | Alder King | Trowbridge | 1 |
| 5 | Trowbridge | 335000 | 7 | Alder King | Trowbridge | 1 |
| 1 | Trowbridge | 96950 | 17 | Alder King | Trowbridge | 1 |
| 5 | Hilperton | 279950 | 8 | Alder King | Trowbridge | 1 |
| 4 | Melksham | 149950 | 9 | Alder King | Trowbridge | 1 |
| 1 | Trowbridge | 220000 | 18 | Alder King | Trowbridge | 1 |
| 4 | Melksham | 127500 | 10 | Alder King | Trowbridge | 1 |
(etc)
| 3 | Hilperton | 465000 | 13 | Kavanaghs | Melksham | 10 |
| 2 | Westbury | 140000 | 14 | Kavanaghs | Melksham | 10 |
| 2 | Trowbridge | 116000 | 15 | Kavanaghs | Melksham | 10 |
| 11 | Melksham | 275000 | 16 | Kavanaghs | Melksham | 10 |
| 4 | Semington | 250000 | 20 | Kavanaghs | Melksham | 10 |
+------+------------+--------+-----+--------------------------+------------------+-----+
190 rows in set (0.36 sec)

Clearly that's not what I want - I usually want so see what connects to what, so I add an on clause to give me all the records that match as appropriate:

mysql> select agid,locate,asking,sid,agent,town,aid 
from sales join agents on aid = agid;

+------+------------+--------+-----+--------------------------+------------+-----+
| agid | locate | asking | sid | agent | town | aid |
+------+------------+--------+-----+--------------------------+------------+-----+
| 10 | Semington | 225000 | 1 | Kavanaghs | Melksham | 10 |
| 10 | Melksham | 195000 | 2 | Kavanaghs | Melksham | 10 |
| 10 | Atworth | 237500 | 3 | Kavanaghs | Melksham | 10 |
| 8 | Westbury | 152000 | 4 | Town and Country Estates | Westbury | 8 |
| 8 | Trowbridge | 205000 | 5 | Town and Country Estates | Westbury | 8 |
| 6 | Melksham | 229950 | 6 | Halifax | Melksham | 6 |
| 5 | Trowbridge | 335000 | 7 | Halifax | Trowbridge | 5 |
| 1 | Trowbridge | 96950 | 17 | Alder King | Trowbridge | 1 |
| 5 | Hilperton | 279950 | 8 | Halifax | Trowbridge | 5 |
| 4 | Melksham | 149950 | 9 | Jayson Kent | Melksham | 4 |
| 1 | Trowbridge | 220000 | 18 | Alder King | Trowbridge | 1 |
| 4 | Melksham | 127500 | 10 | Jayson Kent | Melksham | 4 |
| 3 | Semington | 222000 | 12 | DK Residential | Trowbridge | 3 |
| 3 | Hilperton | 465000 | 13 | DK Residential | Trowbridge | 3 |
| 2 | Westbury | 140000 | 14 | Connells | Trowbridge | 2 |
| 2 | Trowbridge | 116000 | 15 | Connells | Trowbridge | 2 |
| 4 | Semington | 250000 | 20 | Jayson Kent | Melksham | 4 |
+------+------------+--------+-----+--------------------------+------------+-----+
17 rows in set (0.18 sec)

Which gives me just 17 out of 190 records.

I can even ask for the other 173 records if I wish by switching to a not equals operator and getting a list of who is NOT selling what - the Estate agents you can walk into and enquire about a specific house to be told "Sorry - that one's NOT on our books". Sounds silly, doesn't it - but the query IS possible:

mysql> select agid,locate,asking,sid,agent,town,aid 
from sales join agents on aid != agid;

+------+------------+--------+-----+--------------------------+------------+-----+
| agid | locate | asking | sid | agent | town | aid |
+------+------------+--------+-----+--------------------------+------------+-----+
| 10 | Semington | 225000 | 1 | Kavanaghs | Melksham | 10 |
| 10 | Melksham | 195000 | 2 | Kavanaghs | Melksham | 10 |
| 10 | Atworth | 237500 | 3 | Kavanaghs | Melksham | 10 |
(etc}

| 2 | Trowbridge | 116000 | 15 | Kavanaghs | Melksham | 10 |
| 11 | Melksham | 275000 | 16 | Kavanaghs | Melksham | 10 |
| 4 | Semington | 250000 | 20 | Kavanaghs | Melksham | 10 |
+------+------------+--------+-----+--------------------------+------------------+-----+
173 rows in set (0.35 sec)

You may have noticed that we had 19 properties for sale, but only 17 of them came up on the "reasonable" join. That's because my data includes two properties which are not listed with any agent at all - they're for sale by owner. If I want to include extra records to ensure that I have one output row for EVERY incoming row in the leftmost of the tables in my join, I can generate the extra records by specifiying a LEFT JOIN rather than a JOIN, and the extra records are generated, NULL filled. There's a full explanation and example of left and right joins [here] and that page also shows you how to find ONLY those records which don't match - the "for sale by owner" orphans, and the estate agents with nothing for sale.

Posted by gje at 08:47 AM | Comments (0)

March 14, 2008

Budget tax increases hit vehicle market

Seen in Melksham at lunchtime today:

The Chancellor put heavy tax increases onto larger road vehicles this week in his budget - I wonder if he expected to have quite such a swift and far-reaching effect as this!

Posted by gje at 07:58 PM | Comments (0)

March 13, 2008

C - structs and unions, C++ classes and polymorphism

C's structs allow you to define a variable type in which you can hold a variety of elements by name ... and that's very similar to how you define all the variables within a C++ class. In a C++ class, though, you also define your methods which take that language forward into the Object Oriented world.

C's unions let you define a block of memory which has two (or more) names associated with it so that - when combined with structs - you can produce a whole family of defined variable types based on a common core, but then varying in parts where appropriate. In OO terms, that's starting to head towards C++'s inheritance and polymorphism ...

Posted by gje at 06:28 PM | Comments (0)

March 12, 2008

Await guests in the early hours

You may wonder what I am doing sitting at my keyboard at 1 in the morning!

We have a rule - "we don't take reservations for tonight after 10 p.m." We made the rule as we're really not well suited to provide accommodation to people who have spent the evening in the local pub and are then looking for somewhere to stay because they can't drive home and they hadn't really thought about planning ahead. Bitter experience has shown us that such people will drag us out of bed, tell us they want a room and that they don't care about the price - but then tell us that our price is far too high for them and say they've only got twenty five pounds and can we do it for that. And by the way they need a room with three single beds (which we don't have for that. The customer is always right and in these cases especially - our prices and facilities are not what they are looking for, and I just wish they had looked at the illuminated sign that makes the prices very clear before they rung the bell that dials us at home.

It was about 20 past eleven - that's about 2 hours ago - that the phone rang last night. "Here we go". And, yes, an enquiry for rooms "tonight". "Sorry - we don't take bookings for tonight ...." but there was something different, and it turns out that the search is on for rooms for four people who have been working on the railroad about 8 miles from here since 7 this morning - a job that's long overrun and they need somewhere to lay their heads when the job is done. And so I wait; I feel I've made the right decision to bend the rule, but really I can't yet be sure. All I can say is that I made what I feel was the right judgment at the time, and whatever the outcome there's always the need to consider the individual and not tar everyone with the same brush.

Posted by gje at 01:57 AM | Comments (0)

March 10, 2008

London Midland ... Merrymaker ... Percy Danks

"Can you write about some good rail trips" asked Jim on the forum I administer ... and my mind went back to Percy Danks and his Merrymaker day excursions. And when I write, I go on rather. Have a look at the topic here

I didn't make real mention of the Scottish trips he ran too - overnight both ways, sleepers if we were very lucky but usually sleeping in the coach for a full day at Oban (with a trip on the KGV to Fingle's Cave and Iona) or to Mallaig for a boat up the sound of Sleat to Kyle of Lochalsh, the Kyleakin Ferry, and a coach tour of Skye. Fond, fond memories.

Posted by gje at 08:20 PM | Comments (0)

March 09, 2008

I dont care - goodbye

"I don't care" ... what a great publicity line for an attention seeker, except that it rather does close the door if the person or people who are being addressed just say "fair enough".

I've seen the line used a number of times over the years as a "goodbye" on forums, where a difference between the board's operators / moderators and a member leads to one party moving on. I've actually been on both side. I can admit to using the phrase (or at least indicating my lack of concern) when I left uk-yankee some 3 years back when really I did care - very much indeed. And with the boot on the other foot, I found myself this morning in touch with the other moderators on the First Great Western Coffeeshop concerning a member who we had asked to moderate his language / criticisms of a personal nature, and who has, regrettably, chosen to use that phrase as a probable exit.

Of course he/she cares. More than you (and the moderators) might even imagine. Forums and online discussion boards can become a part of people's lives. When they've been posting for over 100 days, with over 100 individual posts, it WILL be a big shock to their system to break it off. Indeed, the very over-reaction to a gentle "please watch what you say - this can be read by children, and also the very people you criticize" message indicates just how much the quitter cares. And if I look carefully, I can see withdrawal symptoms - a visit but no action from the same place ... after midnight ...

Where am I headed? Well - to some extent this post is overdue and cathartic - as it gives me a chance to comment, long, long after it matters to me (truly, I think!) or anyone else - about the time the boot was on the opposite foot and I felt the need to leave uk-yankee (where I was a moderator too). It was over the problem that some of the newer members had with me being (a) British and (b) male in a predominantly American female group; a significant feeling that it was more important for the moderators to be all their peers that to have (in my case) background knowledge for the "travel and transport" section I looked after, with a lot of transatlantic knowledge based on an intercontinental courtship. There were other issues too - a conflicts of interest, and another potential one. There was a community get-together at our home which was for female American members and their non-participating British partners only. This was based on a discussion thread - active male members of the forum NOT welcome was the majority view - it was to be girlie chat in one room and hubbies / boyfriends in another - no doubt boozing and watching the tele was the plan; didn't turn out like that - I ended up being ordered around in my own home by a bossy b**ch who so clearly felt that the American race is far superior to the British that I wondered what she was doing in the UK ... and that when you visit someone in your home, your role is "prince / princess" and theirs is "servant / skivvy". I won't go into the "potential" - it wasn't a problem at that point to me or the people with whom it conflicted, but it could have become one if stirred by - well people like the ones I mention in the previous sentence!

But you can see I really did care (and I still feel hurt) by the very act of bringing it up here some 3 years later. And - I think - it helps put me in the shoes of forum members who fit only 98% not 100%. Regrettably, a forum cannot be somewhere that total freedom of speech on any subject is granted; there are legal issues, there are issues of the forum providing a comfortable place for our general audience, there are questions of diluting real content on our chosen specialist subject. There are also other questions that you might not consider, such as the cost of operating a board that has so much traffic that the money to be paid to the ISP rockets (yes, I have seen that happen - and have you ever wondered who funds a forum?)

In the cold light of day, there's a positive aspect to all of this. There does become a time to move on. To do something different, to set new goals, rather than getting set in a rut. But, seeing both sides of "I don't care" also tells me that it's by far the best if the door can always be left open - many a word has been written in haste and regretted thereafter, and it's in both party's interest for the doors to be left open should they be desired or required to be used in future. And I have reposted on "UK-Y" since my June 2005 decision - 6 later that year, 5 posts in 2006, 1 early last year ... looking back there in the last few minutes - first time in 2008 - I see that the top posters all remain old friends, with the elements over whom I left not in the rankings, but there's only a very minor temptation indeed to add a message somewhere.

Posted by gje at 08:22 AM | Comments (0)

March 08, 2008

What colour is the season?

Do you associate seasons with colours? What about the current season?

No - something there looks a bit wrong.

No - still no right - how about this?

Ah - much more like it - it's the start of the Roadwork Season! We have Melksham's centre up for 8 weeks with the two ends of the town linked only by the bypass. Then - when that's back we have a few days before the bypass again gets flooded with spilt traffic - this time from the A36 all the way over near Bath, with heavies kindly donated to us for 3 months.

Yes - that looks right. Certainly the yellow season!

Posted by gje at 06:17 PM | Comments (0)

March 07, 2008

Melksham - Swindon. Train v Bus v Car

I'm going to an event called "Social Enterprise and the railways" tomorrow - and I'm Driving there - to Swindon. How silly can you get! But it's a case of the head ruling the heart.

I could have left on the direct train at 19:50 tonight. I could catch the hourly bus to Chippenham then the hourly train on tomorrow - but that would leave me with a 56 minute wait as the timetables have been designed to fail the through traveller.

Amongst the speakers is Anne Snelgrove - local MP and PPS to the Transport Secretary Ruth Kelly. It will be very interesting to hear what she has to say about the provision of public transport that is capable of meeting the disparate range of travel requirements we have in this area.

Here are some recent links on the "train subject":

A new TransWilts Study

Campaign handout - what we have now and what we should have and separate what we have and what we should have sheets.

Travel Watch South West handout to Save the Train

First Great Western Coffeeshop flyer

Recent Pictures

Posted by gje at 10:40 PM | Comments (0)

March 06, 2008

Strange behaviour of web directory requests without a trailing slash

When you call up a web page and you give a directory name WITHOUT a training slash, the web server return a "moved temporarily" page - code 302 - giving you the same name WITH a trailing slash as your new page:

Dorothy:~ grahamellis$ telnet 192.168.200.162 80
Trying 192.168.200.162...
Connected to 192.168.200.162.
Escape character is '^]'.
GET /jdemo HTTP/1.0
 
HTTP/1.1 302 Moved Temporarily
Date: Thu, 06 Mar 2008 14:20:08 GMT
Server: Apache-Coyote/1.1
Location: http://192.168.200.162/jdemo/
Content-Length: 0
Connection: close
Content-Type: text/plain

and that's followed by

Dorothy:~ grahamellis$ telnet 192.168.200.162 80
Trying 192.168.200.162...
Connected to 192.168.200.162.
Escape character is '^]'.
GET /jdemo/ HTTP/1.0
 
HTTP/1.1 200 OK
Date: Thu, 06 Mar 2008 14:20:55 GMT
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=51F67B6EBA96D532A6E405BAD2129968; Path=/latmjdemo
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 1070
Connection: close

This extra loop means that you'll get very odd behavior if you call for a page without a trailing slash on a server on which either
a) You don't have the server name properly set up or
b) You are proxying, and your ProxyPassReverse isn't compatibly configured.

Posted by gje at 04:25 PM | Comments (0)

March 05, 2008

Languages compared - based on developer community size

Thanks to Leah for forwarding a link to Tiobe - "The Coding Standards Company" and their page showing the relative popularity of languages when measured by the size of the community for each. It's interesting to see how the programing languages we teach fit in to the ranking table.

1. Java 20%
2. C 16%
(Visual Basic)
4. PHP 10%
5. C++ 10%
6. Perl 6%
7. Python 5%
(C #)
(Delphi)
10. Ruby 2.5%

We do not provide courses on the languages listed in brackets; we do also provide courses on Tcl which we know to be very niche indeed.

Posted by gje at 11:54 PM | Comments (0)

March 04, 2008

Default file (MiMe types) for Apache httpd and Apache Tomcat

Apache Tomcat web server default MIME type

What file extension maps to what "Mime Type" in Apache Tomcat? It's important to know, since the Mime type is sent out by the server to the browser to tell the browser how to handle the following data stream.

a) There is a long list of extensions and their mappings in the conf/web.xml file - for example it contains
<mime-mapping>
<extension>html</extension>
<mime-type>text/html</mime-type>
</mime-mapping>

b) Within the source code of Servlets, an appropriate method call is used to set the type, for example
outgoing.setContentType("text/html");

c) If you have enabled CGI, you'll generate a Mime header in your script

d) And if none of these apply ... the default Apache Tomcat Mime Type is text/plain. Here's an example using a .duck extension ...

Apache httpd web server default MIME type

a) Most extensions are mapped according to instructions in the TypesConfig directive in httpd.conf, which may read something like:
TypesConfig conf/mime.types

b) Perl scripts (CGI) can generate a mime header, and if you're using PHP you can use the header section to change the type.

c) If the mime_magic module is loaded, the contents of the file itdelf will be examined for clues as to the return type. The configuration directive is

<IfModule mod_mime_magic.c>
MIMEMagicFile conf/magic
<IfModule>

d) If the httpd server still hasn't been able to work out the type it will use the value specified in the DefaultType setting in httpd.conf:
DefaultType text/plain

Posted by gje at 04:55 PM | Comments (0)

Guidlines for posting on a forum

I help look after a number of forums, and it's always an interesting question what should and should not be allowed in terms of language and topic. Leaving aside issues of subject and content which would make another whole article, I have tidied up some notes on language and style for one of the forums and felt it is worth sharing. You are welcome to use these notes as a basis for any forums that you run, but please provide a link back to Well House Consultants at http://www.wellho.net and / or The Coffeeshop at http://www.firstgreatwestern.info/coffeeshop for our mutual benefit.

What is acceptable language and style on "The Coffeeshop"?

A brief guide for new posters, who should remember that this forum can be read by anyone and everyone, including children, the train company we travel with (or in the case of Melksham WISH to travel with), and groups and individuals who we may criticise .. and who we may wish to talk to and work with in the future.

Language

1. The words that "I can't bring myself to type" - you know the ones, I'm sure - certainly are out. And, no, I am not coming up with a list.

2. The "arse", "scum", "bastard", "moron" level - certainly out when used to refer to a member, an identifiable person, or one of a small group of people. Probably out too when used to talk about larger groups - a very slightly grey area there. But some of these words have to be acceptable in their original meaning. "There was a horrid scum on the coffee I was served in the buffet at Dilton Marsh station" has to be AOK.

3. Calling an identified person a "silly cow" or "twit" starts getting even more questionable. Again I would say "no" when an identified person, but the team behind the scenes does not wish to drive you to come up with colourful new phrases which might be even more difficult to moderate.

4. It has to be a case by case basis with many of the lesser terms and content which may offend by its combination of totally innocent words. I personally found a comment that I felt to be sarcastic referring to me as "his holiness" to be offensive, although I let it go by without comment at the time as it provided me with a useful reminder of my place. And that also reminded me just how many others may be offended from time to time, but not say anything!

The moderation team takes a delight in the fact that there a number of us moderating. Any poster who seriously transgressed the acceptable level of any one of the group may get asked to change his/her language (or have it changed), so we cannot be 100% predictable and people should if in doubt, leave it out

Style

a. I would like to discourage the use of texting language as it's not universally understood. We have a common language in English and we're talking about a British company and operation in England and Wales - so really we should all stick to posts in standard English to be universally understood by our readers.

b. Please try to cut down on the number of acronyms you use - we DO have an acronym page on which I try to list them all as they come up, but at times I get my GOSW mixed up with my GOBLs - so what must it do to the newcomers? If you introduce an acronym to make your post less verbose, please define it the first time in full.

c. Whilst we don't wish to go round and round (and round and round) the same subject in a thread, remember that we are rapidly growing and that there are many newcomers here all the time - and guests, and people who find our pages via search engines. So you are encouraged to go back to basics, provide full explanations, re-open matters that we discussed a couple of months back, and should NOT assume that everyone is up to speed. Established posters - if you see a subject repeating itself in a short timescale, please help us by adding a link back to the old subject so that we can keep "churning" at acceptable levels.

In spite of the comments above, the general approach to moderation is a "lighter touch" with moderators very much looking to facilitate the use and usefulness of the board. Typically, we will NOT jump in and correct spellings nor grammatical errors, nor alter posts that we feel could have been explained better in another way - after all, it's your forum. We may point out via a personal message that a post could be understood in two different ways if we feel there could be a chance the original poster didn't realise this. As a "backstop" we (or rather I as the administrator) have a legal responsibility to act on posts that are (or may be considered) indecent, incite hatred, incite illegal actions, break copyright laws, are libelous and a whole host of other things which - thank you everyone - are very rare indeed here.

Posted by gje at 08:26 AM | Comments (0)

March 03, 2008

Java Compiler - needs all classes, compiles them all too

Remember that when you compile a java source file ...

a) You must have the classes it will use when it runs available to the compiler so that it can check (a bit frustrating at times if you're compiling on one machine but going to be running on another)

b) If you supply only java course code for some of the classes used within the class you're compiling, or have updated the sources of those used classes, Java will automatically recompile them. (this can be a bit confusing when you see an error message referring to "line 65" and don't even have a line 65 in the file you've asked to be compiled - the error being in one of the other files)

Here's an example where I compiled a "Sales" application on last week's Java Course:

Dorothy:c2 grahamellis$ ls
Period.java Product.java Sales.java Single.java
Dorothy:c2 grahamellis$ javac Sales.java
Dorothy:c2 grahamellis$ ls
Period.class Product.class Sales.class Single.class
Period.java Product.java Sales.java Single.java
Dorothy:c2 grahamellis$

See that running here

Posted by gje at 07:20 AM | Comments (0)


Useful link: Java training

March 02, 2008

Uploading to a MySQL database through PHP - examples and common questions

One of the most popular pages on the technical part of our web site relates to the uploading of images to a server from a local disc file via a browser, then storing those images on a database, and displaying them later. Another popular page relates to the same thing with .pdf file - and really the two requirements are the same technically - a piece of data that's to be treated as an indivisible block by the server - a "blob" or binary large object in database terms - is to be uploaded, stored are then returned back later.

We have two examples that I'll point you at. The first does the whole thing in one program, and is documented in our solution centre. It's here and the demonstration - in this case - uses .jpg image files. The second example has been split into three parts which makes it much easier for the newcomer to take in - an initial form, then a script to store the binary data in a database and finally a script to return something from the database. This example uses a .pdf file.

We've even provided facilities for you to try out our scripts - see here for the image uploader and there's another script to search the image database based on the picture description here. The .pdf uploader demo starts here.

You'll find a whole load of user comments on the bottom of the .jpg image script, but I still get a lot of questions relating to how it works. That's no big surprise really - the script is quite short, but it makes use of a lot of PHP and MySQL facilities that aren't covered on many courses on the subject (as this is an example from our course you can be assured we'll cover it if relevant to even one member of the group. And many of the questions are about failing uploads - again, no big surprise as in order for our script yo work, file upload needs to be configure "in" on the PHP server, a temporary directory assigned as appropriate as it probably won't be there by default on windows boxes, file permissions need to be set, a database needs to be set up and user name and passwords changed ... and if a newcomer misses any of the vital steps out it won't work.

Advise on sorting this out? I'm going to finish this article by reproducing a couple of paragraphs just written to a gent who was reporting zero length blobs in his database ...

"""The two most likely problems are that you don't have write permission set to allow for the web server to write the temporary disc files created, or that the directory in which they are to be written does not even exist. Judging by the fact that you are quoting the name of my blob field, I think you've pretty much copied the code from my site (and that's OK - that's what it's there for) but that makes it slightly less likely that it's too much of a coding error. Of course, without seeing your code / configuration details (I don't even know you're hosting server's operating system!) I can only guess in the dark!"""

"""Take it step by step - look at the temporary files to see that they're uploaded, look at the variable that hold the string to be put into the database and check that's non-zero along the way - then you'll have the process split into three pieces and will be able to find which one is the first one that's failing"""

Posted by gje at 07:28 AM | Comments (0)


Useful link: PHP training

March 01, 2008

HST Power Car TravelWatch SouthWest

Today, I had a chance to listen to Andrew Haines - CEO of First Great Western, and the man who has been given the task of turning certain aspects of the company - which is currently something of an embarrassment to the "First" brand - around. You'll find me writing more seriously about what he had to say, and my impression of where FGW are going and with particular respect to the Salisbury - Swindon service - posted in the next few days in several places (save the train and the coffeeshop). This has been what has turned out to the the third day of campaigning at the end of a busy week - a place on the platform at a public meeting on Thursday, the mayor reception where I was taking with lots of influencer's and local people on the subject on Friday, and now this today.

But I thought I would share a lighter moment with you. "TravelWatch SouthWest" - the umbrella that arranges meetings like today's where campaign group representatives get to meet up, listen to the transport providers and government, for the mutual benefit of all is lead by a charismatic, effective and knowledgeable chair - Chris Irwin - for whom I have a lot (and awful lot) of time. And he gave us a big scare at the tail end of last year - a medical emergency that put him into hospital for (I understand) more than just a short visit. Well - he was back today with the charisma, meeting control and knowledge unabated, I'm glad to say - delighted to see you if you happen across this, Chris.

And - it came as a surprise - First Great Western have name one of their newly refurbished power cars "Travel Watch South West". We were all wondering what was happening when we were asked to board a bus from the conference centre to the station ...


Andrew Haines and Chris Irwin naming "Travel Watch South West" at Taunton

Now - I have to admit - I'm a bit of a cynic about naming trains. But - in this case - I'm more than won over and feel that, yes, it was the right thing to do. It doesn't replace all the other far more important things that FGW have to do like get back the disenfranchised passengers that was on Andrew Haines's first slide - and nowhere more than Melksham, where I estimate 90% have been lost.

If I see one of these HSTs around on my travels - no doubt I'll be looking to see if it's "TWSW" - here she is at Westbury about half an hour after being named:

But (and everyone knows this) still be concentrating that much more on getting an appropriate TransWilts service running. A final picture:

And, no, that is NOT Melksham. It's the 07:50 Bradford-on-Avon to Great Malvern that two of us caught to the meeting. We would have started from Melksham, but (a) the first train scheduled on a Saturday is too late to get us to Taunton in good time (b) it goes in the wrong direction and the first southbound train isn't until mid afternoon which is when the meeting ends and (c) it is a bus anyway - so we would have taken so long we would have walked in just as Mr Haines finished talking.

We look forward to the disenfranchised becoming part of the franchise again, Andrew, and to working with you to help produce the right solution (practical, cost effective) for "TransWilts"

Posted by gje at 07:55 PM | Comments (0)