Tuesday 11 July 2017

To sessions and beyond!

Continuing down the installation and basic configuration list I've made a note to make sure that the directory permissions are set when I migrate this off the Windows box and I come down to additional configuration steps.  I'm pretty sure the last 3 blog posts will take 5 minutes the next time I do this.

For the time being I'm going to skip digging into the cache and hope that the default values are enough to get me up and running (I'm sure they are) and move directly along to the database configuration.  I will not be returning to the installation page to check out the web configuration notes since I'm already familiar with this and won't be fussing with it now, mod_rewrite works on my server and if it all breaks when I migrate I'll have a clue why.

I'm using a mySQL database for no reason other than that's what I'm most familiar with at present and I know it's well supported by my hosting company.  I know there is some debate (read: holy wars) about which is the best to use but I'm going to recuse myself from that conversation right here.  Since local database access is available on my server, I went ahead and continued to use localhost through XAMPP.  This will, of course, require a migration later from this database to the live server but that's fine.

I had previously worked up a schema and went ahead and implemented it on my host along with the reader, writer and admin accounts I wish to have.  I understand I don't need this to be complete in order to get things up and running but having prepared a design there's no reason not to put in as much as I can as I go.

Implementing the read and write connections in mySql is very simple, and the database documentation provides an example of how this is set up under the heading Read & Write Connections.  There is no documentation on how to do the different read/write sections with the .env file but looking at the existing keys I created a few like DB_READUSER and DB_WRITEUSER, passwords etc in .env and modified database.php so the end result looks something like this:
    'connections' => [
        'mysql' => [
'read' => [
'username' => env('DB_READUSER', ''),
'password' => env('DB_READPASS', ''),
],
'write' => [
'username' => env('DB_WRITEUSER', ''),
'password' => env('DB_WRITEPASS', ''),
],
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ]
    ],
 For those unfamiliar with utf8mb4_unicode_ci as I was it's an extension of utf8 to allow it to be expanded to 4 bytes for new code pages like Chinese and emoticons.  The _ci has a more correct lexicographical sorting order than then _bin version with a minor trade off in performance.

The rest of the instructions on the documentation page begin to delve into use of the database, which I'm going to gloss over for now.  On to sessions.

The first choice is which driver to use.  A little bit of research suggests that for smallish sites file or database are quite good enough solutions and a little more reading suggests file for low latency and reduced SQL traffic overhead.  I'm unlikely to run out of storage space due to the session files and I'm only running on a single server, so "file" it is.  Just a reminder that while I'm looking at my session.php I'm making most of my edits in the .env file.

Scanning the file I see the server side encrypt option is false by default, which strikes me as a little odd since of course security is a big topic.  I can see the justification here for performance ... as long as the server itself is secure then there's no worry on the session files.  I may revisit this information if I start collecting any sort of sensitive information like credit card numbers, etc, some experimentation on the performance hit will be in order.  For now it's on the "to do" list to look into this more later.

A small thought towards security, if you're particularly bent this way, is to change the session storage location from the default value.  My thought is that if the server is compromised then so are the config files, so in this case I won't bother.

The next setting I want to look at is "secure" ... I have a temptation to set this to true because my app will only communicate on https, with requests for http being redirected to https.  I see that there's an issue with setting secure "remember me" cookies.  I think I want to change this to true, but for now while I'm testing locally on http I'll leave this as false.  I'm making a note to review this decision later in the development.  With password managers and such being increasingly used in browsers I need to think about this some more.

There are clearly a lot more settings to dive into but for the moment I'm going to leave them alone.  I'm feeling sufficiently configured to actually start working on the app itself!

Monday 10 July 2017

From install to index.php with a small *Pixar Cars Character Guido": Pit Stop!

If you are at all like me then after this install all you want to do is see your site working.  Yep, from install to finished site in one sitting.  For me it takes effort to stop and resist the urge to jump forward into creating html/php files and to start looking at why I'm using a framework in the first place - to get rid of the mess of garbage files and wasted effort that plagues many of my projects in the first place.

If MVC or object oriented programming are new concepts for you then using a framework is probably going to be a fight for you.  These two concepts are really the key to making this thing save you time and effort.

