Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

June 26, 2015

JavaScript HighCharts in Laravel 5 via Blade

Laravel 5's Blade templating engine is awesome. It can be used to directly inject PHP variables into a HTML5 template to display Eloquent ActiveRecord entities right away to the client. Besides this obvious intended use, escaping those variables can be powerful, as we will see.

HighCharts is a JavaScript library that can be used to display beautiful visualizations of sets of data. If you're here and reading this, you are probably looking for a way to integrate your Laravel PHP app with this JS library.

I started by checking out some HighCharts PHP ports on Packagist, but at the time of this writing, the few such packages have either gone unmaintained into obsolescence, or are overkill for what can be elegantly accomplished with a few lines of code. The trick here is to take advantage of Blade template escaping.

Let's look at the official HighCharts example, as given in its native JavaScript + jQuery:


$(function () { 
    $('#container').highcharts({
        chart: {
            type: 'bar'
        },
        title: {
            text: 'Fruit Consumption'
        },
        xAxis: {
            categories: ['Apples', 'Bananas', 'Oranges']
        },
        yAxis: {
            title: {
                text: 'Fruit eaten'
            }
        },
        series: [{
            name: 'Jane',
            data: [1, 0, 4]
        }, {
            name: 'John',
            data: [5, 7, 3]
        }]
    });
});

The following HTML snippet with the above JS in an HTML page will display a simple chart:


<div id="container" style="width:100%; height:400px;"></div>

That's cool and all, but that's a lot of JS for a PHP app, and it doesn't solve actually getting the database variables to HighCharts, unless we feel like resorting to some funky AJAX hackery... Fear not, there is a better way. Let's start by reconstructing the JSON config structure from the JS HighCharts into a PHP array. Create a controller, say DashboardController and make this method:


public function index() {

    $yourFirstChart["chart"] = array("type" => "bar");
    $yourFirstChart["title"] = array("text" => "Fruit Consumption");
    $yourFirstChart["xAxis"] = array("categories" => ['Apples', 'Bananas', 'Oranges']);
    $yourFirstChart["yAxis"] = array("title" => array("text" => "Fruit eaten"));

    $yourFirstChart["series"] = [
        array("name" => "Jane", "data" => [1,0,4]),
        array("name" => "John", "data" => [5,7,3])
    ];
    return view('finances.dashboard', compact('yourFirstChart'));
}

Now add the route to routes.php:

Route::get('dashboard', 'DashboardController@index');

