【laravel項目】@13 解決訪問器與數據填充衝突

所用的知識點

1.遷移文件的建立
2.數據填充
3.經過觀察者監聽模型事件
4.註冊觀察者
5.模型php

素材須要

數據庫

字段 value
id 分類id
name 分類名
parent_id 父級id
image 分類圖標
level 當前分類的等級
sort 排序
possess 該分類的全部父類

GoodsCategory模型

在這裏插入圖片描述
在category定義一個與上級以及子級的模型關聯。而後添加三個獲取器;1.獲取全部的上級id,2.根據獲取的id獲取子級的全部上級,而且根據level排序。 至於以後一個只是獲取全部的上級名稱數據庫

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 * 商品分類
 */
class GoodsCategory extends Model
{
    protected  $fillable = ['name', 'category_image'];

    public function parent()
    {
        //反向關聯
        return $this->belongsTo(GoodsCategory::class);
    }

    public function children() {
        //一對多
        return $this->hasMany(GoodsCategory::class, 'parent_id');
    }

    //定義一個訪問器,獲取全部祖先類目的ID值
    public function getPossessIdsAttribute()
    {
        //array_filter 將數組中的空值移除
        return array_filter(explode('-', trim($this->possess, '-')));
    }

    //定義一個訪問器,獲取祖先類目並按層級排序
    public function getAncestorsAttribute()
    {
        return GoodsCategory::query()
            ->whereIn('id', $this->possess_ids)
            //按層級排序
            ->orderBy('level')->get();
    }

    //定義一個訪問器,獲取以 - 爲分隔的全部祖先類目的名稱以及當前類目的名稱
    public function getFullNameAttribute()
    {
        return $this->ancestors //獲取全部祖先類
            ->pluck('name') //獲取祖先類目的name 字段爲一個數組
            ->push($this->name)//獲取當前類目的 name 字段加到數組的末尾
            ->implode(' - '); //用 - 符合將數組的值組成一個字符串
    }

    public function getLevelAttribute($value) {
        $data = [
            '0' => '根目錄',
            '1' => '二級',
            '2' => '三級',
        ];
        return (is_null($value)) ? $data : $data[$value];
    }

    /**
     * 測試方法
     * @return [type] [description]
     */
    public function test() {
        $category = GoodsCategory::where('id', 10)->first();
        $data = $category->ancestors->toArray();
        return $data;
    }
}

建立GoodsCategoryTableSeeder.php數據填充文件

命令:php artisan make:seeder GoodsCategoryTableSeeder
在這裏插入圖片描述數組

<?php
use App\Models\GoodsCategory;
use Illuminate\Database\Seeder;

class GoodsCategoryTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $categories = [
            [
                'name'     => '手機配件',
                'sort'     => '0',
                'children' => [
                    [
                        'name'     => '手機殼',
                        'sort'     => '0',
                        'children' => [
                            [
                                'name' => '華爲V10手機',
                                'sort'     => '0',
                            ],
                            [
                                'name' => '小米',
                                'sort'     => '1',
                            ],
                        ],
                    ],
                    [
                        'name'     => '數據線',
                        'sort'     => '4',
                        'children' => [
                            [
                                'name' => '蘋果數據線',
                                'sort'     => '0',
                            ],
                            [
                                'name' => '安卓數據線',
                                'sort'     => '1',
                            ],
                        ],
                    ],
                    [
                        'name'     => '耳機',
                        'sort'     => '0',
                        'children' => [
                            [
                                'name' => '有線耳機',
                                'sort'     => '1',
                            ],
                            [
                                'name' => '藍牙耳機',
                                'sort'     => '0',
                            ],
                        ],
                    ],
                ],
            ],
            [
                'name'     => '六星果園',
                'sort'     => '0',
                'children' => [
                    [
                        'name'     => '國產水果',
                        'sort'     => '0',
                        'children' => [
                            [
                                'name' => '蘋果',
                                'sort'     => '0',
                            ],
                            [
                                'name' => '梨',
                                'sort'     => '1',
                            ],
                        ],
                    ],
                ]
            ]
        ];
        foreach ($categories as $data) {
            $this->createCategory($data);
        }

    }
    public function createCategory($data, $parent = null)
    {
        // 建立一個分類
        $category = new GoodsCategory([
            'name' => $data['name'],
            'sort' => $data['sort'],
        ]);
        // 若是有父級參數,表明有父類目
        if (!is_null($parent)) {
            // 將模型實例與給定的父實例關聯。
            $category->parent()->associate($parent);
        }
        // 保存到數據庫
        $category->save();
        // 若是有children字段而且 children字段是一個數組
        if (isset($data['children']) && is_array($data['children'])) {
            foreach ($data['children'] as $child) {
                $this->createCategory($child, $category);
            }
        }
    }
}

建立GoodsCategoryObserver.php觀察者

命令:php artisan make:observer GoodsCategoryObserver --model=GoodsCategory
在這裏插入圖片描述app

<?php