When I first started writing dynamic pages a lot of what I was doing was just encapsulating html files  in a php file with a bit of dynamic stuff thrown in.  I really only wanted database access and session management and didn't use PHP to create the pages in any substantial way.  This lead to having files included that contained the header at the top or the footer at the bottom but those files were really not much more than basic HTML anyway with some variable substitution or the odd if statment.

In other words I was writing HTML with some PHP.  I think that moving to a framework requires a shift in thinking that you are writing a lot of PHP and a little HTML.  I want the program to create the pages and I want to write as little actual HTML as possible.  Rather than include a header from a file I should have that in a variable somewhere that can be included on the dynamic page.

My first nudge towards frameworks came from trying to implement security levels.  Unregistered user, registered user, moderator, administrator.  This is not rocket science here, and yet my files started becoming such a tangled mess that I knew there had to be a better way.  My first foray into frameworks was CodeIgniter.  I might still be using it today except that it doesn't seem to be as actively developed as other frameworks.  Still if you're looking for something more entry level I can highly recommend trying CodeIgniter.  It can help you understand MVC with less complexity ... after all, with great power comes great documentation reading.

So back to the project at hand.  I know what I want from my landing page since I've done a story board already on paper.  Yes, paper.  I hate flipping between screens and no matter how many monitors I have I somehow manage to fill every pixel with work that I don't want to move.  Plus paper is easy to transport to the laundry room when I have an hour and a half of sitting watching clothes get clean.  Even if I had done an electronic design I'd still be printing it, easier to mark off what is finished and what's not with a highlighter.

My basic features will involve different views based on whether the user is logged in or not, an image of the day sort of splash, a site search bar, a header and a footer.  Again, not rocket science but there's enough going on here that I need to know what my database is going to look like or at least where it lives and what the accounts associated with it are, how I'm connecting to it, how I'm managing sessions ... and of course fall backs if any of the above fails.  In the wading pool of flat HTML we've just jumped into the ocean.

Having done all this in PHP at different points in different projects I know how some of this stuff should work behind the scenes and it's exactly that approach that I want to avoid.  Most of these things have been solved so many times that it's not just reinventing the wheel, it's almost lazy NOT to use established solutions.

Instead of even starting an index.php file I turn my attention to the Laravel configuration files because ultimately the reason for using a framework is to get away from those details and be able to focus on the project.

For the most part the app.php file is well documented.  The implications of choices here are not yet clear but here's what I've done:

  • name: changed name to my website's name
  • env: apparently it can be set to local but it doesn't seem critical for developing right now so I'm leaving it alone
  • debug: I changed false to true, I want more detailed output on errors but this will have to change back later on - the first note on my deployment to do list
  • url: for now this is just http:/localhost/ but it will need to change, though since it's used with Artisan I may not need to change it for a while
  • timezone: took a little research but any PHP time zone value is acceptable here ... now that I know how to change it I question whether I should or rather if I should set it to a localized value for the user, another question for down the road
  • locale and fallback_locale: it is not clear from the localization documentation whether you can use any string you want for a locale, but my guess is yes, as long as you create the relevant language directories to match up.  You may want to use the PHP locale values in case you have to pass the local to another application.  For now I'll leave them as "en" since that's my native tongue.
  • key and cipher: at this point of things I know that the key should be set but my configuration only says 'key' => env('APP_KEY') ... An answer on Stack Overflow explains why my key should have been set on install and why it is in fact set now.  It also demonstrates to me that I shouldn't be editing \config\app.php but that I should be editing \.env  I'm leaving cipher at the default.
Now that I know I should be editing .env a quick look through at the log and log_level settings are satisfactory ... single and debug respectively.  If I need to change these in production I'll revisit them.

A nice discovery this file, I also see the opportunity to start my database configuration directly rather than elsewhere, though I do not yet see how to create different database user accounts for reading and writing.


As my posts are wont to do this is getting long.  The basic configuration seems done and the default index.php is correctly loading from /public/ as http://localhost/ and the next steps remain database connection and sessions.

Not so scary after all eh?

Installing Laravel on Windows - Tinker, Tenor ... no wait... Composer, Tinker ...

(I accidentally deleted my original posting of this attempting to fix colour issues with the theme, oops!  Thought I was just discarding a draft ... ack!)

