라라벨 설치와 기본 학습

2020.03.13 05:49

Admin Views:52

1. 라라벨 설치와 실행

PATH 등록 : 

윈도우( %USERPROFILE%AppDataRoamingComposervendorbin )

리눅스( $HOME/.composer/vendor/bin )

# export=$PATH:$HOME/.composer/vendor/bin

 

# composer global require laravel/installer

# composer create-project --prefer-dist laravel/laravel 프로젝트명

# laravel new 프로젝트명

 

> OCTOBER CMS 설치과정

# composer create-project october/october laravel dev-master -vvv

# chmod 775 - R laravel

# cd laravel

# vi config/cms.php.

'disableCoreUpdates' => true,

:wq

 

> 컴포저를 통해 October CMS를 설치할때 'wikimedia' 관련 오류가 출력될경우. 

# composer require wikimedia/composer-merge-plugin

> October CMS Setup

# php artisan october:install

> 관리자 페이지 접속

http://localhost/backend

 

 

> 라라벨 권한 설정

# chown -R $USER:http storage

# chown -R $USER:http bootstrap/cache

# chmod -R 775 storage

# chmod -R 775 bootstrap/cache

# cp .env.example .env

# vi .env

DB_CONNECTION=mysql

DB_HOST=127.0.0.1

DB_PORT=3306

DB_DATABASE=laravel

DB_USERNAME=root

DB_PASSWORD=

:wq

 

# php artisan passport:install

# php artisan key:generate

# php artisan migrate

# npm install

# npm run dev

# php artisan serve

# php artisan --version

 

## Synology NAS 에서 라라벨을 설치할 경우 php 기본 버전을 변경해야 한다.

## 시놀로지의 기본 PHP 버전 변경은 다음과 같이 할 수 있다.

cd /bin

rm php

sudo cp /volume1/@appstore/PHP7.3/usr/local/bin/php73 /bin/php

php -v

 

 

2. 라우트 기본 사용법

/routes/web.php

 

Route::get('/', function () {

    return view('welcome');

});

 

Route::get('posts', function() {

    $posts = AppPost::with('user')->get();

    return view('posts.index', compact('posts'));

});

 

Route::get('posts', function() {

    $posts = AppPost::get();

    $posts->load('user');

    return view('posts.index', compact('posts'));

});

'resources/views' 폴더에 welcome.blade.php 파일이 생성되어 있으며, 루트('/') 문서로 welcome.blade.php 로 연결된다.

with(string|array $relations) 메소드는 항상 엘로퀀트 모델 바로 뒤, 다른 메소드를 체인하기 전에 써야 한다. 메소드의 인자는 테이블 이름이 아니라, 모델 클래스에서 정의한 관계를 나타내는 메소드 이름임을 잘 기억하자.

가끔 엘로퀀트를 이용한 쿼리를 먼저 만들어 놓고, 나중에 관계를 로드해야 하는 경우가 발생할 수 있다. 예를 들면, 쿼리 하나를 여러 번 재사용할 경우, 앞에서는 Eager 로딩이 필요없었지만, 나중에 필요하게 되는 경우 등이 해당된다. 이때는 load(string|array $relations) 메소드를 이용할 수 있다.

 

 

터미널, 도스창에서 "php artisan route:list" 를 입력하면, 등록된 라우트 목록을 확인할 수 있다.

"IlluminateDatabaseQueryException" 에러 또는 "IlluminateContractsContainerBindingResolutionException"가 있는 경우

아래 명령어를 터미널, 도스창에서 실행한다.

 

# php artisan route:list

 

# php artisan migrate:fresh

# composer dump-autoload

# php artisan passport:install

 

# php artisan config:cache

# php artisan cache:clear

# php artisan route:clear

# php artisan view:clear

 

만약 storage 에 이미지 업로드한후, 이미지 출력이 안될 경우

# rm -rf public/storage

# php artisan storage:link

 

 

 

만약, '/home' 페이지를 추가하려면, 아래 구문을 추가한후, views 폴더아래에 home.blade.php 를 생성하면 된다.

