라라벨 설치와 기본 학습
2020.03.13 05:49
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
사용예)
<사용예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
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();
}
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모델명
> 라라벨 기본 작업 과정
# 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) 클래스를 바인딩한다.
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. 팩키지 클래스 생성
namespace Phteahang;
use IlluminateDatabaseEloquentCollection;
use IlluminateDatabaseEloquentModel;
use IlluminateFilesystemFilesystem;
use IlluminateSupportArr;
use IlluminateSupportFacadesCache;
use IlluminateSupportFacadesStorage;
use IlluminateSupportStr;
class Phteahang
{
protected $viewLoadingEvents = [];
public function __construct()
{
//
}
}
5. 파사드 생성
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
use IlluminateSupportFacadesRoute;
Route::group(['middleware' => ['web']], function() {
Route::get('dashboard', ['uses' => 'PhteahangControllersHomeController@dashboard', 'as' => 'dashboard']);
Route::get('home', 'AppHttpControllersHomeController@index')->name('home');
});
7. 컨트롤러 생성
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');
}
}
Comment 0
No. | Subject | Author | Date | Views |
---|---|---|---|---|
10 | REQUEST 관련 구문 정리 | Admin | 2020.10.22 | 25 |
9 | SCOUT AND 검색(searchBoolean) | Admin | 2020.05.05 | 122 |
8 | 페도라 설치후 서버 기본작업 | Admin | 2020.04.21 | 192 |
7 | Model Factory - 데이터 심기(Faker) | Admin | 2020.04.19 | 110 |
6 | SCOUT 관계 검색 | Admin | 2020.04.16 | 460 |
5 | 라라벨 Model, Controller, View 실습 | Admin | 2020.04.07 | 245 |
4 | October CMS Theme 만들기 | Admin | 2020.04.04 | 289 |
3 | October CMS 설치방법 | Admin | 2020.04.03 | 76 |
2 | Laravel 에서 라우트된 페이지에서 404 에러가 출력될 경우 - Synology | Admin | 2020.03.25 | 200 |
» | 라라벨 설치와 기본 학습 | Admin | 2020.03.13 | 52 |