Laravel common code collection

Time:2020-10-27

I have been using laravel for a long time, and I have used many versions. The following code is collected in daily projects and shared as notes. I hope it will be of some use to you.
Note: the version is not marked. If there is any incompatibility, you can fine tune it.

verification

I’m not used to having a separate request verification class. I’m more used to the following writing method:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;

    $inputData = $request->only(['name', 'address', 'mobile', 'draw_id']);
    $messages = [
        'required '= >': attribute is required ',
         'Int' = > ': wrong attribute parameter type',
         'MAX '= >': attribute length cannot exceed: size ',
    ];
    $validator = Validator::make($inputData, [
        'draw_id' => 'required|int',
        'name' => 'required',
        'mobile' => 'required',
        'address' => 'required',
    ], $messages,[
        'name' = >'name of consignee ',
        'mobile '= >'mobile number',
        'address' = >'receiving address',
    ]);

    if ($validator->fails()) {
        return self::response([], current($validator->errors()->all()), 2);
    }

Custom validation

For example, the commonly used mobile phone number verification:

php artisan make:rule Mobile

Then change it:

/**
     *Mobile main code
     *Is the validation passed
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        //
        return preg_match('/^1\d{10}$/', $value);
    }

    /**
     *Error message
     *
     * @return string
     */
    public function message()
    {
        Return 'mobile phone number format is incorrect';
    }

And then use it like this:

$columns = [
    'college' => 'required|max:32',
    'mobile' => ['required', new Mobile()],
    'qq' => 'required',
];

ORM

Association query

  • one-on-one
//Model definition, associated foreign key
class User extends Model
{
    ...
    
    public function userIntegral()
    {
        return $this->hasOne('App\Models\UserIntegral', 'user_id', 'id');
    }
}
//Query with
(new User())->with('userIntegral')->orderBy('id', 'desc')->paginate($limit);
  • One to many
//Model
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Hotel extends Model
{
    public function orders()
    {
        return $this->hasMany('App\Models\Order');
    }
}
//For example, query the order with status = 30 under a hotel
$hotel = Hotel::with(['orders' => function ($query) {
        $query->where('status', 30);
    }])->find(4);

Unified exception handling

This can be seen in the previous articleLaravel unified error handling as JSON

queue

Failed queue in

  • Generating tables

Build failed_ Jobs table

php artisan queue:failed-table
php artisan migrate
  • individualization

The failure can be handled separately in the job, and the job failure will also be written to the failed generated above_ Jobs table

/**
*Process of task failure
*
* @param  Exception  $exception
* [@return](https://learnku.com/users/31554) void
*/
public function failed(Exception $exception)
{
    //Processing
}

Retry Queue

Sometimes there are loopholes in the code, and the queue execution may fail. At this time, we need to try again.

  • View all failures
php artisan queue:failed
  • Retrying all failures
php artisan queue:retry all
  • Retrying a single failure
php artisan queue:retry 13
  • Empty failed (this is not allowed for important queue data)
php artisan queue:flush

In addition, it is not convenient to operate manually. You can set a cron to try all failures on a regular basis. However, it is necessary to pay attention to the message reminder, so as to prevent the queue from being retried and failing all the time, which will affect the normal queue performance.

Other common codes

File upload OSS

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Controller;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use OSS\OssClient;
use OSS\Core\OssException;

class UploadController extends Controller
{
    public function index(Request $request)
    {
        $file = $request->file('file');
        if ($file->isValid()) {
            $ext = $file->getClientOriginalExtension();
            $realPath = $file->getRealPath();
            $filepath = config('app.env').'/' . md5(uniqid('', true));

            $result = $this->uploadOss($realPath, $filepath.".".$ext);

            if ($result['code']) {
                return response(['code' => 2, 'msg' => $result['msg']]);
            } else {
                Return response (['code '= > 0,' MSG '= >'upload succeeded','data '= >)[
                    'filepath' => $result['data']['url'],
                    'data' => $request->all()
                ]]);
            }
        }
    }

    /**
     *Upload OSS
     *@ param $filepath current path
     *@ param $object predefined file name, can contain folder
     * [@return](https://learnku.com/users/31554) array
     */
    public function uploadOss($filePath, $object)
    {
        $accessKeyId = config('filesystems.disks')[config('filesystems.default')]['access_key'];
        $accessKeySecret = config('filesystems.disks')[config('filesystems.default')]['secret_key'];
        $endpoint = config('filesystems.disks')[config('filesystems.default')]['endpoint'];
        $bucket= config('filesystems.disks')[config('filesystems.default')]['bucket'];
        $url = config('filesystems.disks')[config('filesystems.default')]['host'];

        try{
            $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
            $ossClient->uploadFile($bucket, $object, $filePath);
            return [
                'code' => 0,
                'data' => [
                    'url' => $url.'/'.$object
                ]
            ];
        } catch(OssException $e) {
            return [
                'code' => 1,
                'msg' => $e->getMessage()
            ];
        }
    }
}