Route::get('/home', function () {

    return view('home');

});

 

3. 뷰 기본 사용법

/resources/views/welcome.blade.php

 

@extends('layout')

 

레이아웃에서 yield('title') 로 지정된 부분에 들어가는 제목등록

@section('title')

제목

@endsection

 

레이아웃에서 yield('content') 로 지정된 부분에 들어가는 내용등록

@section('content')

내용

@endsection

extends('layout') 는 뷰에서 layout.blade.php 를 레이아웃으로 지정하였다.

섹션(section)은 레이아웃 뷰(layout.blade.php)에서 yield()에서 등록된 id 로 section()을 추가한후 내용을 입력하면 된다.

 

레이아웃 뷰 생성(layout.blade.php)

<!DOCTYPE html>

<html>

    <head>

        <meta charset="utf-8">

        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>@yield('title','기본값')</title>

    </head>

    <body>

    @yield('content')

    </body>

</html>

 

4. 라우트에서 뷰로 정보 전달

 

/routes/web.php 에서 아래 내용을 추가한다.

Route::get('/', function () {

    $colors = [ 'white', 'orange' ];

    return view('welcome', [ 'colors' => $colors ]);

});

 

비슷한 사용예

return view('welcome')->with(['colors' => $colors]);

또는

return view('welcome')->withColors($colors);

 

 /resources/views/welcome.blade.php 뷰에서 content 섹션에 다음과 같이 내용을 출력할 수 있다.

@section('content')

사용예 1)

<?php var_dump($colors); ?>

 

사용예 2)

@foreach($colors as $color)

{{ $color }}<br />

@endforeach

 

@endsection

 

5. 컨트롤러 기본 사용법

컨트롤러는 모델(DB)와 뷰(페이지) 사이에서 자료전달 역활을 담당한다.

 

컨트롤러 생성 - 터미널에서 아래와 같은 구문을 입력하여 컨트롤러를 생성한다.

# php artisan make:controller 컨트롤러명

ex) php artisan make:controller HomeController

생성된 컨트롤러 경로 : /app/Http/Controllers/HomeController.php

아래 구문을 컨트롤러에 추가한다.

class HomeController extends Controller

{

    public function index() {

        $colors = [ 'white', 'orange' ];

        return view('welcome', [ 'colors' => $colors ]);

    }

}

 

라우트(web.php) 에서 다음과 같이 컨트롤러를 사용할 수 있다.

Route::get('/', 'HomeController@index');

 

RESTful Resource Controller 만들기

Route::resource('/sketchbook','SketchbookController');

# php artisan make:controller SketchbookController --resource

 

 

6. 마이그레이트 사용법

DB 테이블 생성

# php artisan migrate

생성된 테이블 삭제

# php artisan migrate:rollback

DB 테이블을 삭제한후 다시 생성한다.

# php artisan migrate:fresh

새로운 테이블 생성

# php artisan make:migration create_sketchbook_table

database/migrations 폴더아래에 '생성한날짜_create_sketchbook_table.php' 라는 파일이 자동 생성된다.

 

* 위에서 생성한 테이블을 마이그레이트를 하면 DB에 새로운 테이블이 생성된다.

# php artisan migrate

# php artisan db:seed

 

* 사용자 추가

# php artisan tinker

factory(AppUser::class)->make();

factory(AppUser::class, 2)->create();

factory(AppUser::class)->make()

 

7. 모델 사용법

모델은 DB 자료 전달과 관리하는 역활을 한다.

일반적으로 하나의 테이블에 하나의 모델을 사용한다.

# php artisan make:model Sketchbook

# php artisan make:model Sketchbook -c -m

생성된 모델 경로 - /app/Sketchbook.php

옵션 -c -m 은 c 는 컨트롤러, m 은 마이그레이션을 한꺼번에 생성하는 옵션이다.

 

컨트롤러(HomeController.php)에 아래 구문을 추가한다.

public function sketch() {

    $sketchbook = /App/Sketchbook::all();

    return view('color.book', ['sketchbook' => $sketchbook]);

}

