umutphp / laravel-model-recommendation

This package generates recommendation list for elequent models. It provides a simple API to work with to generate and list recommendations for a model.
MIT License
56 stars 7 forks source link
composer-package eloquent hacktoberfest laravel laravel-package machinelearning recommendation

Generate Recommendation List For Eloquent models

GitHub release (latest SemVer) WOSPM Checker Codestyle Check Test In All PHP Versions Markdown Linter

This package generates recommendation list for elequent models objects. It provides a simple API to work with to generate and list recommendations for a model.

Laravel Model Recommendation

Glosary

How To Install

Requiring The Library

composer require "umutphp/laravel-model-recommendation"

Prepare The Database

php artisan vendor:publish --provider="Umutphp\LaravelModelRecommendation\ModelRecommendationServiceProvider"
php artisan migrate

Add The Service Provider

Append the following line to the providers array in config/app.php;

Umutphp\LaravelModelRecommendation\ModelRecommendationServiceProvider::class,

Add The Trait And Interface To The Model

Add HasRecommendation trait and InteractWithRecommendation interface to the class definition of the model. Please do not forget to implement the config function of the interface.

getRecommendationConfig(): It should returns a multi dimensional array as follows with correct values. The definition of values in inner arrays are;

A sample model class definition is as follows;

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class ModelName extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'recommendation_name' => [
                'recommendation_algorithm'         => 'db_relation',
                'recommendation_data_table'        => 'recommendation_data_table',
                'recommendation_data_table_filter' => [
                    'field' => 'value'
                ],
                'recommendation_data_field'        => 'recommendation_data_field',
                'recommendation_data_field_type'   => 'recommendation_data_field_type',
                'recommendation_group_field'       => 'recommendation_group_field',
                'recommendation_count'             => 5,
                'recommendation_order'             => 'desc'
            ]
        ];
    }
}

How To Use

Here are a few short examples of what you can do.

ModelName::generateRecommendations('recommendation_name');
$recommendations = $model->getRecommendations('recommendation_name');

For these functions (generateRecommendations() and getRecommendations()) to be executed correctly, you should implement the config function described in Add The Trait And Interface To The Model section. The methods used to generate the recommendations and some use cases thay may help you are explained below.

Recommendation Generation Methods

DB Relation

This is an item based filtering (collaborative filtering) method by using the co-occurrence of the models in a data table under same group defined with a field.

Similarity

Inspired from the great articale "Building a Product Recommender System with Machine Learning in Laravel" by Oliver Lundquist.

The recommendation list is generated from a similarity calculation between models by using the field and taxonomy values of the objects.

Use Case 1

Assume that you want to get recommendations for products (sold together) in an e-commerce site. You have Product model and order_products table storing the relation between orders and products.

order_products table;

Field1 Field2 Field3 Field4 Field5 Field6
id order_id product_id product_count created_at updated_at

Product model class;

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class Product extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'sold_together' => [
                'recommendation_algorithm'         => 'db_relation',
                'recommendation_data_table'        => 'order_products',
                'recommendation_data_table_filter' => [],
                'recommendation_data_field'        => 'product_id',
                'recommendation_data_field_type'   => self::class,
                'recommendation_group_field'       => 'order_id',
                'recommendation_count'             => 5
            ]
        ];
    }
}

Function calls;

<?php
...

use App\Model\Product;

Product::generateRecommendations('sold_together');

$product1        = Product::find(1);
$recommendations = $product1->getRecommendations('sold_together');

Use Case 2

Assume that you want to get recommendations for users in a dating site. You have User model and user_friends table storing the relation between users.

user_friends table;

Field1 Field2 Field3 Field4 Field5
id user_id friend_id created_at updated_at
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class User extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'possible_match' => [
                'recommendation_algorithm'         => 'db_relation',
                'recommendation_data_table'        => 'user_friends',
                'recommendation_data_table_filter' => [],
                'recommendation_data_field'        => 'friend_id',
                'recommendation_data_field_type'   => self::class,
                'recommendation_group_field'       => 'user_id',
                'recommendation_count'             => 5
            ]
        ];
    }
}

Function calls;

<?php
...

use App\Model\User;

User::generateRecommendations('possible_match');

$user1           = User::find(1);
$recommendations = $user1->getRecommendations('possible_match');

Use Case 3

A use case for generating recommendations from product similarity. We have products and category table as follows and a one-to-one relation between them.

products table;

Field1 Field2 Field3 Field4 Field5
id color material price category_id

category table;

