Mutators 사용 시 "laravel Trying to get property 'name' of non-object" 에러 해결법

Laravel Mutators를 이용하여 Relationships 관계에 있는 컬럼의 값을 포함하고자 하는 경우 getAttribute() Magic 메서드로 포함하고자 할 컬럼을 지정해주고 $appends 프로퍼티에 명시하여야 한다.

다음 코드는 Post 모델에 Category 모델의 name 컬럼을 Post 모델의 category_name 프로퍼티로 포함하는 예제이다.

class Post extends Model
{
    protected $appends = [
        'category_name',
    ];

    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function getCategoryNameAttribute()
    {
        return $this->category->name;
    }

}

하지만, 중간중간 해당하는 Category 모델이 없는 경우 (카테고리가 삭제 된 경우) "laravel Trying to get property 'name' of non-object" 에러가 발생한다.

당연히 해당 모델이 없기 때문에 $this->category는 null이 되고,  $this->user->name 프로퍼티에 접근할 수 없기 때문에 발생하는 문제이다.

이럴 경우 다음과 같이 null 여부를 체크하면 된다.

public function getCategoryNameAttribute()
{
    return $this->user !== null ? $this->user->name : null;
}

뿐만 아니라, 개발에 있어서 이와 같은 방어적 코딩을 습관화 하는 것이 좋다.

Develop Laravel Mutators Troubleshooting

Laravel에 AdminLTE Template 통합하기

AdminLTE는 무료 오픈소스 대시보드 템플릿이다. 본 포스트에서는 AdminLTE를 Laravel과 통합하는 방법을 설명하고자 한다.

Laravel 프로젝트에서 다음 명령어를 입력하여 AdminLTE 템플릿을 npm으로 설치한다.
(bower로 설치하는 방법도 있지만 Laravel Mix와 연계를 위해 가급적 npm을 사용하는 것이 좋다고 생각한다.)

npm install admin-lte --save-dev

resources/sass 경로에 admin.scss (이름은 자유롭게 한다.) 파일을 하나 생성하고, 코드를 다음과 같이 입력한다.

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Variables
@import 'variables';

// Font awesome
@import '~font-awesome/scss/font-awesome';

// Bootstrap3
@import '~admin-lte/bower_components/bootstrap/dist/css/bootstrap.css';

// Admin LTE
@import '~admin-lte/dist/css/AdminLTE.css';
@import '~admin-lte/dist/css/skins/_all-skins.css';
@import '~admin-lte/bower_components/Ionicons/scss/ionicons';

참고로 AdminLTE 2.x 버전은 Bootstrap 3에 의존성을 가진다. 2018년 12월 기준 현재 Laravel 5.7 버전은 Bootstrap 4 버전을 내장하고 있기 때문에 기존의 app.scss 파일에 있는 Bootstrap 4를 그대로 사용하면 스타일이 깨져 나온다. admin-lte에 내장된 Bootstrap 3를 사용하도록 한다.

resources/js 경로에 admin.js 파일을 하나 생성하고 코드를 다음과 같이 입력한다.

require('admin-lte');
require('admin-lte/bower_components/chart.js');

webpack.min.js 파일은 다음과 같이 수정한다.

mix.js('resources/js/app.js', 'public/js')
    .js('resources/js/admin.js', 'public/js')

    .sass('resources/sass/app.scss', 'public/css')
    .sass('resources/sass/admin.scss', 'public/css')

    .extract([
        'jquery'
    ])

    .autoload({
        jquery: ['$', 'jQuery', 'jquery'],
    })

    .version();

중간에 autoload 메소드에 jquery를 로드하는 부분 없이 그냥 jquery만 vendor에 통합하면 Error가 발생한다.

다음으로, DashboardController를 생성한다.

php artisan make:controller DashboardController

app/Http/Controllers/DashboardController.php를 아래와 같이 편집한다.

class DashboardController extends Controller
{
    public function index()
    {
        return view('dashboard');
    }
}

routes/web.php를 아래와 같이 편집한다.

Route::get('/admin', 'DashboardController@index')->name('dashboard');

resources/views/layouts 에 다음과 같이 레이아웃 파일을 생성한다. 레이아웃 형식은 자유롭게 작성한다.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title></title>

    <link href="{{ asset('css/admin.css') }}" rel="stylesheet">
</head>
<body class="hold-transition skin-blue sidebar-mini">

<div id="app">
    @yield('content')
</div>

<!-- Scripts -->
<script src="{{ mix('js/manifest.js') }}"></script>
<script src="{{ mix('js/vendor.js') }}"></script>
<script src="{{ mix('js/admin.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>

@yield('script')
</body>
</html>

이제 resources/views에 dashboard.blade.php 뷰 파일을 생성하고 AdminLTE 데모 페이지의 소스를 참고해 내용을 채워넣는다.

js와 sass파일을 컴파일한다.

npm run prod

 

Develop Laravel AdminLTE

WARGAME Management System

 

 

작업기간

  • 2008 ~ 2009
    (솔루션 개발)

 

세부사항

  • 해킹방어대회 운영을 위한 프로그램 개발에서 아이디어를 얻어 (2007, 2008 고교생 해킹/방어 챔피언십) 웹호스팅, 서버 등 다양한 환경에 설치하여 운용할 수 있도록 솔루션화 함
  • 오픈소스로 배포 예정이었으나 개발이 중단됨,

Develop Legacy PHP Portfolio WMS