Ben Lobaugh Online

I think, therefore I am. I am, therefore I sail

World’s cheapest standing desk

Standing desks are great to get you up from a sedentary chair, especially when you are at your desk all day. In my case, a standing desk is helpful to alleviate the pain of a back injury that I suffered in my teens.

I would like a sit/stand convertible desk, however those cost hundreds of dollars and I wanted to be a bit thrifty. This desk cost less than $20 to build. The top is reclaimed from an old shelf, and and I counted it as free.

I also wanted to be able to integrate my musical keyboard into the setup. It came out pretty well for $20!

How to use custom pivot tables in Laravel 6.x

Have you run into this before?

Your app’s database table structure is predefined and unalterable. There are lookup tables (called pivot table in Laravel) that create many to many relationships between tables using YOUR naming convention. It makes sense in the context of your application, but you quickly find out that Laravel’s relationship defaults do not match it well.

Lets take this scenario for example:

You have users who are part of organizations, and organizations can have groups in them, created by the users.

There are three primary tables:

  • users
  • organizations
  • groups

Additionally there is a lookup table called organization_groups. The lookup table contains not only the related id, but several other relevant data points, including a field called “created_by_user_id”.

This looks good in theory, however Laravel is going to require the pivot (lookup) table to be named groups_organizations out of the box. In your data structure it logically makes sense to have the table named organization_groups though. Luckily this is entirely possible, though the documentation on how to do it leaves a little to be desired.

Step One: The basic models

Let’s start out by creating the basic models. This can be easily done with Laravel’s artisan command

php artisan make:model Users
php artisan make:model Organizations
php artisan make:model Groups

It should be noted here that I used the build in Laravel users model that comes with the authentication mechanisms. I did not actually run the make:model command for that. You will not need to if you use Laravel’s users either.

Step Two: Related Groups to the Organizations model

This was the most annoying part to figure out, and the least well documented…..

When you load an organization you will be able to access all the groups via a class property. For example:

$org = Organization::find( $id );

$groups = $org->groups;

Laravel is doing some magic behind the scenes here- first, “groups” is not a property. When requested, Laravel checks to see if a corresponding method exists. In this case it looks for “public function groups()”. The method must return a relationship, such as “belongsToMany”.

By default, Laravel will use the “groups_organizations” table, but by messing with parameters I determined how to properly switch the table. Laravel does a lot of magic with parameters- depending on how many you use the meaning of the parameter changes. In our case it looks like

$this->belongsToMany( CLASS, TABLE, KEY-RELATING-THIS-MODEL, KEY-FOR-OTHER-MODEL )

which comes out to

$this->belongsToMany( Groups::class, ‘organization_groups’, ‘organization_id, ‘group_id’ )

Notice the keys are singular. Laravel is expecting them to be plural (like the table name I think) so have have to be explicitly specified here.

Here is the full code to create the relation. This code belongs in the Organizations model.

public function groups() {
   return $this->belongsToMany( Groups::class, ‘organization_groups’, ‘organization_id, ‘group_id’ );
}

Now we will be able to do things such as:

$org = Organizations::find( 42 );

foreach( $org->groups as $group ) {
    echo $group->name;
}

Step Three: Relate a User to the Group

Here each Group has a single User set in the “created_by_user_id” field.

Laravel’s many-to-one relationship used “hasOne”. In the Groups model class we add:

public function createdBy() {
    return $this->hasOne( User::class, 'id', 'created_by_user_id' );
}

Now we can find which user created a group with

$group->createdBy->name;

In the organizational context, we may have a list of all groups and who created them.

$org = Organizations::find( 42 );
foreach( $org->groups as $group ) {
    echo “Group: “ . $group->name . “ - Created by: “ . $group->createdBy->name ;
}

Hope that helps!

30_gallon_stand_cardboard_mockup

The 30 gallon fish tank stand is getting an upgrade – Sides!

With Clara crawling, it is time to baby-proof the house. One big project to tackle is the fish tank. Currently the 30 gallon tank sits on a custom stand made of 2x4s. There is a shelf on the bottom, that inevitably winds up holding tank gear. It is open for all the world to see. We are going to be closing it in  so that Clara cannot get ahold of any of the chemicals or electrical connections that are kept on that shelf.

This stand is fairly old, so this update will give is a whole new life. I do not recall exactly when we found this, but my buddy Jordan got it first I think- when we were teens still!

Here is the cardboard mock up of our solution.

30_gallon_stand_cardboard_mockup

free 90 gallon tank and stand

Free 90 gallon fish tank! Big project alert

Some of you may know- to add to the list of crazy traits I have, I love fish keeping. When I was born my parents had 21 fish tanks in the house, in fact, they met at a fish club show. Growing up I was around all varieties of tanks, from 5 gallons to 125 gallons. Small community fish to fish large enough to take a finger off.

Over the last four years I lived on a small powerboat- not really enough room to have a proper tank, so I have been without fish a while. After moving into our project house, I set up my old 30 gallon tank, but I wanted more.

Yesterday on OfferUp I saw a 130 gallon tank listed, FOR FREE! Hard to pass that up. I headed over and picked it up a few hours after it was posted.

free 90 gallon tank and stand

Tank size from a picture is a bit hard to determine, so I will post photos of the measurements below. Suffice to say this is a 90 gallon tank, not a 130. But hey, it was free!

The tank material is acrylic. I believe this is the first acrylic tank I have owned. There is a slight haze to it that I can get off with a good buffing. Sometimes when filled with water the haze disappears, so I will try that first.

The stand looks rough in the picture- because it is rough. There is a lot of rot and water damage on it. I do not trust it with the 800 pounds it will be holding. No big deal, we were already knew it needed work from the posting photos. I will take the doors off the front and build a new skeleton inside it. Piece of cake.

Sadly, there are several projects around the house that are higher priority than getting this tank running, so it will be a few months until she is up and running.

I prefer under gravel filters but am tossing around the idea of building an external sump. What do you think? Shoot me a message.

Outer tank size

Inner tank size

Looping stairs

How to fix a WordPress HTTPS redirect loop with an NGINX reverse proxy

If your WordPress site is set up to use HTTPS and a reverse proxy, such as an NGINX reverse proxy, is put in front of it you may wind up with an infinite redirect loop.

Following the redirect in dev tools, it looks like this is happening:
https://example.com -> https://example.com

A head scratcher for sure, but understanding what is going on behind the scenes reveals the issue and the solution together.

Here is what is actually happening:

  • Request is made to https://example.com
  • The reverse proxy catches the request and makes it’s own request to http://example.com. Take special note that the schema changed to http.
  • The WordPress site sees a request for http://example.com and says, “Hey, that’s not right, I am at https://example.com” and tells the browser to go there
  • Repeat indefinitely

You could change the site to support http to the exclusion of https, however that is hacky and anything wanting https will still work itself into an infinite redirect.

An easier solution is to trick WordPress into thinking the request is https enabled.

WordPress looks at a server variable when determining the status of https. Open your wp-config.php file and add the following just after the <?php tag:

if ( $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['SERVER_PORT'] = 443;
}

And now your site will work as originally anticipated.

Dastardly isn’t it 😉

Photo by Dan Freeman on Unsplash

Page 1 of 160