Stuff I'm Up To

Technical Ramblings

Laravel storage/logs Error — July 19, 2018

Laravel storage/logs Error

A regular issue for me is failing the initial deployment of a git clone Laravel server using Nginx. It’s almost always because I forget to create and give permissions to the Nginx user www-data.

UnexpectedValueException
There is no existing directory at "/var/www/myproject/storage/logs" and its not buildable: Permission denied
Then even if I do sort the permissions here it fails again with:
InvalidArgumentException
Please provide a valid cache path.
This is because the storage/framework path and subfolders don’t exist. You need to create folders and make sure the www-data user has read/write/create permissions:
$ mkdir -p storage/framework/cache
$ mkdir -p storage/framework/sessions
$ mkdir -p storage/framework/views
$ sudo chgrp www-data storage -R
$ sudo chmod g+rwx storage -R
Advertisements
Building a Debian Development Server — July 13, 2018

Building a Debian Development Server

When I setup a development system there are a few steps I follow to get everything working together.

The aim is to get everything installed to provide php and composer, node, nginx, mysql and Laravel as a base to build on.

Install Debian

I take the latest amd64 version using a network installable iso. This way if I use an older 9.1, 9.2, 9.3 version iso, being a netinst version I’ll end up with the latest in that series as it downloads from the net.

Mostly making a 50GB disk is more than enough, as it’s thin provisioned on a virtual, space isn’t really a concern. When it comes to partitioning I’ve learned to take the easy option and create one partition to mount all filesystems into it.

Capture1

As it’s a development platform I never install a desktop environment. I never need to use any GUI programs on the server. The only options I choose to install are the standard system utilities and the ssh server.

Capture2

Out of personal preference, once up and running I install sudo, zsh, curl and git.

# apt-get install sudo zsh curl git

Then I add my non-root user to the sudo group so I can stop using root and use my regular user account to ssh onto the dev server..

# usermod -aG sudo [user]

Setup OhMyZsh

I like using zsh and the OhMyZsh which is why I installed curl and git. So logon as your non-root user.

$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

Then I edit the ~/.zshrc file and change the theme to “bureau”.

Network Config

If I’m building a Virtual Box guest that runs on my local PC I’ll setup two interfaces. If it’s a virtual on VMWare I’ll just use the one production interface.

On a local Virtual Box I use one interface as NAT, so it gets a DHCP address like 10.0.2.15 which all outgoing traffic is routed by default. Makes life easier on a corporate network where network authentication is required. Using NAT like this means I don’t need to authenticate my guest as it NAT via my physical hosts authenticated interface.

I then setup second interface so I can connect to what is being served from the guest. This is a “host only” interface and means only my local system can connect to it, but because of the NAT the guest will still have access to the corporate network resources/servers.

This means I end up with two devices usually named enp0s3 (NAT) and enp0s8 (Host Only) on Debian.

Using a Static IP (optional)

I choose to make my system with a static IP. Using the Virtual Box DHCP server on a “host only” interface gives out a 192.168.56.101 address to the first guest, 102 to the second and so on. But you can end up with inconsistent IP’s for your hosts. So making them static is a better option IMO.

Edit /etc/network/interfaces and set you host only adapter to static:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo

iface lo inet loopback

# The primary network interface
allow-hotplug enp0s3
iface enp0s3 inet dhcp

allow-hotplug enp0s8
iface enp0s8 inet static
  address 192.168.56.2
  netmask 255.255.255.0

This way My dev system always gets the static IP I chose for it.

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
  link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
  inet6 ::1/128 scope host 
    valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  link/ether 08:00:27:61:a6:a8 brd ff:ff:ff:ff:ff:ff
  inet 10.0.2.15/24 brd 10.0.2.255 scope global enp0s3
    valid_lft forever preferred_lft forever
  inet6 fe80::a00:27ff:fe61:a6a8/64 scope link 
    valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
  link/ether 08:00:27:2b:04:26 brd ff:ff:ff:ff:ff:ff
  inet 192.168.56.2/24 brd 192.168.56.255 scope global enp0s8
    valid_lft forever preferred_lft forever
  inet6 fe80::a00:27ff:fe2b:426/64 scope link 
    valid_lft forever preferred_lft forever

