Model Search and Filtering in Laravel

Hi guys, as I have written this functionality a few times at this point, and I have been asked how to do it a couple of times, too. That is Laravel searching and filtering, I am going to develop a simple composer package which I can use to allow users to search and filter Laravel (Eloquent) Models using PHP traits which can be used on Laravel controllers.

Assumptions

I am going to work on the assumption that you are comfortable with basics.

I shall also assume you’re fairly comfortable with the Illuminate HTTP Request object, a Controller, and Eloquent Model.

Concept

So the first thing we want to tackle, as a concept, is that the best way, in my experience, is to start with a query, and then modify it as required. This allows us to optionally do almost anything, but equally allows us to do nothing, and simply return an unfiltered set if we want to.

This point would be true outside of Eloquent too, even if working with vanilla SQL.

Starting Off

To start with you want something like this within your Controller.

public function index(Request $request)
{
// Of course you can change this if you don't want to select everything
$query = YourModel::select('*');
}

Now we have the $query object which we can work with as and where we want to.

Filtering Records

Excluding deleted/is deleted, as we’ll cover that later on.

Let’s say you now want to filter results on author_id just to keep things simple.

if(!empty($request->author)){
$query->where('author_id', '=', $request->author);
}

Of course take into account everything here, you may need to do sanitisation or validation or anything else in there.

Multiple Filters, Save Lines

If you have many fields on which you wish to do this I usually find something like this is better

$fields = ['author_id', 'category_id'];
foreach($fields as $field){
if(!empty($request->$field)){
$query->where($field, '=', $request->$field);
}
}

That example assumes the exposure of your field names, you could always use an associative array so you could do “author” maps to “author_id” and so on, if you were so inclined.

Fluffy Search

Now you might want to do a fluffy search, taking the assumption of posts with content and an author name, and a category name (stored within the model) you could do something like this

if(!empty($request->search)){
$searchFields = ['title','content','author_name','category_name'];
$query->where(function($query) use($request, $searchFields){
$searchWildcard = '%' . $request->search . '%';
foreach($searchFields as $field){
$query->orWhere($field, 'LIKE', $searchWildcard);
}
})
}

Handling Trash

You probably want something which allows you to see soft deleted models, if you’re using them. I do something like this

if($request->trash == true){
// Retrieve soft deleted models only, you can only do this if you're using soft deletion on this model
$query->onlyTrashed();
}

Ordering and Limiting

Now to handle ordering and pagination – which Eloquent beautifully does for us, all we need to do is let the user modify it if they want to.

// Set the query ordering
$query->order($request->orderBy ?? 'updated_at', $request->order ?? 'DESC');

$perPage = $request->per_page ?? 25;

// It is a good idea to make sure we cap this
if($perPage > $maximumPerPage){
$perPage = $maximumPerPage;
}

// Final part - get the results
$results = $query->paginate($perPage);

// You will now need to do something with your results, and return some kind of Response - this could be a JSON response or adding the results to the data returned to the view, depending on your context

There’s an assumption here that our default order is updated at, last updated first, and that if not specified, we want to return 25 pages.

Of course you can store this information wherever you want.

In Summary, and Further Reading

Rather than creating a really complicated set of rules to handle all the things you may need from your API calls, start with a query, and then optionally modify that query.

Further Reading

An introduction to Checksums

Hi everyone

This is a quick introduction into checksums, and practically how to use them, at the request of someone through the Ask Johno section of the blog.

I know what a checksum is, but I’m not sure how to implement or use one (in PHP) to achieve what I need.

Anonymous Asker

They go on to explain what they are trying to achieve, which is essentially to verify a file hasn’t changed (in this case it’s the HTTP document sent by an API) before doing something.

Firstly, a checksum is a very small data snippet (datum) which represents something larger.

In my experience there are 2 main reasons to use one, these are;

  1. To verify a change in something larger
  2. To verify that a piece of data matches from that which was sent by its originator (checksum on an API payload)

I will very briefly cover both of these with PHP examples.

Note; I am using MD5 for simplicity, but depending on your requirements this likely won’t be the best option for your use case.

Edit: Please see Further Reading at the bottom of this article for more information about hashing

Using a Checksum to Detect Changes

Now I don’t know what we’ve got, but whatever it is; we are going to need a string representation, 2 main ways of getting this:

$stringRepresentation = serialize($myThingToCheck);

or

$stringRepresentation = json_encode($myThingToCheck);

Personally, I would advise PHP’s serialize because that will work with, and instantiate objects. However, the choice is yours depending on your use case, JSON is smaller than a PHP serialization.

Now that we have a string, we need to make it small and easy to check. Something like this will work fine;

$checksum = md5($stringRepresentation);

Now to check for changes, we just need the last checksum that we stored that something happened on.