So like many others I started reading about how to install Laravel and immediately backtracked.  What is composer?  Oh it manages packages for PHP.  My small experience in the Linux world has prepared me for the idea of a package manager.  For anyone who has been living in the Windows world and hasn't played in Linux then this little bit of weirdness helps save you time.

The simplest way I can think to explain it is like this: you've just decided to include Laravel as a module in your program.  Laravel relies on other 3rd party modules to provide things like database support, etc.  Which version of library x matches up with Laravel version y?  What happens if there's a security issue in library z and you have to figure out what version to migrate to - if you can find the right site once you're aware there's an issue?  There should be an easier way to do this - oh wait, that's a good part of what the package manager is going to help you with.  Someone maintaining Laravel changes a dependency in their configuration and magic happens and you can get the update from the command line without having any idea what the change was about, unless you want to know more.

Step 1 is to install PHP to your local machine.  I couldn't think of a good reason not to install PHP7 since this is a new project and has no legacy considerations so that's what I did by following the instructions at Dac Chartrand's blog.  I chose the zip file and simply extracted it into C:\PHP7 since this machine isn't a live server for anything.

Dac's instructions aren't specialized to include information about configuration of PHP for use with Laravel but they were more than good enough to get up and running with PHP and composer.

The section I'm going to expand on here is where Dac writes "Scroll down to the DLL extensions section and uncomment the extensions you want to use". The first thought I have is "how do I know what I want to use?" given my seconds of experience doing this. No sweat, don't uncomment any, finish his install and return to the php.ini file after you've confirmed things are working.

When you move along to installing composer you'll have to make an edit to your php.ini. I followed his updated and externally linked instructions for downloading composer and I hit a snag...

C:\PHP7>php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 
PHP Warning:  copy(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP? in Command line code on line 1

In order to resolve this you need to uncomment one of those extensions we ignored, specifically uncomment the line that reads extension=php_openssl.dll.  If the php package changes somewhere down the line I'm sure a quick google will return the appropriate Stack Overflow answer for you.  Once I did this the rest of the steps worked like a charm.

Step 2 involves returning to the Laravel installation documentation and reading the server requirements.  PHP version is high enough and we just enabled OpenSSL.  PDO, Mbstring are also already in your php.ini for windows, so if you're doing this naively without being aware of what these things are doing, you can simply uncomment the following lines:

  • extension=php_mbstring.dll
  • extension=php_pdo_firebird.dll
  • extension=php_pdo_mysql.dll
  • extension=php_pdo_oci.dll
  • extension=php_pdo_odbc.dll
  • extension=php_pdo_pgsql.dll
  • extension=php_pdo_sqlite.dll

Here lies snag #2.  When I ran the install command line for Laravel's installer I got the following warnings:

C:\PHP7>composer global require "laravel/installer"
Warning: PHP Startup: Unable to load dynamic library 'ext\php_pdo_firebird.dll' - The specified module could not be found.
PHP Warning:  PHP Startup: Unable to load dynamic library 'ext\php_pdo_oci.dll' - The specified module could not be found.

Of course this is another wtf moment right?  I just downloaded the package from php.net how can it not be complete?  The files are even in the directory!?!

Before I explain how to get rid of the warning let's look at what these things are.  PDO means PHP Data Object ... yay, tells me nothing, next?  PDO is used here to encapsulate the database technology and provide you with a standard PHP interface so that you don't have to deal with the database server at the technology level - that is, you should be able to write a php command to execute a query and have it work regardless of whether you've chosen mySQL, sqLite, or a number of other database technologies - or even more to the point, if you change database technology down the line you don't have to rewrite your website.  THAT is what this section is about.  If you know which technology you will work with you can PROBABLY comment out the other PDO lines and live life with no further worries until you need to use one of the others.  If you KNOW you're using mysql then you probably only need to uncomment that line.  There may be some hidden gotcha down the line, but at my current level of understanding I'm not aware of any.  As another side note, if you leave them uncommented then I believe most Linux php installations will support those extensions without the need for the following fixes but we'll deal with the linux php.ini when we get there.  Remember this is strictly about getting this thing working on Windows.

Ok, so maybe you just want to fix the errors anyways ... which is what I initially did because I wasn't thinking about what I was doing.  I just wanted the warnings to go away and was not confident I could comment the extensions back out.

The answer is that you need fbclient.dll which can be obtained from firebirdsql.org. I downloaded the Win32 zip file and extracted the dll to my PHP7 directory and the first warning died. To kill the second you need to obtain files from Oracle which can be found at Orcale's site, search for "Enabling the PHP OCI8 Extension on Windows". I'm going to move forward with the Stack Overflow advice - I don't plan on using Oracle databases so I'm going to comment the line back out. I'm also going to guess I could have commented out the Firebird line and lived a happy life. This is all about database access and I think I'm only going to need mysql and sqlite access for this project but ... live and learn.

So just Tokenizer and XML PHP extensions left to go. According to NuSphere Tokenizer and XML are now built into the Windows version so let's see what happens from here.

Rerunning the composer command line completes after installing some packages.

Ok so the next step says
Make sure to place the $HOME directory (or the equivalent directory for your OS) in your $PATH so the laravel executable can be located by your system.
I never gave it a path name so where is it right?  The installer ended up in my Users\username\AppData\Roaming\Composer\vendor\laravel\installer directory.  If you can't find it try dir /s \laravel*  and it should turn up.

Change into that directory and issue the command php laravel new project-name ... my experience was that it ignored path names so just move the folder after the install completes.

In hindsight using the composer create-project method probably would have been easier but hey, reading documentation that looks like step by step instructions top to bottom never leads anyone astray right? :-)