Install PHP

Because we don’t want Apache2 installed you need to install php-fpm which won’t force an install of Apache.

$ sudo apt-get install php-fpm

It will include a load of other php components you need, but no Apache, so you can then choose to move on to Nginx or some other php service.

Add the Laravel php requirements

$ sudo apt-get install php-mbstring php-zip php-xml libpng-dev make gcc g++

The additional module libpng-dev is required for Laravel to build using NodeJS npm. Without libpng-dev, make, gcc and g++, under your Laravel project folder the call to $ npm i fails with errors like:

> pngquant-bin@4.0.0 postinstall /home/user/myproject/node_modules/pngquant-bin
> node lib/install.js
⚠ The `/home/user/myproject/node_modules/pngquant-bin/vendor/pngquant` binary doesn't seem to work correctly
⚠ pngquant pre-build test failed
ℹ compiling from source
✔ pngquant pre-build test passed successfully
✖ Error: pngquant failed to build, make sure that libpng-dev is installed
at Promise.all.then.arr (/home/user/myproject/node_modules/pngquant-bin/node_modules/bin-build/node_modules/execa/index.js:231:11)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)

Install MySQL

As you’ll need a database you’ll want to install MySQL. These days MySQL is installed from the MySQL site by downloading a .deb file which add the Oracle repositories. The version of MySQL in the Debian repositories is MariaDB, a fork of MySQL.

If you go for the Oracle version  you’ll probably need to ensure you use legacy authentication for now.

Include the php drivers as we install the server:

$ sudo apt-get install mysql-server php-mysql

To manage MariaDB using mysql you need to use sudo:

$ sudo mysql -u root
...
MariaDB [(none)]>

Install Composer

Go to your home folder and use the command line install from here: https://getcomposer.org/download/

You’ll end up with a file composer.phar. This is ok if you’re the only one going to use it but I like to put it in /usr/bin as just composer so it is available for everyone.

$ sudo cp ~/composer.phar /usr/bin/composer
$ sudo chmod 755 /usr/bin/composer

Install NodeJS

Install it using a package manager following the steps for Debian

https://nodejs.org/en/download/package-manager/

$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt-get install -y nodejs

Then the first thing I do is update npm.

$ sudo npm i npm -g

Install Samba

Because not all development takes place on a Linux host this will allow us access to shares for Windows clients.

$ sudo install samba

Edit /etc/samba/smb.conf and make some simple changes.

workgroup=[NETBIOS DOMAIN NAME]

Then find [homes] and in that section change:

read only = no
create mask = 640
directory mask = 750

Create a password entry for your non-root user:

$ sudo smbpasswd -a [user]

Then restart Samba

$ sudo systemctl restart smbd

Then when you browse to the server from windows you should see and have access to your home folder eg. \\192.168.56.2\user

Installing Laravel

I prefer to install Laravel as a project using the Create Project method:

$ composer create-project --prefer-dist laravel/laravel [myproject]

This downloads all of the PHP composer prerequisites and delivers the project.

Once the project is created you can go into the folder [myproject] and check you can compile the assets using Node.

$ cd myproject
$ npm i

This will install all of the NodeJS prerequisites used for building/compiling your assets using the Laravel asset management tools – currently Laravel Mix (Based on Webpack). So with the Node modules installed you should be able to run prod and dev builds:

$ npm run dev
$ npm run prod

These should complete successfully.

You can then run Laravel’s built in development server to serve your project:

$ php artisan serve

But in reality this will fire up a pretty useless server listening on the IP address 127.0.0.1 on port 8000. So it’s only accessible from the development server.