if($checksum != $oldChecksum){
echo 'Something has changed';
}

So that covers how to use a checksum to detect changes in pieces of data, which is useful if you’re having to poll for changes.

Using a Checksum to Verify Validity

This is something I’ve noticed a couple of times, particularly when working in the financial industry, and around certain payment gateways.

It usually looks something like this; but it does change per API integration so be aware of that and follow their own documentation.

$secret = 'my_secret_api_key';

$payload = [
'foo' => 'Bar',
'another' => 'Thing',
'datetime' => '2018-12-25 00:00:00'
];

$jsonPayload = json_encode($payload);

$checksum = md5($jsonPayload . $secret);

$payload['checksum'] = $checksum;

// Do the rest of your stuff here, including sending the payload etc.

One advantage of this approach is that you never expose the API key in plain text.

If you were to want to verify on the API so that you’re the provider, rather than integration, you would simply do these steps in the opposite order, so it would look something like this

// Assuming you've done everything you need, and now have the $payload array/object back

$secret = 'the_secret_youre_expecting';

$checksumProvided = $payload['checksum'];
unset($payload['checksum'];
$checksum = md5(json_encode($payload) . $secret);

if($checksum != $checksumProvided){
// If the checksums don't match, in theory the secret key provided was incorrect
}

I think that about covers this topic, as a brief introduction to checksums, and how they’re often used in PHP.

Further Reading

PHP: hash() for more information about the best ways to hash data

I have deliberately not gotten into the discussion over hashing algorithms, as it really is out of the scope of this article, and indeed a whole book could be written on the topic alone.

Thanks to u/artemix-org and u/BradChesney79 on Reddit for suggesting this edit.

PHP Interfaces, Traits, and Inheritance, how and when to use them

Hi all

So this one is going to be fairly short and simple, I hope! What I am going to cover, and this does assume so prior knowledge, is what interfaces, traits, and inheritance are; and some different use cases for them.

So the first one, and maybe the easiest one to cover, first:

Inheritance

In its simplest term, and I’m going to try and keep things simple in this article. In very brief terms, inheritance is about extending something which exists. Of course, you may well have created this base on which you’re extending.

Simple use case: User class, extended by an Administrator class. This would be because that an Administrator can do everything a user can do, but a User can’t necessarily do everything an Administrator can do.

The way you would do this in PHP would look like:

class User
{
    // Regardless of whether you're a standard user or an administrator you would have access to this method
    public function getUserId() : int
    {
        return $this->id;
    }
}

class Administrator extends User
{
    // Only administrators can delete users
    public function deleteUser(int $userId)
    {
        // Do something here
    }
}

Of course, there are a million ways of using this, but essentially what you’re doing here is following a single line of inheritance, each extension gaining its own functionality. Something else of note is that you can override (except where the final keyword is used) methods and classes.

There are many ways you might want to do this, including several layers of inheritance, or multiple classes extending the same base.

Interfaces

This is concept defines a set of interfaces (or integration points), though the key theme here is that an interface can be applied to anything. You’re specifying very little, except that the class implementing this interface must abide by the rules laid out.

interface Notifiable
{
    public function getEmailAddress() : string;
}

Now the thing to note here is that the interface simply doesn’t care how you retrieve that email address, but you must have a way of doing it, and any class this is applied to must follow those rules.

The easiest use case for an interface, that I can think of, is something like the above. Notifiable, anything within your system could be notifiable. An instance of the system, a user, an organisation, a team or department. It doesn’t matter, applying the interface means that it could be parsed and handled, through a notification service.

Traits

I’ve tried to explain this one recently, and the use case for it. The easiest way I found of explaining it recently has been: An interface lets you define the input and output of some methods, inheritance lets you gain functionality from parent classes. Traits are for where you don’t want to use parent classes (because you can only extend one class at a time), but want to bring the “meat” of some methods across.

At the risk of causing some controversy here (again) I’m going to say the easiest use case to explain with traits is a logging class, which might look something like

trait Logger
{
    // PSR-3 compliant functionality here
}

class MyThingDoer
{
    Use Logger;
}

All this does is allows the MyThingDoer class to do anything that the Logger trait specified.

In Summary

I’m not necessarily advocating the use of these three sets of functionality, or how they should be used, or anything like that. I’m simply documenting their existence and usage in a way that those moving from PHP procedurally into a structured OOP environment might understand it.

I understand there are dependency injection arguments regarding traits, and I think that is a conversation for another day.

So, in a sentence. When you want to have a base class, and things which logically make sense to be extensions – use inheritance. When you want to ensure conformity to a set of rules, so that objects can be parsed into service providers, use interfaces. When you want to simply share functionality across multiple classes, use traits.

I hope this has helped, of course, if you have anything to add, anything you’d like to say or anything to contribute, stories, personal experiences, etc. as always feel free to drop it in the comments.

Quick Life Hacks with the Eloquent Model

Hi folks,

It’s no secret that I love Laravel, and especially love Eloquent. This post isn’t about why various people don’t like Eloquent, etc, etc. but just some “life hacks” of working with Eloquent.

#1 – Naming Conventions

I personally like to use the following naming convention on my databases (using a forum as an example)

forums
forums_topics
forums_topics_replies

Whereas Eloquent would expect the following:

forums
forum_topics
forum_topic_replies

I personally dislike this, for no other reason than I like to be able to see what’s being owned by what at a very quick glance. Additionally, namespacing; I like to namespace my Models, at the very least into a Model namespace, but often I like to further namespace these to represent the ownership of the data; so I end up with something like (I’m using a directory structure, because PSR-4 namespaces follow this anyway)

app/
- Model/
- - Forum
- - ForumTopic
- - ForumTopicReply

My only issue with this is that the Model namespace can end up huge, and with classes with some really ridiculously long names. So I prefer to break this down like so:

app/
- Model/
- - Forum
- - Forum/
- - - Topic
- - - Topic/
- - - - Reply

I realise this begins to look like overkill, but I find it particularly useful when separating functionality by module or something like that.

The Autonaming

The above means I have two options, number one is to follow the convention to the letter. Option two is to overwrite the naming convention on a base model, from which I then extend. This base/abstract model contains the following method:

/**
 * Overwrite the autonaming conventions
 * @return string
 */
public function getTable()
{
    $class = substr(get_class($this), strlen(self::MODEL_NAMESPACE));
    $namespaces = explode('\\', $class);
    foreach($namespaces as &$namespace){
        if(substr($namespace, -1) == 'y'){
            $namespace = strtolower(substr($namespace, 0, -1) . 'ies');
        } else {
            $namespace = strtolower($namespace . 's');
        }
    }
    return implode('_', $namespaces);
}

Note: You will need to have the MODEL_NAMESPACE constant declared as well

All this does is turned app\Model\Forum\Topic into forums_topics, but it’s pretty useful

PSR-2 properties

So the other thing I find occasionally annoying is that when writing PHP my properties follow the PSR-2 naming convention (camelCaseForVariables) – but using eloquent I am forced to snake_case_columns because (understandably) this is what is in the database.

By adding the following 3 methods to your base model you can use PSR-2 compliant field names. So that created_at becomes createdAt; without having to modify the database;

/**
 * Overwrite the getter so that we can use camelCase field names
 * @param string $property
 * @return mixed
 */
public function __get($property)
{
    return parent::__get($this->convertToSnakeCase($property));
}

/**
 * Overwrite the setter so that we can use camelCase field names
 * @param string $property
 * @param mixed $value
 */
public function __set($property, $value)
{
    parent::__set($this->convertToSnakeCase($property), $value);
}
/**
 * Turn a camelCase string into snake_case
 * @param $string
 * @return mixed
 */
protected function convertToSnakeCase($string)
{
    return strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $string));
}