$sketchbook = /App/Sketchbook::all();

/모델네임스페이스/모델명::all() 하면 모델에서 지정한 테이블의 모든 자료를 가져와서 $sketchbook 변수에 저장된다.

view('color.book', ['sketchbook' => $sketchbook]) 는 뷰폴더 아래의 'color' 폴더 아래에 book.blade.php 파일에 $sketchbook 변수값이 전달된다.

 

Eloquent: Relationships - 관계 

  • 1:1(일대일) 관계 - hasOne
  • 1:*(일대다) 관계 - hasMany, belongsTo(역관계)
  • *:*(다대다) 관계 - belongsToMany
  • 연결을 통한 단일 관계 - hasOneThrough
  • 연결을 통한 다수를 가지는 관계 - hasManyThrough
  • 1:1(일대일) (다형성) - morphTo, morphOne
  • 1:*(일대다) (다형성) - morphMany
  • *:*(다대다) (다형성) - morphToMany, morphedByMany
  • 관계 질의 - has, hasMany, doesntHave, whereDoesntHave

사용예)

Relationships.jpg

<사용예1> profile 테이블의 program_id 값과 연결된 program 테이블 자료 가져오기

public function Program()

{

  return $this->hasOne(Program::class, 'id', 'program_id');

}

## program 테이블의 모델 파일에 다음과 같이 관계 설정을 해줘야 한다.

public function Profile()

{

    return $this->belongsTo('AppProfile', 'id', 'program_id');

}

 

<사용예2> profile 테이블의 program_id 값과 연결된 program 테이블에 있는 country 테이블 자료 가져오기

public function Country()

{

  return $this->hasOneThrough('AppCountry', 'AppProgram', 'id', 'id', 'program_id', 'country_id');

}

## country 테이블의 모델 파일에 다음과 같이 관계 설정을 해줘야 한다.

public function Program()

{

    return $this->hasMany(Program::class);

}

 

<자료전달> 컨트롤러에서 DB테이블 자료를 불러와서 뷰 파일로 값을 전달한다.

$profile = DB::table('profile')->orderBy('id', 'asc')->get()

return view('뷰파일').with([ 'profile' => $profile ])

 

<결과출력> 블레이드 view 파일에서 다음과 같이 자료를 출력하면 된다.
$profile->Country->name

 

 

 

자주 사용하는 DB 구문 정리

$users = DB::table('users')->get();

return view('user.index', ['users' => $users]);

foreach ($users as $user) { echo $user->name; }

 

$user = DB::table('users')->where('name', 'John')->first();

echo $user->name;

$email = DB::table('users')->where('name', 'John')->value('email');

$user = DB::table('users')->find(3);

 

$titles = DB::table('roles')->pluck('title');

foreach ($titles as $title) { echo $title; }

$roles = DB::table('roles')->pluck('title', 'name');

foreach ($roles as $name => $title) { echo $title; }

 

DB::table('users')->orderBy('id')->chunk(100, function ($users) {

    foreach ($users as $user) {

        //

    }

});

DB::table('users')->orderBy('id')->chunk(100, function ($users) {

    // Process the records...

    return false;

});

DB::table('users')->where('active', false)->chunkById(100, function ($users) {

  foreach ($users as $user) {

    DB::table('users')->where('id', $user->id)->update(['active' => true]);

  }

});

 

$users = DB::table('users')->count();

$price = DB::table('orders')->max('price');

$price = DB::table('orders')->where('finalized', 1)->max('price');

$price = DB::table('orders')->where('finalized', 1)->avg('price');

 

return DB::table('orders')->where('finalized', 1)->exists();

return DB::table('orders')->where('finalized', 1)->doesntExist();

 

$users = DB::table('users')->select('name', 'email as user_email')->get();

$users = DB::table('users')->distinct()->get();

$query = DB::table('users')->select('name');

$users = $query->addSelect('age')->get();

 

$users = DB::table('users')->select(DB::raw('count(*) as user_count, status'))->where('status', '<>', 1)->groupBy('status')->get();

