Quick snippet – Selecting only certain columns for a model in laravel

With a model named (Person) that maps to a table named (persons) with a structure defined below

CREATE TABLE `persons` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `first_name` VARCHAR(255) NOT NULL,
  `last_name` VARCHAR(255)  NOT NULL,
  `email` VARCHAR(255) NOT NULL,
  `created_at` TIMESTAMP NULL DEFAULT NULL,
  `updated_at` TIMESTAMP NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `persons` (`email`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Then, Consider the eloquent statement given below

$result = Person::find(1);

this is equivalent to,

SELECT * FROM Persons

The above can be wasteful if all you require is just a few columns such as the firstname and lastname, to fix this, we use the eloquent statement below

$result = Person::find(1, ['first_name', 'last_name']);

This is equivalent to,

SELECT first_name, last_name FROM persons

Hope, you have been able to learn something new today.

Advertisements

Did you know? You can fetch multiple Eloquent records with one command

The Eloquent class in Laravel has a method called find, this you must be aware of , you can use this to find an Eloquent Model record using the primary key. This is used as follows

// Retrieve a model record by its primary key...
$car = App\Car::find(1);

Now, what if we want to find all cars with primary key in the list [1,2,3]? You can suppluy an array of primary keys to the find method or use the findMany method. Consider the code snippet below

$cars = App\Car::find([1, 2, 3]);
or
$cars = App\Cr::findMany([1, 2, 3]);

 

Note: If you supply an array of keys to the find method, it calls findMany internally. Whichever you decide to use between the two methods described above, they both return an instance of  \Illuminate\Database\Eloquent\Collection.

giphy5

 

 

Highlighting Active Bootstrap Menu Items (Nav – Item) Based On Route

In this post, I will show you a niifty little trick, one that is always required whenever you are working on some sort of web project with multiple routes.

You occasionally need to set the nav-item that inidicates the current route to be active (i.e. make it coloured ), to achieve this using laravel, consider the code snippet below

<ul class="navbar-nav">
<li class="nav-item {{ is_active('route.name.one') }}">
    <a class="nav-link" href="{{ route('route.name.one') }}">Route One</a></li>
<li class="nav-item {{ is_active('route.name.two') }}">
    <a class="nav-link" href="{{ route('route.name.two') }}">Route Two</a></li>
<li class="nav-item {{ is_active('route.name.three') }}">
    <a class="nav-link" href="{{ route('route.name.three') }}">Route Three</a></li>
</ul>

As you can see from the snippet displayed above, for every <li> element, the is_active function call has been added to class attribute , this function takes the name of a route as its argument and it returns a class name (active) if the current route name matches that which was supplied. Consider the snippet below to see the logic in the function stored in a file called helpers.php in a new folder called custom (note:  you can store your helper file anywhere you deem logical, I have just chosen custom/helpers.php).


if (!function_exists('is_active')) {
    /**
     * @param string $routeName
     * @param string $activeClassName
     *
     * @return string
     */
    function is_active(string $routeName, string $activeClassName = 'active')
    {
        $result = '';
        if (request()->route()->getName() === $routeName) {
            $result = $activeClassName;
        }

        return $result;
    }
}

How do you make your function available globally?

To make the function in the [core/helpers.php] file available globally, you need to autoload it using the files attribute of the composer.json file as follow.

"autoload": {
    "classmap": [
      "database/seeds",
      "database/factories"
    ],
    "psr-4": {
      "App\\": "app/"
    },
    "files": [
      "core/helpers.php"
    ]
  }

Hope you have found this helpful..

How to extend the laravel Collection with a macro

At this point in time, if you are familiar with the Laravel framework, I am sure you must have used the lovely Collections class. It is one of my favourite features of the laravel framework, so much so that I use in some bespoke projects outside laravel.

What is Laravel Collections?

It is nothing but php arrays on steroids. It allows you to perform very cool manipulations and processing of php arrays.

How do you create a collection?

$collectionInstance = collect([1,2,3,4,5,6,7]);

$collectionInstance2 = \Illuminate\Support\Collection::make([1,2,3,4,5,6,7]);

The collection class has a hosts of methods , such as

  1. avg
  2. sum
  3. unique
  4. and a lot more

However, sometimes you wish to use a method on the collection class and it isn’t available, so how do you do it? Collection Macros to the rescue.

Creating a macro to convert all items of a collection to camel case.

Consider, if you wish to convert all the strings in a collection to their respective camel case values, and there isn’t one method to do this. Obviously you can use a map or transform to achieve this, but for convenience sake, lets create a macro.

 Collection::macro('camelise', function(){
    return $this->map(function ($value) {
        return camel_case($value);
     });
 });

// to use it
$items = ['foo_bar', 'hello_world'];
$expectedValues = ['fooBar', 'helloWorld'];
$camelValues = collect($items)->camelise();

// assert that result matches the expected values.
$arraysAreEquals = $expectedValues === $camelValues->toArray();
assert($arraysAreEquals);

 

Where do I put the macros?
As helpful as this is, imagine if you have a 100 of such methods, where do you keep them?

Now this is a subjective answer, you can extract your methods into files and require them from a loop of the glob of the location of these files or you create a class with your macros and you use the Php Reflection Class to loop through them and add them to the Collection class.

Also, the AppServiceProvider will be a good point to add the logic described above.

 

giphy4

Fetching Laravel Eloquent results ordered by oldest to newest

In the previous post, I showed you how to order you results from newest to oldest using Eloquent model.

It is only logical to show you how to reverse the operation, ordering you results from the oldest to the newest. As always, Laravel in its majesty has already created a method for this and guess what it is called? oldest, so obvious right?

Consider the code below

Post::oldest()->get();

This will return the results already ordered by created_at from oldest to newest.

giphy3

Fetching Laravel Eloquent results order by newest to oldest

This tiny requirement is one that keeps popping up in you day to day programming routine, yet it is greatly misunderstood at least in the laravel way.

Imagine, if you have a model called Post (mapped to table named posts) and you have been asked to list the posts in descending order of creation date (created_at). Solving this using the ever reliable raw sql can be done as follows

select * from posts order by created_at desc

Wrong way

A very forgivable but wrong approach is to get the Posts and then order It

 Post::get()->sortByDesc('created_at');

While this would work, it is inefficient and in some cases may even be wrong, it is mainly inefficient because it fetches then entire Posts results before ordering it. This may be very expensive as you can imagine depending on the size of the posts table.

Right way (Long route)

The right way is to add the ordering condition on the Post model before getting it. i.e

 Post::orderBy('created_at', 'desc')->get();

As you can see, this is different from the wrong way because it orders the resultset before getting it.

Right way (Short route)

Although we have a right way of achieving this using the method described above, laravel is known for syntactic sugar and guess what, there is one for doing just this. It is called latest. Consider the code below

 Post::latest()->get();

giphy2

Laravel testing with failing foreign key check on sqlite

as a firm believer in Test Driven Development (TDD), I make sure to test all of my codes. Whenever I am coding in PHP using laravel, I opt to use sqlite memory as my testing database because of the speed it gives and it is very inexpensive. Hwoever, sqlite has some shortcomings, one of which is its default lack of foreign keys. This may prove to be problematic when you are testing relationships in your models and you wish to enforce refential inetgrity..

To enable the use of foreign keys in sqlite, use the code below

add the code below into the boot method of  your AppServiceProvider.php

if (\DB::connection() instanceof \Illuminate\Database\SQLiteConnection) {
  \DB::statement(\DB::raw('PRAGMA foreign_keys=1'));
}