Quite simply, all these methods are doing is plugging into the original getter and setter, but first converting camelCase to snake_case – so that throughout my code I can refer to these fields in a way which is fitting with the rest of my code, which conforms to PSR-2

There you have it

A couple of very quick, but very useful, ways to extend the base Eloquent Model so that it is in better fitting with the rest of your code base and database standards (or mine, anyway)

Quick and Easy PHP Singleton

Hi guys

A really short one today, just because someone asked me about it a couple of days ago. I also though it potentially best to avoid something as controversial as my last post about Eloquent and the Single Responsibility Principle, which caused a bit of a stir during the week.

So, you want to make sure you only ever use one specific instance of a class (maybe a DB connection) and need a quick and easy way to do it. Personally, this is the technique I would use:

<?php

class MySingleton{
  
  // This will hold the instance of the class
  private static $instance = null;
  
  // Declare this as private to stop anybody being able to use the "new" keyword
  private function __construct()
  {
    // Your usual constructor stuff in here
  }

  // This is where you get your instance
  public static function getInstance()
  {
    if(is_null(self::$instance)){
      self::$instance = new self();
    } 
    return self::$instance;
  }

}

All we’re doing here really, in a set of steps:

  • You need a way to hold an instance of the object which is persistent throughout the execution
    This is what the private static $instance is doing
  • You don’t want anybody to be able to directly use the new keyword, because then you’ve lost control of the instances of the object
  • You need to be able to get an instance of the class, which is what the getInstance method is for
  • In getInstance all we’re doing is instantiating the object if one hasn’t get been stored against the $instance static

So, to fetch your instance is simply:

$singleton = MySingleton::getInstance();

Wherever you run that throughout your code you will receive the exact same instance. Particularly useful in things like Database connections, loggers/debuggers and things like that.