// -------
//Configuration
'oss' => [
  'driver' => 'oss',
  'root' => '',
  'access_key' => env('OSS_ACCESS_KEY'),
  'secret_key' => env('OSS_SECRET_KEY'),
  'endpoint' => env('OSS_ Endpoint '), // use SSL to set the following settings: https://oss-cn-beijing.aliyuncs.com
  'bucket' => env('OSS_BUCKET'),
  'isCName' => env('OSS_ IS_ CNAME ', false), // if iscname is false, endpoint should configure the domain name provided by OSS, such as:'oss CN'- beijing.aliyuncs.com `Otherwise, it is a user-defined domain name, CNAME or CDN. Please configure and bind the bucket in the alioss background
  'host' => env('OSS_HOST', '')
],

JSON output

protected static $code = 0;
protected static $msg = 'ok';

public function response($data = [], $msg = '', $code = 0)
{
    if (is_null($data)) {
        $data = new \stdClass();
    }
    return response()->json([
        'code' => $code? $code : self::$code,
        'msg' => $msg? $msg : self::$msg,
        'data' => $data,
    ], 200);
}

Process lock

  • Normal version
//$autodel field deletion, $TTL expiration time, seconds
public function  processLock($key, $autoDel = true, $ttl = 60)
{
    $key = 'processLock:'.$key;
    //Different versions or redis extensions will be slightly different. You can adjust the code by yourself
    if (Redis::Command('set', [$key, 1, 'EX', $ttl, 'NX'])) {
        if ($autoDel) {
            register_shutdown_function(function () use ($key) {
                Redis::del($key);
            });
        }
        
        return true;
    }
    return false;
}
  • Lua version
    public function getScript()
    {
        return <<<LUA
        local ret = redis.call("setnx", KEYS[1], ARGV[1])
        if ret == 1 then
            return redis.call("expire", KEYS[1], ARGV[2])
        else
            return 0
        end
LUA;
    }


    public function processLock($key, $autoDel = true, $ttl = 60)
    {
        if (Redis::eval($this->getScript(), 1, $key, 1, $ttl)) {
            if ($autoDel) {
                register_shutdown_function(function () use ($key) {
                    Redis::del($key);
                });
            }
            
            return true;
        }
        return false;
    }

Note: the first 1 in the redis:: Eval line indicates the number of keys to distinguish keys from argv.

JWT

Laravel with JWT

The system notifies the nail

We can use the queue to put some important notices to the nail. The main code is as follows:

<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use GuzzleHttp\Client;


class SystemNotify implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    private $title;

    private $content;

    private $type;

    private $robot;

    const DD_URL = 'https://oapi.dingtalk.com';

    /**
     * Create a new job instance.
     *
     * @param $title
     * @param string $content
     * @param string $type text, markdown
     * @param int $robot
     */
    public function __construct($title, $content = '', $type = 'markdown', $robot = 1)
    {
        //Using systemnotify queue alone
        $this->queue = 'SystemNotify';
        $this->title = $title;
        $this->content = $content;
        $this->type = $type;
        $this->robot = $robot;

    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //It is suggested that the nail robot should use IP segment setting, which is more secure
        switch ($this->type){
            case 'markdown':
                $params = [
                    'msgtype' => $this->type,
                    $this->type => [
                        'title '= > $this - > title.' [keyword] ',
                        'text' => $this->content
                    ]
                ];
                break;
            default:
                $params = [
                    'msgtype' => $this->type,
                    $this->type => [
                        'content' = > $this - > content. '[keyword]',
                    ]
                ];
                break;

        }
        $params = json_encode($params, JSON_UNESCAPED_UNICODE);


        $uri = self::URL_MAPPING[$this->robot];
        $this->getClient()->request('POST', $uri, [
            'headers' => [
                'Content-Type' => 'application/json;charset=utf-8'
            ],
            'body' => $params
        ]);
    }

    //Modify access according to different nail group notification_ The token parameter is OK
    const URL_MAPPING = [
        1 => '/robot/[email protected]',
        2 => '/robot/[email protected]'
    ];

    public function getClient()
    {
        return new Client([
            'base_uri' => 'https://oapi.dingtalk.com',
            'timeout'  => 30,
            'verify' => false
        ]);
    }
}

Note: the content of the notice can be customized, and the operation of adding intelligent robot is relatively simple, so we don’t need to repeat it

Background operation log

Using larravel middleware to add an operation log to the background

Excel

Implementation of Excel import with laravel6 and Maat website Excel

Implementation of Excel export with laravel6 and Maat website Excel

In succession, we are adding

Recommended Today

Java security framework

The article is mainly divided into three parts1. The architecture and core components of spring security are as follows: (1) authentication; (2) authority interception; (3) database management; (4) authority caching; (5) custom decision making; and;2. To build and use the environment, the current popular spring boot is used to build the environment, and the actual […]