This got me up and running enough to follow the remaining steps easily enough.  If you want to work more easily I suggest adding XAMPP or something similar to your new installation.  For a very useful XAMPP tip under Windows 10 see how to free up port 80 for Apache on Stack Overflow.

Saturday 8 July 2017

So you want to use a framework?

Ahh there's nothing quite like putting fingertips to the keyboard on a new project, especially when you've been pouring over planning documents and fleshing out ideas for a while.

My experience with "from scratch" website development is limited.  I've made a number of functional projects but nothing worth writing home about.  I've been through the homebrew mess of getting a dynamic site up and running and even played around with CodeIgniter in the past in an effort to migrate away from trivial development.  When I started my research into frameworks the message I heard was "use Laravel".  I'm not an expert and besides I'm uninterested in debating the finer points on whether that advice is fantastic or not but I've decided that I will take the advice, come what may.  If nothing else, then as so many other projects, I'll get experience in a popular technology.

For years my development host of choice has been GoDaddy.  For those of you who have finished rolling your eyes, it's cheap and relatively reliable.  When I tried to get Laravel installed there however, the problems began.  The TL;DR version is that I chose to install everything to my Windows 10 machine and upload it to the server whole rather than try to force the GoDaddy server to let me install Laravel directly.

For some of you who found this post hoping for insight on how to get the job done on the server -- don't.  First I migrated from my old Linux hosting package to the new one to get the support of PHP7 as the old servers cap out somewhere in version 5, if you're lucky.  This was a nontrivial bit of work and involved moving a networked WordPress site, phpBB installation and so on.  Surprisingly my own code dragged and dropped over rather seamlessly.

I then discovered that you cannot get a straight answer on what version of PHP is actually installed because your ssh connection to the server runs on a different server than the one that hosts your page.  In other words your phpinfo.php page and your php -v outputs can differ completely.  The web page server will run PHP7 but there's no guarantee your back end will.  At some point you'll get stopped by needing some sort of access that you simply won't get and then you'll be where I am: change hosts or install locally and migrate.

Ok ok ok.  So that's where we've been in this adventure to try out Laravel.  As with any project like this that is not a work project I find that the ones I am most familiar with get done first and the ones that have some uncertainty or insecurity about the technology get pushed off longest.  Tonight I bit the bullet and started down the path to getting this actually working.

I've started this blog because I'm sure some other developers have been through some of these headaches and if this becomes nothing more than a collection of "how to" pages, so be it.  Hopefully I'll have something more interesting to say as we go along.  I didn't want to get tied down in setting up a WordPress site for this project so I'm using the simplest thing that came to hand.  Tonight's goal is to get the first Laravel test project fired up, not to go through pages of templates looking for a slick site :-)

... and away we go...