As we’re going to need to access it from our client development machine we need to serve on the actual IP of the server. The easiest way of doing this is to serve it on every IPv4 interface on the server (you probably only have one, so it shouldn’t matter). To do this use:

$ php artisan serve --host=0.0.0.0

and if you want to specify the port you can use:

$ php artisan serve --host=0.0.0.0 --port=8001

Now you can access it from any client pointing your browser at http://192.168.56.2:8001 and begin exploring your Laravel project.

More Laravel

Of course serving a version of your project like this isn’t the only way to go. You should continue into dynamically building your assets using npm run watch and maybe even using tools like browserify to make changes happen at the browser end so you’re not building and refreshing all the time.

I also like to move away from a development web server and setup Nginx to handle serving my Laravel Project.

Further Reading

https://warlord0blog.wordpress.com/2017/03/01/ssh-logon-with-private-key/

https://warlord0blog.wordpress.com/2018/05/16/debian-stretch-ntp-time-sync/

https://warlord0blog.wordpress.com/2017/12/12/php7-0-microsoft-sql-driver-debian-stretch/

https://warlord0blog.wordpress.com/2017/03/01/installing-updating-webmin/

 

 

Composer Require Specific Branch — June 4, 2018

Composer Require Specific Branch

I’m trying to test out a version of a SAML project that doesn’t include the now defunct php extension for mcrypt. Using composer require kept on grabbing the master branch, when I actually wanted the “remove_mcrypt” branch.

I found that using composer with the branch like this failed:

$ composer require "aacotroneo/laravel-saml2":"remove_mcrypt"

[UnexpectedValueException]
Could not parse version constraint remove_mcrypt: Invalid version string “remove_mcrypt”

Thanks to a stackoverflow post: https://stackoverflow.com/questions/33525885/composer-require-branch-name I was able to resolve it by correctly prefixing the branch with “dev-

$ composer require "aacotroneo/laravel-saml2":"dev-remove_mcrypt"
Application Construction — April 4, 2018

Application Construction

Frameworks

For rapid application development there’s a lot of pre-written code out there that is mature and highly capable. There’s no need to build from the ground up when you can use a framework or scaffolding to build your application.

Laravel and Composer

My first step is to use Laravel. It’s installed using composer – which is a dependency manager for PHP. This means if a PHP component you install needs and relies upon other components, they’ll get installed too.

Composer installs all the PHP dependencies under ./vendor path of your project. The files in this path do not need to be included in your distribution. They can be installed and updated automatically using composer.

Composer keeps track of what you install into your project in the file composer.json. So whenever you run $ composer update it will read this file and pull down all the dependencies and install them into ./vendor.

Node.js and NPM

Whilst I may not be developing a Node application I can certainly make use of Node for the development process. It offers some very beneficial development features. It runs webpack to monitor and compile the projects assets and browsersync to refresh my browser when an asset is updated.

NPM is the package management tool that downloads and installs the Node packages required. In the same way as composer installs dependencies for PHP, NPM does this for Node/JavaScript.

NPM uses the file package.json to monitor/manage the dependencies you install, which get installed into ./node_modules. Again this does not need to be included in your distribution as the content you require gets compiled into your JavaScript assets. So you may not even require Node installing on your production server environment.

Webpack

As part of the Laravel install you’ll get a flavour of Webpack, or mix as Laravel terms their adaption.

Webpack carries out the monitoring and compilation of assets. It takes your JavaScript and CSS/SASS files and uglifies/compresses them into smaller code only versions of your scripts. It can take a JavaScript file from 2MB of code down to less than 200kb. Simplistically it does this by stripping all of the “English” from it and shrinking your long variable and function names to what are often single character variable and function names. Removing spaces, tabs and carriage returns etc.

eg.

var my_variable_name = 1;

becomes

var a=1;

Once the code is delivered to the browser in a production environment there is no need for the code to be human readable anymore.

