Ben Lobaugh Online

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

Category: Web Development Page 1 of 31

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!

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

WordPress: How to “properly” allow unfiltered uploads

If you are working with a WordPress site and getting the dreaded “Sorry, this file type is not permitted for security reasons.” message, fret no more!

WordPress has a config that allows you to enable unfiltered uploads

define( 'ALLOW_UNFILTERED_UPLOADS', true );

This, however, does not always work. Especially on Multisite, which may only allow unfiltered uploads for super admin users. No bueno.

Filters to the rescue!

Drop this code into your project (I put it in mu-plugins) and viola! You will have unfettered uploads.

add_filter( 'user_has_cap', 'unfiltered_upload' );

function unfiltered_upload( $caps )
{
    $caps['unfiltered_upload'] = 1;
    return $caps;
}

See also this StackExchange message

Cookies disappear after adding Set-Cookies in .htaccess? Here is how to get them back

I needed to set a cookie via .htaccess, to ensure it was always in the browser, regardless of what the website was doing. Setting a cookie is rather easy, it will look similar to:

Header set Set-Cookie "cookieName=value; Expires=Wed, 15 May 2222 07:28:00 GMT"

The next morning I attempted to login to the site and could not. It turned out the login cookies were not being set. The issue was insidious. Re-read the line above, at first glance it seems fine when you want to set a cookie, however if there are other cookies that need to run you need to add the cookie.

This three letter change resolved the issue and allows all the other cookies to operate properly:

Header add Set-Cookie "siglock=hello-world; Expires=Wed, 15 May 2222 07:28:00 GMT"

Canonical URL plugin for WordPress released!

Have you run into this scenario? You have content that needs to live on multiple sites but you are concerned about SEO issues duplicating said content?

As search engines crawl the web looking for pages to include in their search indexes they may run across content duplicated from another site. When that happens the search engine will first attempt to determine which site is the “source of truth”. The site with duplicated content will be penalized in rankings. If no source can be found both sites rankings will be penalized. An SEO nightmare.

Is it possible to distribute the same content to multiple sites without incurring this penalty? The answer is a resounding YES! All you need to do is let the search engine know where the real of the article is, the canonical article. This is done by including a tag in the html head area. It is for search engines, humans do not typically see it.

WordPress has some built in canonical abilities however in WordPress itself there is no way to set the canonical url. I tend to have articles published all over the web that I would like to copy to this site for posterity. Today I whipped up a little plugin that provides a simple url field to add the article’s canonical url in a search engine friendly way.

It is as simple as adding the url as you create the article!

Publish your post and WordPress will handle the rest.

Here is an example post that I wrote on team building for WebDevStudios.

9 Critical Concepts for Leading High-Performance Teams

You may notice there is also a brief disclaimer at the top of the article. That is optional and may be helpful to some readers and/or required by the site you are reposting from to comply with guidelines.

If you want to use this plugin on your own site simply head over to Github and download the plugin!

https://github.com/blobaugh/canonical-url-for-wordpress

Page 1 of 31