Laravel
로 프로젝트를 수행하면서 몰랐거나, 자주 헷갈리거나, 이해가 안되서 더 찾아봐야 하는 내용을 정리해 봤다. 써 보니 내 무지가 적나라하게 드러나는 것 같아 무척 창피하다. 이 글은 완성이 아니며 계속 수정될 거고, 잘못된 내용도 많을 것이다. 잘못된 내용은 편하게 지적해 주시기 바란다.
php
isset
배열에 관해서는 키가 없거나 값이 null 이면 false
$a = array ('test' => 1, 'hello' => NULL, 'pie' => array('a' => 'apple'));
var_dump(isset($a['test'])); // TRUE
var_dump(isset($a['foo'])); // FALSE
var_dump(isset($a['hello'])); // FALSE
// The key 'hello' equals NULL so is considered unset
// If you want to check for NULL key values then try:
var_dump(array_key_exists('hello', $a)); // TRUE
getIfSet
$a = isset($attrs['a']) ? $attrs['a'] : null);
$b = isset($attrs['b']) ? $attrs['b'] : null);
$c = isset($attrs['c']) ? $attrs['c'] : null);
getIfSet
함수를 써서 표현하면 훨씬 심플해 진다.
$a = getIfSet($attrs['a']);
$b = getIfSet($attrs['b']);
$b = getIfSet($attrs['c']);
function getIfSet(&$var) {
if (isset($var)) {
return $var;
}
return null;
}
참고 : 왜 getIfSet의 인자를 call by reference를 썼을까?
method chain
class Foo {
public function methodA() {
...
return $this;
}
pubilc function methodB() {
...
return $this;
}
}
위 처럼 메쏘드에서 $this
를 반환하면 메쏘드 체인을 사용할 수 있다. 메쏘드 체인은 뭐냐? 시나리오, 프로세스의 연결.
new Foo()->methodA()->methodB();
클래스 static 변수 초기화 방법
class Foo {
static $bar;
}
Foo::$bar = array(…);
또는
class Foo {
private static $bar;
static function init()
{
self::$bar = array(…);
}
}
Foo::init();
type hint
Type hints can not be used with scalar types such as int
or string
. Resources
and Traits
are not allowed either.
if statement
if
문의 다른 표현 방법
<?php
if ($a == 5):
echo "a equals 5";
echo "...";
elseif ($a == 6):
echo "a equals 6";
echo "!!!";
else:
echo "a is neither 5 nor 6";
endif;
?>
reference
다음의 결과를 예측해 보자. 이것 때문에 한참을 해멨다.
$foo = [‘a’ => array(), ‘b’ => array()];
$foo[‘a’][’hello’] = ‘world’;
var_dump($foo['a']['hello']);
$bar = $foo[‘b’];
$bar[‘hello’] = ‘world’;
var_dump($foo['a']['hello']);
$bar = &$foo[‘b’];
$bar[‘hello’] = ‘world’;
var_dump($foo['a']['hello']);
closure
클로저에 변수를 넘기는 방법은?
Route::get(‘/‘, function() use($app) {
dd($app[‘files’]);
});
근데 다음처럼 쓰면 안되나? 역시 클로저를 이해 못하고 있는거야.
Route::get(‘/‘, function($app) {
dd($app[‘files’]);
});
문자열 처리는 Str 객체를 사용하라
- strtolower 대신 Str::lower을 사용해라
- MBCS, UNICDOE 처리 때문에
php snippet
swap을 하나의 라인으로 표시하면
list($max, $min) = array($min, $max);
PHPDoc
@deprecated
/**
* 폴 헬퍼 클래스
*
* @deprecated 임시로 asp에서 php로 변경하면서 만든 클래스이다. 사용하지 말어라.
*/
composer
require-dev
는 뭔가?
Lists packages required for developing this package, or running tests, etc. The dev requirements of the root package are installed by default. Both install or update support the --no-dev option that prevents dev dependencies from being installed.
개발시 필요한 패키지와 서비스시 필요한 패키지를 구분하기 위해서.
app/start/global.php와 composer.json의 autoload의 차이점은?
composer.json
은Laravel
과 상관없는 내용.app/start/global.php
는Laravel
에서 사용할 수 있는 autoload.Laravel
입장에서는 중복 같다. deploy를 생각한다면start.php
가 더 좋아 보인다.
artisan
php artisan tinker
environment
getenv 함수
getenv(‘key’)
환경설정 파일
.env.local.php
.env.production.php
.env.php
<?php
return [
‘key’ => ‘value’
];
input
input 값 바꾸기
Input::merge(array('key' => 'value'));
Input::replace(array('key' => 'value'));
session
- 특정 라우트에 대해서 세션을 사용하지 않게 하는 방법은 ?
Routing
"Route pattern "/product/related-self/{any}/{id}/{any}" cannot reference variable name "any" more than once” 오류 해결 방법
Route::get('/product/related-self/{any}/{id}/{any}', array('as' => 'products.related.self', 'uses' => 'ProductsController@getRelatedSelf'));
위 오류가 나서 임시로
Route::pattern('any', '[^\/]+');
Route::pattern('any2', '[^\/]+’);
Route::get('/product/related-self/{any}/{id}/{any2}', array('as' => 'products.related.self', 'uses' => 'ProductsController@getRelatedSelf'));
Routing 예제
두 개의 url 세그먼트에 각각 패턴 지정하기
Route::get('save/{princess}/{unicorn}', function($princess, $unicorn)
{
return "{$princess} loves {$unicorn}";
})->where('princess', '[A-Za-z]+')
->where('unicorn', '[0-9]+');
routing 패턴 정할 때 사용하는 이름과 실제 호출되는 함수나 메소드의 인자 이름은 별개다. 당연하 얘기겠지만.
Route::get('/foo/{id1}/{id2}', function($arg1, $arg2) {
echo "arg1=$arg1, arg2=$arg2";
});
Eloquent
- composite primary key
class OrderCatalog extends Model {
protected $table = 'Foo';
protected $primaryKey = array('pk1', 'pk2');
}
- 쿼리 예제
return DB::table('tmn_catalog')
->select(array('tmn_catalog.*', DB::raw('(SELECT Count(*) FROM TMN_OrderCatalog WHERE CatalogID = tmn_catalog.CatalogID) AS OrderCnt')))
->where('tmn_catalog.catalogid', '=', $id)
->first();
적색으로 표시한 부분 중요하다. 그 부분이 있어야 hasOne 관계를 통해서 연결을 맺을 수 있다.
public function count_orders() {
return $this->hasOne('Trademall\OrderCatalog', 'CatalogID', 'CatalogID')
->groupBy('CatalogID')
->select('CatalogID', \DB::raw('count(*) AS OrderCnt')
);
}
=> select [CatalogID], count(*) AS OrderCnt from [TMN_OrderCatalog] where [TMN_OrderCatalog].[CatalogID] in ('360680') group by [CatalogID]
public function getOrdersByCatalogIds($catalog_ids) {
return $this->model->whereIn('catalogid', $catalog_ids)
->groupBy('catalogid')
->get(array('CatalogID', \DB::raw('count(*) as OrderCnt')));
}
=> select [CatalogID], count(*) as OrderCnt from [TMN_OrderCatalog] where [catalogid] in ('10', '20') group by [catalogid]
Eager Loading
- Eager Loading을 사용하면 Repository 사용을 줄일 수 있다.
Eloquent Relationship
- function 이름과 모델이름이 같을 필요는 없다.
public function images() {
return $this->hasMany('Trademall\CatalogImage', 'CatalogID', 'CatalogID');
}
DBMS
MSSQL
freetds의 오류 메시지가 null로 보인다.
Design Pattern
한번 감싸라...
class MyLog {
public static function error($message) {
\Debugbar::error($message);
}
public static function warning($message) {
\Debugbar::warning($message);
}
public static function notice($message) {
\Debugbar::notice($message);
}
public static function info($message) {
\Debugbar::info($message);
}
public static function debug($message) {
\Debugbar::debug($message);
}
}
Repository 리턴은 Model이냐 Array냐
Eloquent와의 종속적인 부분을 줄이기 위해서 Array를 반환하라고 하는데, Array로 반환을 하면 다음이 불편함.
- $user['name’] 형태의 작업을 해야 함
- Presenter를 사용하지 못함
Repository는 테이블별로 만들어야 하나?
- 조인은 어떻게 처리를 하지?
helper나 basic function은 어디에 두는 게 좋을까?
helper는 view단에서 쉽게 쓸 수 있어야 한다.
첫번째 방법 : Facade로 만드는 방법
두번재 방법 : libraries 또는 helper 폴더를 만들어서 여기에 두는 방법
Create a libraries folder inside your app folder
Edit start/global.php to add app_path().'/libraries' to the ClassLoader::addDirectories( array.
Edit composer.json to add "app/libraries" to the autoload array.
Run composer dump-autoload
Create your library file, create a class in it, and add static functions to it
Call your class and static functions from your views.
http://stackoverflow.com/questions/20627727/where-do-i-put-custom-code-in-laravel?lq=1
blade 관련
다음 두개의 문장은 동일하다.
@section(‘page_title’, ‘TradeMall’)
@section('page_title')
TradeMall
@stop
@section 내부의 변수
@section
내부의 변수는 공유된다.
@section('a')
{{ $foo }}
@stop
@section('b')
<?php $foo = 'bar';?>
{{ $bar }}
@stop
- 위 결과는
undefined variable
@section
두개를 바꾸면 오류가 나지 않는다.@section
은 순서대로 실행이 되고 그 결과는 내부 변수에 저장되고 이는@yield
를 통해서 접근 가능 (내 추정)
좀 생각을 해보니 @section
내부의 변수라는 말 자체가 틀린 것 같다. @section
은 컴파일한 결과를 보면 그냥 함수의 호출로 변경되고, 따라서 @section
과 @stop
이 어떤 블럭을 형성하는 게 아니라 그냥 같은 스코프 문장의 연속이라고 보는 게 맞을 것 같다. @section
내부의 변수가 아니라 @section
다음에 오는 변수 관련 문장으로 보면 될 것 같다.
blade 에서 use를 사용하는 게 맞는가?
- IDE의 도움(인텔리센스)을 전혀 받지 못함
- 뭔가 코드가 정돈되지 않은 느낌
- 맞지 않다는 결론
view 단에서 반복되는 코드는 어떻게 해결할까?
- 화면 출력이면 partial view로 빼서 include 한다.
Presenter
로 뺀다.- 공통 유틸성이면 helper 클래스로 뺀다.
Package
Carbon
nesbot\carbon
Carbon Class not found 오류가 나는 경우
Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $this->resource->published_at, 'Europe/Berlin')
->toFormattedDateString();
debugbar
- 에러로그는 파일로 남나?
darsain/laravel-console
/console 접속시 notfound 오류 발생
$ php artisan config:publish darsain/laravel-console
config/packages/darsain/laravel-console/config.php 수정
'whitelist' => array('127.0.0.1', '::1', '192.168.33.1'),