And finally, create the dashboard.blade.php view itself. Note that you will also need the actual highcharts.js and jQuery libraries (or the stand-alone framework if you don't want to use jQuery!) - in my case they are simply declared in the parent view which is why they aren't included in the dashboard child view below. Anyways, we are now JSON encoding the $yourFirstChart array as passed in from the controller, and escaping the whole thing:


@extends('app')

@section('content')
<div id="container" style="width:100%; height:400px;"></div>
<script type="text/javascript" src="{{ asset('js/highcharts.js') }}"></script>

<script type="text/javascript">
    $(function () {
        $('#container').highcharts(
            {!! json_encode($yourFirstChart) !!}
        );
    })
</script>
@endsection

Your IDE probably won't like the syntax mixture very much, but it will inject a completely valid JSON into the <script>. And the best part is that the JSON is generated from a PHP array that can receive all the usual Eloquent database objects, thus completing the missing data link between HighCharts and Laravel. If all went well you should see the example chart in all its interactive glory like below - go ahead and click the items in the legend!



May 8, 2015

Laravel 5 Eloquent Models & Tinker Tips

Eloquent is Laravel's implementation of ActiveRecord, seen in other programming languages too, like Ruby. It insulates you from the need to use hard SQL queries in your code. Each new ActiveRecord is basically one line of a database table, containing all the columns as object attributes wrapped in a PHP model class. Creating an Eloquent Model is easy:

php artisan make:model Transaction

This creates a PHP class at app/Transaction.php which can be filled with attributes specific to that object model. Another cool thing, is that Laravel will also create a database migration for it; pretty useful since you are likely going to store this object somewhere. Now that we have a model, we can use Tinker to demonstrate how ActiveRecord queries the database.


Assigning Values


Run php artisan tinker from the command line, and let's play around with objects to manipulate our database. Values can be assigned to attributes like so:

$transaction = new App\Transaction
$transaction->debit = '3.33';
$transaction->description = 'cup of coffee';
$transaction->date = Carbon\Carbon::now();
// object is getting filled up, but not yet persisted to the database:
$transaction->save();

This is roughly equal to the MySQL command:
INSERT INTO transactions (debit, description, date) 
   VALUES ('3.33','cup of coffee', NOW());


Looking Up Values


Now that the object has been persisted back to the database, we can verify the added record by looking directly in the database, by doing something like this in MySQL:
GET * FROM transactions;

More elegantly, we can do one of several ActiveRecord queries via Tinker like so:

App\Transaction::all()->toArray();

// or find via database ID key:
$transaction = App\Transaction::find(1);

// or find by column; this returns a Laravel Collection:
$transaction = App\Transaction::where('debit', '3.33')->get();

// or return only the first result as a class object instead:
$transaction = App\Transaction::where('debit', '3.33')->first();


Mass-Assigning Values


Assigning individual values can be tedious and time-consuming. We can mass-assign values to a database row by passing an array like:

App\Transaction::create([
   'debit' => '3.33',
   'description' => 'cup of coffee'
   'date' => Carbon\Carbon::now()
]);

The ability to mass-assign values like this, requires a safeguard to protect us against exploiters using fake fields to inject data via a form. We can build a safeguard by explicitly adding an accepted array of values that are permitted to be filled via mass-assignment. The app/Transaction.php model could look something like this:

class Transaction extends Model {
   protected $fillable = [
      'debit',
      'description',
      'date',
      'credit',
      'total',
      'account'
   ];
}

Mass Assignment will now work for any combination of fillable fields.


Mass-Updating Values


The mass-assign ::create() method above is directly enacted upon an Eloquent class. To update a database record, first create an Eloquent object, then use the ->update() method on it, passing an array of values:

App\Transaction::create(['description'=>'cheap coffee', 'debit'=>'3.33']);
$tn = App\Transaction::where('description', 'cheap coffee')->first();
$tn->update(["debit" => "2.22"]);

The ->update() method will automatically save to the database!

April 28, 2015

Laravel 5 Database Migrations - The Basics

Migrations are a way to "version control" a database. There are ways to "seed" data into a database, but migrations are more concerning the schema. Previously, to set up a database, a lot of manual setup needed to be done; create a table, add some columns, set their keys, etc etc. And if the database corrupted, or got blown away, or you needed to set it up on another server or share with someone else, there would probably be a bit of manual setup again, despite potential sqldumps and schema exports.

Migrations are a neat way to get around a lot of this manual setup via PHP classes. Basically, a migration is a PHP class that represents the instructions telling the database what needs to happen during setup. Laravel has an easy way to create migrations of various types; depending on what flags are used, a new PHP class with some relevant boilerplate code will be set up. For example:

php artisan make:migration create_cool_table --create="cool"

The migration file will get created and stored in the database/migrations folder as create_cool_table.php. Note the up() and down() methods within it. The former is to implement a change to the database, and the latter is to undo it via a rollback. These two methods should be exact opposites in what they accomplish.

Actually implement a migration - the up() method:
php artisan migrate

Undo the most recent migration - the down() method:
php artisan migrate:rollback

If a rollback fails, it is likely because of a missing database package. Add it:
composer require doctrine/dbal

The Laravel framework uses the migrations table in the database to keep track of which migrations were already run in the past. A migration will never be run again, unless you roll it back, as above, to make changes to it.

Caveat: If a migration has already been run on a Production server, or a friend/co-worker's machine, it is probably better to just create a fresh migration to make further changes, instead of rolling back the migrated migration, changing it, and re-migrating it. To make a change to an existing table, we are still creating a new migration, but can use different flags to set up useful boilerplate for this case:
php artisan make:migration modify_cool_table --table="cool"

As a general rule-of-thumb, it is always easier to just migrate new stuff, than to first un-migrate some stuff, then pull in the updates, then re-migrating... Keep things sequential!

March 19, 2015

Laravel 5 Environment setup

The .env file is a non-version-controlled file that can contain sensitive information such as settings and passwords. Laravel 5 comes with a .env.example file to get things started.

The way you use environment variables is by declaring them in the .env file, and then invoking them as such:
'key' => env('VALUE', 'default')
'host' => env('DB_HOST', 'localhost')

Additionally, further configuration can be set in files in the config folder. For example, all the database connection information is set up in the config/databases.php file. Everything in that folder is used to that extent, so be sure to have a peek there if you install any useful packages into your app.

Laravel error pages also change what they display based on the environment. For example, the APP_ENV variable in the .env file controls how your app interacts with the browser. If set to APP_ENV = local, there will be much more verbose error pages (useful to a developer), as opposed to APP_ENV = production, which will show only the more user-friendly "Whoops, looks like something went wrong." message! Pretty useful stuff.

February 20, 2015

The Laravel 5 Vagrant box: Homestead 2.0

It is possible that if you followed along with the last post, you might get some errors in starting up a Laravel 5 project. The error might depend on several factors such as OS or previous package dependencies, and manual intervention is probably required. This is why a virtual machine is a great way to manage development environments, particularly via Vagrant.

Homestead is Laravel's officially pre-packaged Vagrant box that is already set up with everything needed to run a Laravel project.

Virtual Machine setup


Install Vagrant
Install Virtualbox
Add the Homestead Virtualbox:
vagrant box add laravel/homestead

Homestead source files setup


Now, from here there are two ways of getting a box running. There is no need to do both.

I prefer cloning the Github repository, which is also the officially documented way at the time of this writing for Laravel 5.0. My reason is that if you "dirty" your Homestead repository, it really doesn't take a lot of effort to just remove the dirty/broken/outdated Homestead VM, reclone it afresh, and reimport your settings file. We will just clone the Github repo:


git clone https://github.com/laravel/homestead.git Homestead
cd Homestead
bash init.sh

This will create a Homestead.yaml file, placed in your ~/.homestead directory. This settings file can easily be re-initialized by running the init.sh script again, as above.

The alternate way is using Composer to globally install Homestead. This was previously the officially documented approach, at least back during Laravel 4.2. I am not sure I like this approach, but there are articles out there evangelizing the merits of doing this. I would rather modularize my development environments as done the first way, instead of globally invoking Homestead anywhere in my system (how often do you really need to create a new Laravel box, when a single box can capably manage all of your local Laravel projects? Capriciously, running homestead up is annoying when vagrant up is already so ingrained!):


composer global require "laravel/homestead=~2.0"
homestead init

This will create a Homestead.yaml file, placed in your ~/.homestead directory.

SSH key setup


The ~/.homestead/Homestead.yaml file already sets a sane default location for your SSH key; if yours is different then update it. See here to create a key from scratch if it doesn't yet exist.

Shared folders/sites setup


In the ~/.homestead/Homestead.yaml file, map out the path you want access to in your Homestead VM. I keep all my projects and VMs (including this Homestead VM) in a Projects folder, so let's update the `folders` variable using relative paths, and also the sites (of which you can have as many as you want) with the specific Laravel projects you want to access:


folders:
    - map: ../../Projects
      to: /home/vagrant/Projects

sites:
    - map: mylaravel5project.dev
      to: /home/vagrant/Projects/mylaravel5project/public

Hosts file setup


If you want to access your project in the browser with a pretty name instead of Homestead's default IP, http://192.168.10.10/, be sure to define some hosts for easier access.

Alias setup


To add Bash aliases to your Homestead box, simply add to the aliases file in the root of the ~/.homestead directory.

Create a Laravel Project


composer create-project laravel/laravel projectname

Launch!


Simply run:
vagrant up
To destroy the VM and start fresh, run:
vagrant destroy --force
To SSH into Homestead when it is running, from the Homestead cloned directory, run:
vagrant ssh

Now we are set to visit http://192.168.10.10/ and will see the first mapped Laravel project's main page. If several apps were specified in the Homestead.yaml file's sites, and hosts file definitions were set for all of them, you can access each of them individually via those mapped URLs (i.e. mylaravel5project.dev). Enjoy!

February 17, 2015

Getting started with Laravel 5 and Composer: Initializing a new project

Laravel 4 had largely changed the way that PHP development happens. It saw the addition of package management through Composer, an overhaul of pagination routes, and some of the best "out-of-the-box" security seen in any PHP framework. The level of care and attention to detail made using Laravel 4.2 a ton of fun.

Laravel 5 changes things again. It was supposed to be a simple upgrade to 4.3, but a slew of new features were enough to call for a new major release. There were changes made to the directory structure, blade templates allow for escaped variables, facades are taking a front row seat, routing receive the addition of middleware, and Artisan has tons of new generators. I plan on covering some of these new feature in upcoming posts.

For this post, however, how does one even get started? Well, let's set up a basic Laravel 5 PHP project from scratch.

Install Composer

Composer configures packages from Packagist. Add a package like so:
composer require "vendor/package": "version@branch"

Package dependencies are automatically included and installed as listed in the composer.lock file. These are installed into the {project root}/vendor folder.

Install Laravel 5 with Composer


composer create-project laravel/laravel mylaravel5project

Boot up Laravel 5 homepage


Can be done with PHP's built-in webserver, document root set to the Laravel project's public folder:

cd mylaravel5project
php -S localhost:8888 -t public

Now open http://localhost:8888 in your browser. If this doesn't work, it is likely a PHP5-mcrypt dependency that's missing, so be sure to add that. Alternatively, use a virtual machine such as Homestead.

February 7, 2015

Installing PHP Composer globally on Windows

Composer is a dependency manager for PHP. PEAR used to be the go-to tool for managing PHP dependencies quite some time ago, but it was always cumbersome, and not much fun to use. Composer makes it very easy!

On Windows, you can use the .exe installer; note you will need PHP installed, and have the php.exe accessible. In this particular case, I will be using Cygwin shell, and have already installed PHP as a Cygwin package for it:


When installation is done, close and reopen your terminal:


You can now run the composer command from anywhere in your shell.

composer
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.0-dev

Installing PHP Composer globally on Mac & Linux

Composer is a dependency manager for PHP. PEAR used to be the go-to tool for managing PHP dependencies quite some time ago, but it was always cumbersome, and not much fun to use. Composer makes it very easy!

Installing Composer is easy on Mac or Linux:
curl -sS https://getcomposer.org/installer | php

If you want to run it globally, simply move and rename the downloaded .phar file:
mv composer.phar /usr/local/bin/composer

It might even be possible to set it all up in a single command, though I cannot test it right now:
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

You can now run the composer command from anywhere in your shell.

composer
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.0-dev

October 29, 2014

First introduction into Laravel 4 PHP Homestead, getting started from scratch

Update: This post is now deprecated with the release of Homestead 2.0, which runs Laravel 5. A new post is here, and this one will be kept for historical reference.



I've been enjoying using the Laravel PHP framework over the past year or so, but I always found myself referring back to documentation when I start up a new local project. There are always changed dependencies, and lots of other miscellaneous changes, and I would need to update my Vagrantfile and provisioner software accordingly. This Laravel-Vagrant blog post by culttt was a staple of information for me for a long time, but as of the time of this posting, has been deprecated for a while. Luckily for us, there is a new kid on the block, and this one is officially supported and documented!

Enter Homestead, a pre-packaged Vagrant box with all the dependencies provisioned for, to run a new Laravel project. This was a breeze to get going even on my Windows machine (and I prefer using Cygwin with a Console2 shell as well, which usually requires extra effort finding dependencies than Ubuntu's apt-get or OSX's homebrew), and everything simply worked. Just be sure to have the latest version of Vagrant and Virtualbox installed on your computer!

Let's add the Homestead Virtualbox:

vagrant box add laravel/homestead

If you have an older version of Vagrant, you will likely get the error below:

This command was not invoked properly. The help for this command is
available below.

Usage: vagrant box add <name> <url> [--provider provider] [-h]

        --checksum VALUE             Checksum
        --checksum-type VALUE        Checksum type
    -c, --clean                      Remove old temporary download if it exists.
    -f, --force                      Overwrite an existing box if it exists.
        --insecure                   If set, SSL certs will not be validated.
        --cacert certfile            CA certificate
        --cert certfile              The client SSL cert
        --provider provider          The provider that backs the box.
    -h, --help                       Print this help

To fix it, I simply upgraded from the failing version 1.4.3, to the most up-to-date version 1.6.3 as of this writing. Just download the newest installer for Vagrant and set it up, else via Unix command line set it up for a global install as below (substituting for whatever version is most current for you), and then re-run the box add command from before:

wget https://dl.bintray.com/mitchellh/vagrant/vagrant_1.6.3_x86_64.deb
sudo dpkg -i vagrant_1.6.3_x86_64.deb

Continue by cloning the official Homestead repository into your folder of choice:

git clone https://github.com/laravel/homestead.git Homestead

Now, in the Homestead.yaml file, you need to set your SSH key info. Chances are, if you've ever used SSH everything is already good to go (it comes with some sane defaults), but if not, check out the documentation on how to do that. Folder mapping is assigned to nginx here as well. If you already have a Laravel project you wish to use, you can just tweak the default folders map, as cloned from the repo, but since I am starting from scratch, I had to do this:

folders:
    - map: ../Homestead
      to: /home/vagrant/Homestead
sites:
    - map: homestead.app
      to: /home/vagrant/Homestead/laravelAuth/public

I'll be making a new Laravel authentication app once this is all set up, so I'm gonna call my project laravelAuth, and preemptively set up the public sites map for it, as done above. Note that you can map several different apps in this development environment.

From here, it is simply vagrant up, and in a short while, you'll have a working Laravel dev environment! In the Homestead.yaml file, our box's ip address is set as 192.168.10.10 by default, so opening http://192.168.10.10/ in your browser should yield... an error? "No input file specified." ...what?

That is because we haven't actually created our Laravel project, so there is nothing for this development environment to show yet! This is easily remedied by entering your box via vagrant ssh, and running:

cd /vagrant
composer create-project laravel/laravel laravelAuth --prefer-dist

Reload your page, and now you have arrived at a brand spanking new Laravel home page. Code away!

June 9, 2014

PHP Composer: Adding new required package to the lock file

Composer's lock file is a great way to keep your project's packages locked to a specific tested/working version. If it wasn't there, your project's dependencies would receive the latest package versions every time you spool up your dev environment, or whatever you are currently deploying your project to. Therefore, the command composer install is your friend, and will only install the versions specified in the lock file - which, I would argue, is a good thing to version control if you are working in a team to ensure everyone is using the same packages and dependencies. composer update is a nasty command to run on a regular basis - it bypasses your lock, updates the lock file, and specifically updates all packages in the project to their latest version. This would likely require a round of testing to make sure nothing broke.

So how do you add a new package to the lock file without running a project-wide composer update - i.e. without updating the other packages? From the command line:

composer require "phpoffice/phpexcel":"1.8.*"
composer update --lock

This adds the new package require to the composer.json. Running the update --lock command after that will literally only add the new package info to the composer.lock file.