0%

We have two model class, one is User the other one is Division, user belongs to one division and division has many users.
Users table only has one column named division_id, the other division information like “division name” we can get from Divisions table.

1
2
3
4
5
6
7
8
9
10
11
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->unsignedBigInteger('division_id')->nullable();
$table->timestamps();
});

1
2
3
4
5
6
Schema::create('divisions', function (Blueprint $table) {
$table->id();
$table->string('name', 128);
$table->timestamps();
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\Model; //by default this line is not here, you need to add it manually

class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;

/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
'division_id',
];

/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];

/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];

public function division()
{
return $this->belongsTo(Division::class);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Division extends Model
{
use HasFactory;

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
];

/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'id' => 'integer',
];


public function users()
{
return $this->hasMany(User::class);
}
}

In the blade file if you try to use user->division()->name it will throw an error.

1
#message: "Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$name"

Instead you should use user->division->name to get the name of the division, but if you directly use the property name name it will throw an other error, beacuse the default Laravel user model do not import Eloquent Model.

1
Attempt to read property "name" on null

To solve this problem we need to add a this line to your User model file.

 use Illuminate\Database\Eloquent\Model;

Intergrate multi-language support in Laravel is prettry easy. This implementation is based on a video: Switch languages in Laravel with Localization in 5.8 made easy !
Thanks Bert De Swaef!

We can simply implement multi-language support in Laravel by the following steps.

Route set up

Open your route file routes\web.php and add the following code:

1
2
3
4
Route::get('/lang/{locale}', function ($locale) {
session()->put('locale', $locale);
return redirect()->back();
});

Add middleware

1
php artisan make:middleware Localization

Open the file app/Http/Middleware/Localization.php and edit as the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App;

class Localization
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
//check if session has locale
if (session()->has('locale')) {
//set locale
App::setLocale(session('locale'));
}
return $next($request);
}
}

Then add the Localization middleware to the middlewareGroups section of app/Http/Kernel.php file as the following code:

