laravel

Laravel just released version 8.10.0 with about 20 new features and few bugfixes ! The new release of the framework added some great new features such :

  • Allow chains to be added to batches
  • Added is() method to 1-1 relations for model comparison
  • Added upsert to Eloquent and Base Query Builders
  • Support psql and pg_restore commands in schema load
  • Added Illuminate\Database\Schema\Builder::dropColumns() method on the schema class
  • Added yearlyOn() method to scheduler
  • Added restrictOnDelete method to ForeignKeyDefinition class
  • Added newLine() method to InteractsWithIO trait
  • Added isNotEmpty method to HtmlString
  • Added delay() to PendingChain
  • Added ‘multiple_of’ validation rule
  • Added custom methods proxy support for jobs ::dispatch()
  • Added QueryBuilder::clone() 
  • Support bus chain on fake
  • Added missing force flag to queue:clear command
  • Added dropConstrainedForeignId to `Blueprint
  • Implement supportsTags() on the Cache Repository
  • Added canAny to user model
  • Added when() and unless() methods to MailMessage

Allow chains to be added to batches :

This adds functionality to batching that allows you to pass in a sub array of job classes that will create a job chain included in the batch. The first item in the array will be the “chain head” and be the job that the other jobs are chained onto. It would be used as so:

$batch = Bus::batch([
            new Test1Job(),
            [
                new Test2Job(),
                new Test3Job(),
                new Test4Job(),
            ]
        ])->then(function (Batch $batch) {
            Log::info('Test Complete!');
        })->name('Test')->dispatch();

This benefits users as batching, as it works now ,provides amazing support for doing a bunch of things and doing something when they are completed.
But sometimes some of those things have to happen in a particular order BUT others can happen at any time. This makes that easier without having to add the job to the batch from within another job. Making it easier to track, at a high level, what is happening and in what, if any, sequence.

Added is() method to 1-1 relations for model comparison

This will adds replicates the is() and isNot()methods of the Illuminate\Database\Eloquent\Model to the 1-1 Eloquent relations: BelongsToHasOneMorphTo and MorphOne. We can now do model comparisons between related models, without extra database calls! This is especially useful in gates/policies when we need to know if a model is owned or owns another model. Example on a PostPolicy with a simple BelongsTo relationship:

public function publish(User $user, Post $post)
{
    // Before: foreign key is leaking from the post model
    return $post->author_id === $user->id;

    // Before: performs extra query to fetch the user model from the author relation
    return $post->author->is($user);

    // After 🚀
    return $post->author()->is($user);
}

Example with a polymorphic MorphOne relationship:

// Before
return $attachment->attachable_id === $post->getKey()
    && $attachment->attachable_type === $post->getMorphClass();

// Before
return $post->attachment->is($attachment);

// After 🚀
return $post->attachment()->is($attachment);

The implementation is similar to the Model, it compares the keys, the tables, and the connections of two models. But instead of comparing the primary keys using Model::getKey(), it compares the parent key of the parent model of the relationship with the foreign key of the given model. Both key names are known to the relation instance, so the comparison is straightforward.

The only thing that is not really accurate is the type of the keys. A model usually has an integer or a string primary key, but the foreign keys are not cast to the related model’s primary key type, or sometimes the relationships do not include any primary key, but are constrained by other keys. For this reason, if one of the keys is an integer, we are casting both keys to integers before comparing them, otherwise we are comparing them as they are.

For convenience, the functionality is defined in a ComparesModels trait, so it can be used on custom relationships.
This trait needs two methods to be implemented:

  1. the getParentKey() which already existed on HasOne/MorphOne relations
  2. the getRelatedKeyFrom($model), which is new, but is quite useful because it can be reused in many places in the existing relations codebase, instead of calling $model->{$this->ownerKey}$model->{$foreign}$parent->{$this->localKey}, etc. in so many different ways. I’ve refrained myself from refactoring these calls, but I can do that in a next PR.

Added upsert to Eloquent and Base Query Builders

Laravel already supports bulk inserts, bulk insert/ignores. It’s only logical to also support bulk upserts, which are already supported on frameworks such as Rails or databases such as MongoDB. Sample usage of upsert :

DB::table('users')->upsert([
    ['id' => 1, 'email' => '[email protected]'],
    ['id' => 2, 'email' => '[email protected]'],
], 'email');

The first argument is the values to insert/update and the second argument is the column(s) that uniquely identify records. All databases except SQL Server require these columns to have a PRIMARY or UNIQUE index. This is similar to Rails upsert_all without the returning support.

Bugfixes and changes :

  • Fixed collection wrapping in BelongsToManyRelationship 
  • Fixed LengthAwarePaginator translations issue
  • Improve schedule:work command
  • Guard against invalid guard in make:policy
  • Fixed router inconsistency for namespaced route groups

More information about this release v8.10.0 here, more information about Laravel framework on the official website https://laravel.com/. Released under an MIT license.

LEAVE A REPLY

Please enter your comment!
Please enter your name here