namespace App\Observers;

use Log;
use App\Models\GoodsCategory;

class GoodsCategoryObserver
{
    public function creating(GoodsCategory $goodsCategory) {
        //若是建立的是一個根類目
        if (is_null($goodsCategory->parent_id)) {
            //講層級設置爲0
            $goodsCategory->level = 0;
            //將path 設爲 -
            $goodsCategory->possess = '-';
        }else {
            //將層級設爲父類目層級 + 1
            $goodsCategory->level = $goodsCategory->parent->level +1;
            // 將path 設爲父級目的的PATH 追加父級的id 並最後 跟上一個  -  分隔符
            $goodsCategory->possess = $goodsCategory->parent->possess.$goodsCategory->parent_id.'-';

        }
    }
    /**
     * Handle the goods category "created" event.
     *
     * @param  \App\GoodsCategory  $goodsCategory
     * @return void
     */
    public function created(GoodsCategory $goodsCategory)
    {

    }

    /**
     * Handle the goods category "updated" event.
     *
     * @param  \App\GoodsCategory  $goodsCategory
     * @return void
     */
    public function updated(GoodsCategory $goodsCategory)
    {
        //
    }

    /**
     * Handle the goods category "deleted" event.
     *
     * @param  \App\GoodsCategory  $goodsCategory
     * @return void
     */
    public function deleted(GoodsCategory $goodsCategory)
    {
        //
    }

    /**
     * Handle the goods category "restored" event.
     *
     * @param  \App\GoodsCategory  $goodsCategory
     * @return void
     */
    public function restored(GoodsCategory $goodsCategory)
    {
        //
    }

    /**
     * Handle the goods category "force deleted" event.
     *
     * @param  \App\GoodsCategory  $goodsCategory
     * @return void
     */
    public function forceDeleted(GoodsCategory $goodsCategory)
    {
        //
    }
}

建立數據庫遷移文件

php artisan make:mmigration create_goods_category_table --create=goods_category
在這裏插入圖片描述ide

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateGoodsCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('goods_categories', function (Blueprint $table) {
            $table->increments('id')->comment('商品類別主鍵id');
            $table->string('name')->comment('類別名稱');
            $table->integer('parent_id')->default(0)->comment('父級類別id');
            $table->string('image')->nullable()->comment('分類圖片');
            $table->integer('level')->default(0)->comment('分類等級');
            $table->integer('sort')->default(0)->comment('分類排序');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('goods_categories');
    }
}

註冊觀察者

命令:php artisan make:provider ModelObserverServiceProvider
在這裏插入圖片描述測試

<?php

namespace App\Providers;

use App\Observers\GoodsCategoryObserver;
use App\Models\GoodsCategory;
use Illuminate\Support\ServiceProvider;

class ModelObserverProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        GoodsCategory::observe(GoodsCategoryObserver::class);
    }
}

而後在app裏邊註冊進去便可
在這裏插入圖片描述this

重現數據填充與訪問器衝突

執行數據填充命令

php artisan db:seed --class=GoodsCategoryTableSeeder
在這裏插入圖片描述
而後打開數據庫
在這裏插入圖片描述url

日誌檢測問題

咱們會發現咱們自定義的數據都沒有進去,只進去了第一行,這是爲何呢!
咱們能夠看到有個一報錯信息是 A non-numeric value encountered,而且報到了觀察者的19行,咱們在這裏寫個日誌看看緣由
在這裏插入圖片描述
在把數據填充的命令執行一次
php artisan db:seed --class =GoodsCategoryOberserver
一樣也給出了這裏的報錯信息,那麼我們看看這level字段到底怎麼回事
在這裏插入圖片描述spa

檢測level字段的問題

能夠看到在模型裏邊定義了一個訪問器來從新定義了level字段,那麼問題就在這裏了,這個時候咱們在註釋了之後去執行填充命令
在這裏插入圖片描述
執行
在這裏插入圖片描述
查看數據庫
這個時候就是能夠的了
在這裏插入圖片描述.net

解決訪問器與數據填充時的衝突

雖然咱們在上邊解決了這個問題,可是咱們定義的這個訪問器是在後臺顯示數據的時候使用的。其實數據填充出現的問題,也就是咱們在後臺進行數據添加時會報出的問題,因此這個問題不是一個註釋解決的

1.在模型裏邊定義一個虛擬字段
在這裏插入圖片描述
2.修改以前的訪問器
在這裏插入圖片描述
3.而後在執行填充命令
在這裏插入圖片描述
4.查看數據庫
在這裏插入圖片描述
5.打開後臺查看數據
在這裏插入圖片描述

解決設置的訪問器不能正常使用

咱們在添加了虛擬屬性後, 咱們的數據填充是好了,可是咱們在後臺獲取數據時並無做用
這個時候還須要一步操做,那就是把字段也給換成自定義的字段
在這裏插入圖片描述
這個時候在來查看,就沒有問題了
在這裏插入圖片描述

相關文章
相關標籤/搜索