1
2
3
4
5
6
protected $middlewareGroups = [
'web' => [
...
\App\Http\Middleware\Localization::class,
],

Read more »

If you want to generate PDF file in your Laravel project, you may choose this package barryvdh/laravel-dompdf. Its a laravel wrapper for the most famous PDF generater packeage dompdf. With this package, you can easily generate PDF file with a view with just 3 lines of code.

Here is an example of how to generate PDF file.

Install the package

First use composer to install the package.

1
composer require barryvdh/laravel-dompdf

After updating composer, add the ServiceProvider to the providers array in config/app.php

1
2
3
4
'providers' => [
...
Barryvdh\DomPDF\ServiceProvider::class,
],

You can optionally use the facade for shorter code. Add this to your facades:

1
2
3
4
'aliases' => [
...
'PDF' => Barryvdh\DomPDF\Facade::class,
],

PDF view blade file

You can make a view file with plain html, in this example we generate a pdf file with a table.

  1. Create a view file purchase_order_pdf.blade.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <!DOCTYPE html>
    <html lang="en">

    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Purchase Control System</title>
    <style>
    body {
    font-family: yahei;
    font-size: 12px;
    margin-top: 0 !important;
    padding-top: 0 !important;
    }

    </style>
    </head>

    <body>
    @if (Auth::guest())
    <div>You need to login first.</div>
    @else
    <div class="main">
    <table style="border: 1px solid black;border-collapse: collapse;" width="100%">
    <thead>
    <tr>
    <th style="border: 1px solid black; width:5%">ID</th>
    <th style="border: 1px solid black; width:50%">Item Name/Description</th>
    <th style="border: 1px solid black; width:10%">Quantity</th>
    <th style="border: 1px solid black; width:10%">Price</th>
    <th style="border: 1px solid black; width:5%">Discount</th>
    <th style="border: 1px solid black; width:5%">Tax</th>
    <th style="border: 1px solid black; width:15%">Amount</th>
    </tr>
    </thead>
    <tbody>
    @foreach ($items as $item)
    <tr align="center">
    <td style="border: 1px solid black">{{ $loop->iteration }}</td>
    <td style="border: 1px solid black ;" align="left">
    <strong>{{ $item->name }}</strong><br><span
    style="white-space: pre-wrap;">{{ $item->description }}</span>
    </td>
    <td style="border: 1px solid black">{{ $item->quantity }}</td>
    <td style="border: 1px solid black">{{ $item->price }}</td>
    <td style="border: 1px solid black">{{ $item->discount }}</td>
    <td style="border: 1px solid black">{{ $item->tax }}</td>
    <td style="border: 1px solid black">{{ $item->sub_total }}</td>
    </tr>
    @endforeach
    </tbody>
    </table>
    </div>
    @endif
    </body>

    </html>

    Read more »

The Chinese translation of the validation messages for Laravel 8.

Download the zip file here

The translation files will place at resources\lang\cn folder and change config/app.php 'locale' => 'en', to 'locale' => 'cn',

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<?php

return [

/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/

'accepted' => ':attribute 必须填写',
'accepted_if' => ':attribute 在 :other 是 :value. 的时候必须填写',
'active_url' => ':attribute 必须是一个合法的URL',
'after' => ':attribute 必须是 :date 之后的一个日期',
'after_or_equal' => ':attribute 必须是 :date 或之后的一个日期',
'alpha' => ':attribute 只能包含字母',
'alpha_dash' => ':attribute 只能包含字母、数字、中划线或下划线',
'alpha_num' => ':attribute 只能包含字母或数字',
'array' => ':attribute 必须是一个数组',
'before' => ':attribute 必须是 :date 之前的一个日期',
'before_or_equal' => ':attribute 必须是 :date 或之前的一个日期',
'between' => [
'numeric' => ':attribute 必须在 :min 和 :max 之间',
'file' => ':attribute 必须在 :min 和 :max KB 之间',
'string' => ':attribute 必须在 :min 和 :max 个字符之间',
'array' => ':attribute 必须在 :min 和 :max 项之间',
],
'boolean' => ':attribute 字符必须是 true 或 false',
'confirmed' => ':attribute 二次确认不匹配',
'current_password' => '密码不正确.',
'date' => ':attribute 必须是一个合法的日期',
'date_equals' => ':attribute 必须是一个日期且等于 :date.',
'date_format' => ':attribute 与给定的格式 :format 不一致',
'declined' => ':attribute 必须被拒绝.',
'declined_if' => ':attribute 当 :other 是 :value 时必须被拒绝',
'different' => ':attribute 和 :other 必须不同',
'digits' => ':attribute 必须是 :digits 位',
'digits_between' => ':attribute 必须在 :min 至 :max 位之间',
'dimensions' => ':attribute 无效的图片尺寸',
'distinct' => ':attribute 字段具有重复址',
'email' => ':attribute 必须是一个合法的电子邮件地址',
'ends_with' => ':attribute 必须以此结尾: :values.',
'exists' => '选定的 :attribute 是无效的',
'file' => ':attribute 必须是一个文件',
'filled' => ':attribute 字段是必填项',
'gt' => [
'numeric' => ':attribute 必须大于 :value.',
'file' => ':attribute 必须大于 :value 千字节.',
'string' => ':attribute 必须大于 :value 字符.',
'array' => ':attribute 必须大于 :value 项目.',
],
'gte' => [
'numeric' => ':attribute 必须大于等于 :value.',
'file' => ':attribute 必须大于等于 :value 千字节.',
'string' => ':attribute 必须大于等于 :value 字符.',
'array' => ':attribute 必须包含 :value 项目或更多.',
],
'image' => ':attribute 必须是 jpeg, png, bmp, 或者 gif 格式图像',
'in' => '选定的 :attribute 是无效的',
'in_array' => ':attribute 字段在 :other 中不存在',
'integer' => ':attribute 必须是整数',
'ip' => ':attribute 必须是一个合法的IP地址',
'ipv4' => ':attribute 必须是一个合法的 IPv4 地址',
'ipv6' => ':attribute 必须是一个合法的 IPv6 地址',
'json' => ':attribute 必须是一个合法的 JSON 字符串',
'lt' => [
'numeric' => ':attribute 必须小于 :value.',
'file' => ':attribute 必须小于 :value 千字节.',
'string' => ':attribute 必须小于 :value characters.',
'array' => ':attribute 必须包含少于 :value 项目.',
],
'lte' => [
'numeric' => ':attribute 必须小于等于 to :value.',
'file' => ':attribute 必须小于等于 to :value 千字节.',
'string' => ':attribute 必须小于等于 to :value characters.',
'array' => ':attribute 必须包含不多于 :value 项目.',
],
'max' => [
'numeric' => ':attribute 的最大长度为 :max.',
'file' => ':attribute 大小至少为 :max ',
'string' => ':attribute 的长度至少为 :max 字符',
'array' => ':attribute 至少为 :max 项',
],
'mimes' => ':attribute 的文件类型必须为 type: :values.',
'mimetypes' => ':attribute 的文件类型必须为 type: :values.',
'min' => [
'numeric' => ':attribute 的最小长度为 :min 位',
'file' => ':attribute 大小至少为 :min ',
'string' => ':attribute 的最小长度为 :min 字符',
'array' => ':attribute 至少有 :min 项',
],
'multiple_of' => ':attribute 必须为倍数 :value.',
'not_in' => '选定的 :attribute 是无效的',
'not_regex' => ':attribute 格式不正确.',
'numeric' => ':attribute 必须是数字',
'password' => '密码不正确.',
'present' => ':attribute 字段必须展现.',
'prohibited' => ':attribute 字段是被禁止的.',
'prohibited_if' => ':attribute 字段是被禁止的在 :other 是 :value.',
'prohibited_unless' => ':attribute 字段是被禁止的除非 :other 是在 :values.',
'prohibits' => ':attribute 字段是被禁止的如果 :other 被展现.',
'regex' => ':attribute 格式是无效的',
'required' => ':attribute 字段是必须的',
'required_if' => ':attribute 字段是必须的当 :other 是 :value.',
'required_unless' => ':attribute 字段是必须的除非 :other 是在 :values.',
'required_with' => ':attribute 字段是必须的当 :values 存在时',
'required_with_all' => ':attribute 字段是必须的当 :values 存在时',
'required_without' => ':attribute 字段是必须的当 :values 存在时',
'required_without_all' => ':attribute 字段是必须的当没有一个 :values 存在时',
'same' => ':attribute 和 :other 必须',
'size' => [
'numeric' => ':attribute 必须是 :size 位',
'file' => ':attribute 必须是 :size ',
'string' => ':attribute 必须是 :size 个字符',
'array' => ':attribute 必须包括 :size 项',
],
'starts_with' => ':attribute 必须以以下内容开头: :values.',
'string' => ':attribute 必须是一个字符串',
'timezone' => ':attribute 必须是一个有效的时区',
'unique' => ':attribute 已存在',
'uploaded' => ':attribute 上传失败',
'url' => ':attribute 无效的格式',
'uuid' => ':attribute 必须是一个有效的 UUID.',

/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/

'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],

/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/

'attributes' => [],

];


Want to creat a multi-tenancy application? You can use the Tenancy package to create a multi-tenancy application with multiple database and multiple domains support.

Here is a simple instruction for you to create a multi-tenancy application in windows system.

Requirement

  • PHP 8.0+
  • Laravel 8.0+
  • spatie/laravel-multitenancy 2.0+

Installation

Create a new laravel project and add neccessary packages then publish some config files

1
2
3
4
5
6
7
8
laravel new mulittenancy
cd mulittenancy
composer require laravel/breeze --dev
php artisan breeze:install
npm install && npm run dev
composer require "spatie/laravel-multitenancy:^2.0"
php artisan vendor:publish --provider="Spatie\Multitenancy\MultitenancyServiceProvider" --tag="multitenancy-config"
php artisan vendor:publish --provider="Spatie\Multitenancy\MultitenancyServiceProvider" --tag="multitenancy-migrations"

Create databases and run the migration

For simplicity we just manually create the 3 databases by HeidiSQL, you can implement your own code to create tenant database on the fly. Open your favorite mysql client app create 3 databases, names are tenant_1, tenant_2 and landlord .

Read more »