$orders = DB::table('orders')->selectRaw('price * ? as price_with_tax', [1.0825])->get();

$orders = DB::table('orders')->whereRaw('price > IF(state = "TX", ?, 100)', [200])->get();

$orders = DB::table('orders')->select('department', DB::raw('SUM(price) as total_sales'))

->groupBy('department')->havingRaw('SUM(price) > ?', [2500])->get();

$orders = DB::table('orders')->orderByRaw('updated_at - created_at DESC')->get();

 

$users = DB::table('users')

->join('contacts', 'users.id', '=', 'contacts.user_id')

->join('orders', 'users.id', '=', 'orders.user_id')

->select('users.*', 'contacts.phone', 'orders.price')->get();

$users = DB::table('users')->leftJoin('posts', 'users.id', '=', 'posts.user_id')->get();

$users = DB::table('users')->rightJoin('posts', 'users.id', '=', 'posts.user_id')->get();

$users = DB::table('sizes')->crossJoin('colours')->get();

DB::table('users')->join('contacts', function ($join) {

  $join->on('users.id', '=', 'contacts.user_id')->orOn(...);

})->get();

DB::table('users')->join('contacts', function ($join) {

  $join->on('users.id', '=', 'contacts.user_id')->where('contacts.user_id', '>', 5);

})->get();

 

$latestPosts = DB::table('posts')

->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))

->where('is_published', true)->groupBy('user_id');

$users = DB::table('users')->joinSub($latestPosts, 'latest_posts', function ($join) {

  $join->on('users.id', '=', 'latest_posts.user_id');

})->get();

 

$first = DB::table('users')->whereNull('first_name');

$users = DB::table('users')->whereNull('last_name')->union($first)->get();

 

$users = DB::table('users')->where('votes', '=', 100)->get();

$users = DB::table('users')->where('votes', 100)->get();

$users = DB::table('users')->where('votes', '<>', 100)->get();

$users = DB::table('users')->where('name', 'like', 'T%')->get();

$users = DB::table('users')->where([['status', '=', '1'],['subscribed', '<>', '1'],])->get();

$users = DB::table('users')->where('votes', '>', 100)->orWhere('name', 'John')->get();

$users = DB::table('users')->whereBetween('votes', [1, 100])->get();

$users = DB::table('users')->whereNotBetween('votes', [1, 100])->get();

$users = DB::table('users')->whereIn('id', [1, 2, 3])->get();

$users = DB::table('users')->whereNotIn('id', [1, 2, 3])->get();

$users = DB::table('users')->whereNull('updated_at')->get();

$users = DB::table('users')->whereNotNull('updated_at')->get();

$users = DB::table('users')->whereDate('created_at', '2016-12-31')->get();

$users = DB::table('users')->whereMonth('created_at', '12')->get();

$users = DB::table('users')->whereDay('created_at', '31')->get();

$users = DB::table('users')->whereYear('created_at', '2016')->get();

$users = DB::table('users')->whereTime('created_at', '=', '11:20:45')->get();

$users = DB::table('users')->whereColumn('updated_at', '>', 'created_at')->get();

$users = DB::table('users')->whereColumn([

  ['first_name', '=', 'last_name'],

  ['updated_at', '>', 'created_at']

])->get();

 

DB::table('users')->where('name', '=', 'John')->where(function ($query) {

  $query->where('votes', '>', 100)->orWhere('title', '=', 'Admin');

})->get();

# select * from users where name = 'John' and (votes > 100 or title = 'Admin')

 

DB::table('users')->whereExists(function ($query) {

$query->select(DB::raw(1))->from('orders')->whereRaw('orders.user_id = users.id');

})->get();

# select * from users where exists ( select 1 from orders where orders.user_id = users.id );

 

 

$users = DB::table('users')->where('preferences->dining->meal', 'salad')->get();

$users = DB::table('users')->whereJsonContains('options->languages', ['en', 'de'])->get();

$users = DB::table('users')->whereJsonLength('options->languages', '>', 1)->get();

 