The primary input for webpack comes from the assets ./resources/assets/js/app.js and bootstrap.js (not to be confused with the bootstrap framework). These two files are the core of your JavaScript application.

Webpack compiles your assets into ./public/css/app.css and ./public/js/app.js. So you only have a few includes required in your projects HTML to use your assets. You can split them down further so 3rd party or vendor code is separated from your own code.

Vue.js

Laravel ships with Vue.js these days. This is very new to me and strangely different. It’s a JavaScript framework that is a totally different environment than my experience with jQuery. The main features that make it so different for me are the ability to bind data to components. This means a big change in the way you previously needed to monitor and trigger events based on changes in data. Vue.js does this for you.

Vue components live with your JavaScript assets under ./resources/assets/js/components. Once required/imported in your app.js file the .vue files get compiled into your application.

Bootstrap and Bootstrap-vue

Bootstrap is a HTML presentation framework. it provides the visual construction of the web page that the users of your application see. It’s the styling/CSS of the application. It’s a distinctive style, but very powerful in that designing for mobile, tablet through to desktop presentation is a built in function of the framework.

Bootstrap-vue is a Vue.js componentised implementation of Bootstrap. The need for writing HTML code in the manner of Bootstrap is taken over by writing vue components that build the Bootstrap HTML. So a Bootstrap button can become a vue component with data binding with actions and references like any other vue component. This brings program-ability to the visual presentation capabilities of Bootstrap.

Vuetify and Material Design

As an alternate presentation framework to Bootstrap/Bootstrap-vue on one project I’ve used Vuetify. Vuetify again is a very distinctive style. It uses the Google Material Design styles to present your application.

Application Delivery

After writing and testing the application locally I need to deploy it to a web server.

As part of my development process I use the Git version control system. This allows me to commit changes of my code in a controlled manner and enables me to rollback to previous versions, compare changes I’ve made and easily deploy the code to other systems.

For this I installed a Gitlab server so we have our own internal Git version control server. Using Github is only for publicly accessible code unless you take out a commercial package. Having our own Gitlab server provides the same functionality, but enables me to keep private projects internally.

To deploy the code to a server is as simple as compiling my assets for production and cloning the project to the server or pulling the changes.

Compile my production assets and upload/push them to the Gitlab server:

$ npm run prod
$ git add .
$ git commit -m "Production deployment"
$ git push

Then from the server clone the code and install/update the PHP dependencies:

$ git clone git@gitlab.domain.local/projectpath/project.git
$ composer update

or, to update the server:

$ git pull
$ composer update

Then it’s good to go.

So in all it seems a lot of components and when I started down this path I thought it all very confusing and more than a little daunting. But it’s like Lego. They all snap together quite tidily and the end result is a comprehensive application development and delivery platform.

Vue.js, Laravel and JSON Web Tokens — March 28, 2018

Vue.js, Laravel and JSON Web Tokens

When you have a Vue.js powered app authentication using traditional logon pages isn’t going to work. This is because primarily the apps interaction with the server is using Ajax calls with axios. So now we need to use JSON Web Tokens (JWT) to handle the authentication and store a client side session authentication token.

This article is very useful for this: https://codeburst.io/api-authentication-in-laravel-vue-spa-using-jwt-auth-d8251b3632e0

Continue reading

Vue.js – Past the First Week — March 21, 2018

Vue.js – Past the First Week

I started recoding a project that I’d only just built using Vue.js as an exercise in learning Vue. The project had only just been deployed using Laravel 5.5, Bootstrap 3 and jQuery. So I rewrote it and used Laravel 5.5, Bootstrap 4 and Vue.js.

The initial project delivered a nav menu driven series of pages that presented tabular results with a search/filter capability, with some Ajax/XHR calls to update datatables.

I’d built several blade templates to deliver the content and used some excellent Open Source code for building PHP forms for the filters and result details – Kris’ laravel-form-builder. I used DataTables.net to present columns of data and it all came together quite well.

