Laravel Watchable Package

I created this package to ‘scratch my own itch’. I have a model called Order. I wanted to notify certain people (only people who were watching the order) when the status of the order changed.

In this article, I will give you some boilerplate code that you can use in your application to wrap around the Laravel Watchable package.  If you fancy reading a little more about why I needed to build it in the first place, read the “A little background into ‘Why'” at the end of the page.

The problem

In the documentation, under the Using The Notification Facade section, you can see the example below.

However, the question is, how do you get the users? What I want to be able to do is send a collection of users who are watching the model.

The solution

Install the Laravel Watchable Package (https://github.com/jamesmills/watchable)

Remember to add the trait to your model. Throughout this post, I will use Order as the example.

Once you have the package installed this will help you handle the watchable request on the model. However, you will still need to add some additional functionality to your application. Below is some scaffolding which I hope will help.

I have created a separate controller to deal with this so that I can reuse the same controller for any models I want to be ‘watchable’.

To use this controller remember to add the route!

Now you can use the example below in your view file when you are showing the model you want to be watchable.

Important: The key thing to remember is that we send a hidden field with the ‘key’ as the model name you want to watch/unwatch. This is what makes our controller code reusable.

Now that we have added the ability for someone to be able to watch your model we can simply get the watchers of the model when we perform an action on it.

The below is a simplified version of what we have in our application when an order gets paused.

Notes

I use the Laracasts Easy Flash Messages for the flash()->success(‘message’) messages you can see in the controller to display the watching status back to the user after they have clicked the button.

A little background into ‘Why’

At Clicksco we are experts in traffic acquisition and we use this skill to drive traffic to highly optimised landing pages to generate form fill leads for a number of partners focusing in the financial industry.

We partner with a company called Lead Byte for lead processing and delivery which we use in combination with a number of in-house systems to manage the entire lead lifecycle.

A few months ago I was working on a new lead ordering module which would allow us to create an order for leads and have the system manage it. A lead order is when a company comes to us and says they will buy X number of leads from us. They might require people looking for Y product and the value of their fund might have to be above Z.

Within Lead Byte we set all the delivery configurations so we can delivery the lead directly to the clients CRM. We also set up rules to make sure the correct partner gets the correct leads. The one thing we were missing was being able to create a lead order to fit various scenarios. (Example: Send 
20 leads daily until a total of 500 leads have been sent or until 22nd Oct 17).

Using a combination of Laravel, Pusher and Vue we implemented our solution in our main system (we call this the PMD). What was missing was a way for us to notify specific people when certain things happened to an order. For example, when the daily frequency was met and the order was paused. Or, when the total number of leads for the order was delivered so the order is closed. Using Laravel 5.5 Notifications it’s easy to send out these notifications using a selection of different channels but the tricky part comes when you need to decide who to send the notification to.

The is why the Laravel Watchable package was developed. I allow anyone who can log into the system to ‘watch’ an order. Once they are a watcher of a lead order they will automatically get all notifications of all order status changes. It’s easy to find the order, get all its watchers and then send a notification to everyone who is watching.

 

Laravel Eloquent relationship query

I am working on a tool at the moment which is built on top of Codebase. I am going to blog later in more detail about this tool. For now, I want to touch on a specific Laravel issue I had yesterday.

We also use TeamWeek to plan on a more top level. TeamWeek enables us to plan on a weekly and monthly basis who will be working on what and when.

One thing that’s been annoying me for a while is having to duplicate information and use two tools. So we have been pulling our own TeamWeek view inside our internal application.

We have users and tickets. What I wanted to do was pull all users along with their tickets which match a given condition. I did not want all users and I did not want all tickets. The condition was that the started_at and deadline_at columns must not be null. I also only wanted tickets that either start or end within a given time frame.

What I eventually came up with was a query that searched for all users which had tickets that matched this condition. Then I added looked up only the tickets that matched the condition.

I am not confident this is the best Eloquent solution, but it works.

Comments welcome!

Laravel Envoyer & FreeBSD mv: illegal option — T

UPDATE

Originally Taylor tried to ‘lookup’ the operating system you were using and then use the correct command. Unfortunately, this broke things for other users so he had to roll it back.

So he has now included a config option


I have been meaning to try Laravel Envoyer for some time now. At work we have a deployment process which is mainly focused around Codeship with some custom scripts that are either on the server or committed to the repo.

Although there are many options for zero downtime deployment I really like the idea of using Envoyer so I decided to give it a go. Nearly all of our servers are FreeBSD for various reasons and as I excitedly watched the deployment happen for the first time I was disappointed when I saw ‘Finished With Errors’. I clicked on the output button with provides you with some more feedback and I was faced with a rather confusing message.

screenshot-2016-09-29-09-10-11

It looks like the option -T is not available on FreeBSD as it is in Linux systems so the final step where Envoyer activates the new release is not able to move the ‘current-temp’ folder to be the ‘current’ folder.

I sent a tweet out to see if anyone else was having this issue or if it was something I was doing wrong. I got a helpful tweet back from @FreeBSDhelp which confirmed that the option -T was not available.

Interestingly if you run the move command without the -T and you already have a current folder it will place the ‘current-temp’ folder inside the ‘current’ folder resulting in ‘/home/forge/domain.com/current/current-temp/’, obviously not what we are looking for. So it looks like the option in FreeBSD is to replace the -T option with -h which will do a similar thing.

So for FreeBSD we need to run

and on all other we can run

I have exchanged a couple of emails with Taylor and I hope that we will see this merged into Envoyer soon so that I can continue my trial of the product.

I would love to hear from anyone else who has had the same issue.

Video

Laravel 5.3 Overview

I am sure many of you who follow Laravel will know that it was Laracon US just a few weeks ago (July 27-29, 2016 in Louisville, Kentucky). I purchased a live streaming ticket because I was unable to attend the conference this year.

The website that is hosting the video has just released all the videos for free open access now, so get yourself along to https://streamacon.com/video/laracon-us and enjoy!

It’s also worth keeping your eye on Laracon EU which is when it’s rumoured Laravel 5.3 will be released!

Screenshot 2016-08-16 08.53.52

 

Some of my other favourites include:

Source: Watch Taylor Otwell – Laravel 5.3 Overview from Laracon US!

Link

Laracogs

Prepare your Laravel apps incredibly fast, with various commands, services, facades and boilerplates.

I stumbled across Laracogs a few days back. I setup a test project to play around with it and I found both the CRUD and the Table CRUD to be really interesting.

I recently chatted with Matt Lantz, from Yab Inc, who created the package. Chatting in a PM in the wonderful LaraChat slack group, he informed me he is working on a version 2 of the package. This is really exciting because it looks like you will be able to pick from a few DDD (Domain Driven Design) patterns.

https://laracogs.com

Get remote laravel log file

By now you are deploying your web applications via some sort of magic like Codeship and have probably decided to turn FTP off on your servers. Either that or you are using Forge and the only way you can get at your production server is via SSH.

If you want to run migrations on your production server then you can SSH in or maybe have an Envoy command to do this. However, what happens if you need to review your production log files from your Laravel app but you cannot just FTP in and download them.

At first I thought about doing it via Envoy but I could not get my head around how to use the ‘scp’ command. I ended up setting an alias to do it from my local machine using

alias get-amazing-com-log=”scp username@server.com:/home/web/amazing.com/app/storage/logs/laravel.log ~/Projects/amazing_com/app/storage/logs/”

Then I thought, how about a quick Laravel Command to do something like

php artisan logs:get

To do this we are going to make use of the SSH Class in Laravel, specifically SFTP Downloads. For us to be able to use this class we need to set some remote configurations.

To get started we need to go to ‘/app/config/remote.php’ and add the settings for your remote server, in this example we will set them for our production server.

You will notice that the only thing we actually set in this file is the ‘root’ as everything else is extremely sensitive so we are going to set those configuration items using “dot” files.

Once we have the configuration setup then we are ready to setup our new Artisan Command.

And remember to register this command so you have access to it when running Artisan on the CLI.

And there you have it. Now you can run a simple Artisan command from your local machine or from within your Homestead VM and it will connect to production, pull down the log file and store it in ‘app/storage.logs/production.log’.

You’re welcome.

Limit packages to development in Laravel applications

Let’s say you like to use Laravel 4 Generators by Jeffery Way like we do at Clicksco. If you are not familiar with this package then you should head over to Laracasts and watch the free video. You will only be using the generators in development so you don’t really want to have this included on production. Let’s have a look at how we can do this.

First of all you need to make sure that you have included ‘way/generators’ in the ‘require-dev’ section of your composer.json file and not the ‘require’ section. You can do this manually or from terminal by running

Worth noting that if you run this then composer will automatically run a ‘composer update’ and this update will run including require-dev packages, this is the default action of a composer update. Your composer.json file will now include the package in the ‘require-dev’ section.

After requiring the package, which now sits in your vendor folder, you will need to instruct Laravel to use it. To do this we register a service provider. If you were to follow the installation instructions on GitHub then you will notice that you are asked to open ‘app/config/app.php’, and add a new item to the providers array (shown below).

This is where we are going to start doing things a little differently.

Instead of doing the above we are actually going to add the service provider to our development environment app config.

As I am sure you are aware, inside the ‘app/config’ folder you can create folders that match your environments. By default the ‘app/config/app.php file will be loaded by Laravel and this will be true for production. However, for development we want to tell Laravel to load ‘app/config/development/app.php’. To do this we need to alter ‘bootstrap/start.php’ and include something like:

The above example has my local machine hostname for situations where I would be using MAMP and also the hostname of my Vagrant VM for when I am working in our default Vagrant setup we have at Clicksco. I then have the domain of the live application in the production array. There are a number of different ways of managing this but I have found this to work best for my needs.

Another way, and one that is much better

We have told Laravel to check in the ‘app/config/development’ folder for settings to be used when in our development environment we now need to add our service provider to this file.

Normally we would just add the config settings for development in a new array inside the ‘app/config/development/app.php’ file but by default this will override the settings loaded from ‘app/config/app.php’. So we are going to make use of the ‘append_config’ helper method in our environment app configuration file, see below.

Notice that the debug = true is an example of an override and our providers = append_config is an example of us appending to what has already been loaded. Now we have access to Jeffery Ways Generators but only when we are in development, you can test this by running

and you will now see something like

[text]
generate
generate:controller Generate a controller
generate:migration Generate a new migration
generate:model Generate a model
generate:pivot Generate a pivot table
generate:publish-templates Copy generator templates for user modification
generate:resource Generate a new resource
generate:scaffold Scaffold a new resource (with boilerplate)
generate:seed Generate a database table seeder
generate:view Generate a view
[/text]

To finish off we will want to make sure that we don’t include the ‘require-dev’ packages on production. This is simply done by running composer update adding the –no-dev option. Just add the ‘–no-dev’ option to your deployment script.

Hope this helps someone.