$users = DB::table('users')->orderBy('name', 'desc')->get();

$user = DB::table('users')->latest()->first();

$randomUser = DB::table('users')->inRandomOrder()->first();

$users = DB::table('users')->groupBy('first_name', 'status')->having('account_id', '>', 100)->get();

$users = DB::table('users')->skip(10)->take(5)->get();

$users = DB::table('users')->offset(10)->limit(5)->get();

 

$role = $request->input('role');

$users = DB::table('users')->when($role, function ($query, $role) {

  return $query->where('role_id', $role);

})->get();

 

$sortBy = null;

$users = DB::table('users')->when($sortBy, function ($query, $sortBy) {

  return $query->orderBy($sortBy);

}, function ($query) {

  return $query->orderBy('name');

})->get();

 

DB::table('users')->insert( ['email' => 'john@example.com', 'votes' => 0] );

DB::table('users')->insertOrIgnore([

    ['id' => 1, 'email' => 'taylor@example.com'],

    ['id' => 2, 'email' => 'dayle@example.com']

]);

$id = DB::table('users')->insertGetId( ['email' => 'john@example.com', 'votes' => 0] );

 

DB::table('users')->where('id', 1)->update(['votes' => 1]);

DB::table('users')->updateOrInsert( ['email' => 'john@example.com', 'name' => 'John'], ['votes' => '2'] );

DB::table('users')->where('id', 1)->update(['options->enabled' => true]);

 

DB::table('users')->increment('votes');

DB::table('users')->increment('votes', 5);

DB::table('users')->decrement('votes');

DB::table('users')->decrement('votes', 5);

DB::table('users')->increment('votes', 1, ['name' => 'John']);

 

DB::table('users')->delete();

DB::table('users')->where('votes', '>', 100)->delete();

 

DB::table('users')->where('votes', '>', 100)->dd();

DB::table('users')->where('votes', '>', 100)->dump();

 

# Join same table

DB::table('sponsor_child as sa')

  ->join('sponsor_child as sb', 'sa.sponsor_id','=','sb.sponsor_id')

  ->where('sa.id', $request->id)

  ->pluck('sb.id');

 

php artisan make:migration add_fields_to_users_table --table=users

 

 

라우트(web.php) 에 아래 구문을 등록하면, 새로운 페이지(sketch)가 생성된다.

Route::get('/sketch', 'HomeController@sketch');

 

뷰(/resources/views/color/book.blade.php) 에 아래 구문을 추가한다.

@extends('layout')

 

@section('content')

    @foreach($sketchbook as $color)

    {{ $color->DB컬럼 }}

    @endforeach

@endsection

 

8. 로그인과 인증처리

# php artisan make:auth

Laravel >=6

 

# composer require laravel/ui --dev

# php artisan ui vue --auth
# npm install && npm run dev

 

9. 라라벨 검색(Scout)

# composer require laravel/scout

# php artisan vendor:publish --provider="LaravelScoutScoutServiceProvider"

 

>> Add the LaravelScoutSearchable trait to the model

 

use LaravelScoutSearchable;

class 모델명 extends Model

{

    use Searchable;

    public $asYouType = true;

 

    /**

     * Get the indexable data array for the model.

     *

     * @return array

     */

    public function toSearchableArray()

    {

        $array = $this->toArray();

        // ID, NAME등 조건 검색일 경우

        $array = collect($this->toArray())->only(['id', 'name'])->toArray();

        return $array;

    }

 

    public function getScoutKey()

    {

        return $this->name;

    }

}

 

>> Modify "config/scout.php"

'driver' => env('SCOUT_DRIVER', 'tntsearch'),

'queue' => env('SCOUT_QUEUE', true),

'tntsearch' => [

  'storage'  => storage_path(), //place where the index files will be stored

  'fuzziness' => env('TNTSEARCH_FUZZINESS', false),

  'fuzzy' => [

    'prefix_length' => 2,

    'max_expansions' => 50,

    'distance' => 2

  ],

  'asYouType' => false,

  'searchBoolean' => env('TNTSEARCH_BOOLEAN', false),

],

 

 