But then I switched to Vue.js and replaced the form builder and datatables with bootstrap-vue.

Continue reading

failed to mount component: template or render function not defined. — March 15, 2018

failed to mount component: template or render function not defined.

Today I have been mostly smashing my head on the desk trying to figure out Laravel and Vue.js.

I thought I’d try to template an existing Laravel 5.5 project using Vue.js. Try as I might I could not get the template to work. I even stuck with the default example-component trying to get that to work . All I saw was an error reported in the console.

failed to mount component: template or render function not defined.

So I deployed a completely new Laravel project and added the example-component into the welcome page and it worked!

Continue reading

PostGIS Import from PHP Session Fails — March 12, 2018

PostGIS Import from PHP Session Fails

When importing a CSV file using Laravel I found that I’d get some strange error messages relating to a called function not matching the parameters that I was sending.

local.ERROR: SQLSTATE[42883]: Undefined function: 7 ERROR: function st_makepoint(numeric, numeric) does not exist
LINE 1: SELECT ST_SetSRID(ST_MakePoint(NEW.x_coordinate, NEW.y_coord...
 ^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.

I narrowed it down to the ST_SetSRID() and ST_MakePoint() functions and was 100% sure that they existed in the database, and with the right parameter types. I tried casting the values to double precision and still and the same errors.

The solution turned out to be that the function existed in the public schema NOT the schema I was using!

Continue reading

Axios — February 28, 2018
Laravel 5 – jQuery File Upload — February 22, 2018

Laravel 5 – jQuery File Upload

I needed a mechanism to upload CSV files to my Laravel instance and then process them into a table. The first part was working out how I wanted to upload the files.

I came across blueimp-file-upload which seems pretty popular and capable.

There was no need to go overly fancy. Just a simple form will do as the file will probably be uploaded as a single file. First I had to figure out how to get blueimp into Laravel.

Continue reading

The Power of Sphinx — February 21, 2018

The Power of Sphinx

I’ve only really used Sphinx as part of a home project with MySQL. But today found that searching for text in 28 million rows in a PostgreSQL table needs something with a bit more performance that the base SQL server.

Installing Sphinx on Debian is very straight forward if you want the default repository version and not the leading edge version. I saw no reason why not.

$ sudo apt-get install sphinxsearch

Now getting it working takes some fettling of the /etc/sphinxsearch/sphinx.conf file. It doesn’t exist by default so you need to create it either by copying the sphinx.conf.dist file or start fresh.

You also then need to edit the /etc/default/sphinxsearch file and set START=yes.

Continue reading

Fontawesome 5 and Laravel 5 — February 20, 2018

Fontawesome 5 and Laravel 5

This should have been easier, but I must have misunderstood how this works.

After upgrading to Bootstrap 4, for some reason my node_modules didn’t contain fontawesome anymore. I don’t know what I did, but I took it as a sign to upgrade to fontawesome 5.

This was a little tricky to follow at first as it works differently to fontawesome 4.

Install fontawesome, install the libraries you want to use so they can be used in Bootstrap.

$ npm i --save @fortawesome/fontawesome
$ npm i --save @fortawesome/fontawesome-free-solid
$ npm i --save @fortawesome/fontawesome-free-regular
$ npm i --save @fortawesome/fontawesome-free-brands

In your resources/assets/js/bootstrap.js:

require('@fortawesome/fontawesome');
require('@fortawesome/fontawesome-free-solid');
require('@fortawesome/fontawesome-free-regular');
require(‘@fortawesome/fontawesome-free-brands’);

Compile it using dev or watch.

$ npm run dev

That’s it. Now you can use the class="fa fa-..." tags as expected. You might find some of your existing fa’s are no longer included free. So checkout the fontawesome site and choose icons to replace them with.

References

https://fontawesome.com/icons?d=gallery&m=free