Field1 Field2
id name
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class Product extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'similar_products' => [
                'recommendation_algorithm'            => 'similarity',
                'similarity_feature_weight'           => 1,
                'similarity_numeric_value_weight'     => 1,
                'similarity_numeric_value_high_range' => 1,
                'similarity_taxonomy_weight'          => 1,
                'similarity_feature_attributes'       => [
                    'material', 'color'
                ],
                'similarity_numeric_value_attributes' => [
                    'price'
                ],
                'similarity_taxonomy_attributes'      => [
                    [
                        'category' => 'name'
                    ]
                ],
                'recommendation_count'                => 2,
                'recommendation_order'                => 'desc'
            ]
        ];
    }

    /**
     * Get the category associated with the product.
     */
    public function category()
    {
        return $this->hasOne(Category::class);
    }
}

Use Case 4

A hybrid use case (Use case 2 + Use case 3) containing both of the algorithms.

products table;

Field1 Field2 Field3 Field4 Field5
id color material price category_id

category table;

Field1 Field2
id name

order_products table;

Field1 Field2 Field3 Field4 Field5 Field6
id order_id product_id product_count created_at updated_at
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class Product extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'sold_together' => [
                'recommendation_algorithm'         => 'db_relation',
                'recommendation_data_table'        => 'order_products',
                'recommendation_data_table_filter' => [],
                'recommendation_data_field'        => 'product_id',
                'recommendation_data_field_type'   => self::class,
                'recommendation_group_field'       => 'order_id',
                'recommendation_count'             => 5,
                'recommendation_order'             => 'random'
            ],
            'similar_products' => [
                'recommendation_algorithm'            => 'similarity',
                'similarity_feature_weight'           => 1,
                'similarity_numeric_value_weight'     => 1,
                'similarity_numeric_value_high_range' => 1,
                'similarity_taxonomy_weight'          => 1,
                'similarity_feature_attributes'       => [
                    'material', 'color'
                ],
                'similarity_numeric_value_attributes' => [
                    'price'
                ],
                'similarity_taxonomy_attributes'      => [
                    [
                        'category' => 'name'
                    ]
                ],
                'recommendation_count'                => 2,
                'recommendation_order'                => 'desc'
            ]
        ];
    }

    /**
     * Get the category associated with the product.
     */
    public function category()
    {
        return $this->hasOne(Category::class);
    }
}

Use Case 5

A use case for using with Laravel Follow package (User follow unfollow system for Laravel).

Laravel Follow package stores the data in user_follower table (Please check the migration). So, the implementation of the config function should be as follows;

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class User extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'users_to_be_followed' => [
                'recommendation_algorithm'         => 'db_relation',
                'recommendation_data_table'        => 'user_follower',
                'recommendation_data_table_filter' => [],
                'recommendation_data_field'        => 'following_id',
                'recommendation_data_field_type'   => self::class,
                'recommendation_group_field'       => 'follower_id',
                'recommendation_count'             => 5
            ]
        ];
    }
}

Function calls;

<?php
...

use App\Model\User;

User::generateRecommendations('users_to_be_followed');

$user1           = User::find(1);
$recommendations = $user1->getRecommendations('users_to_be_followed');

Use Case 6

A use case for using with Laravel Acquaintances package (to manage friendships (with groups), followships along with Likes, favorites etc.).

Laravel Acquaintances package stores the data in interactions table (Please check the migration). So, the implementation of the config function should be as follows;

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Umutphp\LaravelModelRecommendation\InteractWithRecommendation;
use Umutphp\LaravelModelRecommendation\HasRecommendation;

class User extends Model implements InteractWithRecommendation
{
    use HasFactory, HasRecommendation;

    public static function getRecommendationConfig() :array
    {
        return [
            'users_to_follow' => [
                'recommendation_algorithm'         => 'db_relation',
                'recommendation_data_table'        => 'interactions',
                'recommendation_data_table_filter' => [
                    'relation' => 'follow' // possible values are follow/like/subscribe/favorite/upvote/downvote. Choose the one that you want to generate the recommendation for.
                ],
                'recommendation_data_field'        => 'subject_id',
                'recommendation_data_field_type'   => self::class,
                'recommendation_group_field'       => 'user_id',
                'recommendation_count'             => 5
            ]
        ];
    }
}

Function calls;

<?php
...

use App\Model\User;

User::generateRecommendations('users_to_follow');

$user1           = User::find(1);
$recommendations = $user1->getRecommendations('users_to_follow');

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.