>> Modify "php.ini" extension

extension=pdo_sqlite

extension=sqlite3

 

>> install tntsearch

#composer require teamtnt/laravel-scout-tntsearch-driver

 

>> Modify "config/app.php"

'providers' => [

    // ...

    LaravelScoutScoutServiceProvider::class,

    TeamTNTScoutTNTSearchScoutServiceProvider::class,

],

 

 

>> Add SCOUT_DRIVER=tntsearch to your .env file

 

>> add the following line to your .gitignore file.

/storage/*.index

 

>> Then, sync the data with the search service like:

#php artisan scout:import App모델명

 
>> 컨트롤러에 검색 구문 추가
$child = new ChildProfile;
$child = ChildProfile::search($request->search);
$child->orderBy('id', 'asc');
$childrens = $child->paginate(16);

 

 

> 라라벨 기본 작업 과정

 

# git clone ... 

# composer update

# chown -R $USER:http storage

# chown -R $USER:http bootstrap/cache

# chmod -R 775 storage

# chmod -R 775 bootstrap/cache

# cp .env.example .env

# vi .env

DB_CONNECTION=mysql

DB_HOST=127.0.0.1

DB_PORT=3306

DB_DATABASE=laravel

DB_USERNAME=root

DB_PASSWORD=

:wq

 

# php artisan key:generate

# php artisan migrate

# php artisan tinker

factory(AppUser::class, 2)->create();

# php artisan storage:link

# php artisan passport:install


>라라벨 Package 개발과정

 

1. composer.json 의 autoload 에 팩키지명(Phteahang)과 경로(phteahang/) 추가한다.

# composer.json

"autoload": {

    "psr-4": {

        "App": "app/",

        "Phteahang": "phteahang/"

    },

 

2. config 폴더의 app.php 에서 서비스프로바이더 추가한다.

'providers' => [

    PhteahangProvidersPhteahangServiceProvider::class,

 

3. 서비스프로바이더에 팩키지(Phteahang) 클래스를 바인딩한다.

 

<?php

namespace PhteahangProviders;

use IlluminateSupportServiceProvider;
use PhteahangPhteahang;

class PhteahangServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
      //$this->app->alias(Phteahang::class, 'Phteahang');
      $this->app->singleton('phteahang', function () {
          return new Phteahang();
      });
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        $this->loadRoutesFrom(realpath(__DIR__.'/../routes.php'));
        $this->loadMigrationsFrom(realpath(__DIR__.'/../Migrations'));
        $this->loadViewsFrom(__DIR__.'/../View', 'phteahang');
        $this->publishes([
          realpath(__DIR__.'/../Assets') => public_path('phteahang'),
        ], 'public');
    }
}

 

4. 팩키지 클래스 생성

<?php

namespace Phteahang;

use IlluminateDatabaseEloquentCollection;
use IlluminateDatabaseEloquentModel;
use IlluminateFilesystemFilesystem;
use IlluminateSupportArr;
use IlluminateSupportFacadesCache;
use IlluminateSupportFacadesStorage;
use IlluminateSupportStr;

class Phteahang
{

  protected $viewLoadingEvents = [];

  public function __construct()
  {
    //
  }

}

 

5. 파사드 생성

<?php

namespace PhteahangFacades;

use IlluminateSupportFacadesFacade;

class Phtea extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'phteahang';
    }
}

 

6. 라우트 생성 route.php

<?php
use IlluminateSupportFacadesRoute;

Route::group(['middleware' => ['web']], function() {
  Route::get('dashboard', ['uses' => 'PhteahangControllersHomeController@dashboard', 'as' => 'dashboard']);
  Route::get('home', 'AppHttpControllersHomeController@index')->name('home');
});

 

7. 컨트롤러 생성

<?php

namespace PhteahangControllers;

use IlluminateHttpRequest;
use PhteahangFacadesPhtea;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function index()
    {
        return view('phteahang::frontend.index');
    }
}