'Programming/Slim'에 해당하는 글 17건

Slim 은 URL 패턴 끝에 슬래시가 있는 것과 없는 것을 다르게 처리한다.

/user/user/ 는 다른 콜백을 가질 수 있다.

슬래시로 끝나지 않는 모든 URL 에 슬래시를 붙여 리다이렉트 하려면 다음과 같이 미들웨어를 추가한다:


use Psr\Http\Message\RequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
 
$app->add(function (Request $request, Response $response, callable $next) {
    $uri = $request->getUri();
    $path = $uri->getPath();
    if ($path != '/' && substr($path-1== '/') {
        // permanently redirect paths with a trailing slash
        // to their non-trailing counterpart
        $uri = $uri->withPath(substr($path0-1));
        return $response->withRedirect((string)$uri301);
    }
 
    return $next($request$response);
});
cs


다른 방법으로, 모든 URL 의 끝에 강제로 슬래시를 붙이기 위해 oscarotero/psr7-middlewares 의 TrailingSlash 미들웨어를 사용할 수 있다.


use Psr7Middlewares\Middleware\TrailingSlash;
 
$app->add(new TrailingSlash(true)); // true adds the trailing slash (false removes it)
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

404 Not Found Handler


Slim 어플리케이션에 HTTP 요청 URI 와 매칭되는 라우트가 없다면 Not Found Handler 를 호출하고 HTTP 클라이언트에 HTTP/1.1 404 Not Found 응답을 반환한다.


Default Not Found handler

각 Slim 어프릴케이션은 기본 Not Found handler 를 가진다.

이 핸들러는 Response 상태를 404 로, Content type 을 text/html 로 지정하고, Response 본문에 간단한 설명을 작성한다.


Custom Not Found handler

Slim 어플리케이션의 Not Found handler 는 Pimple 서비스이다. 

어플리케이션 컨테이너로 Pimple 의 팩토리 메소드를 사용자 정의하여 이 에러 핸들러를 교체할 수 있다.


$c = new \Slim\Container(); //Create Your container
 
//Override the default Not Found Handler
$c['notFoundHandler'= function ($c) {
    return function ($request$response) use ($c) {
        return $c['response']
            ->withStatus(404)
            ->withHeader('Content-Type''text/html')
            ->write('Page not found');
    };
};
 
//Create Slim
$app = new \Slim\App($c);
 
//... Your code
cs


이 예에서, 우리는 새로운 notFoundHandler 팩토리를 정의하고 호출 가능한 것을 반환한다. 반환된 호출 가능한 것은 두가지 매개변수를 가진다.

  • \Psr\Http\Message\ServerRequestInterface 인스턴스
  • \Psr\Http\Message\ResponseInterface 인스턴스


호출 가능한 것은 적절한 \Psr\Http\Message\ResponseInterface 인스턴스를 반환해야 한다.



405 Not Allowed Handler


Slim 어플리케이션에 HTTP 요청 URI 와 매칭되는 라우트가 존재하지만 HTTP 요청 메소드가 아니라면, Not Allowed Handler 를 호출하고 HTTP 클라이언트에 HTTP/1.1 405 Not Allowed 응답을 반환한다.


Default Not Allowed handler

각 Slim 어프릴케이션은 기본 Not Allowed handler 를 가진다.

이 핸들러는 Response 상태를 405 로, Content type 을 text/html 로 지정하고, 사용 가능한 HTTP 메소드들을 콤마로 구분한 리스트로 HTTP 헤더에 Allowed 를 추가하고, Response 본문에 간단한 설명을 작성한다.


Custom Not Allowed handler

Slim 어플리케이션의 Not Allowed handler 는 Pimple 서비스이다. 

어플리케이션 컨테이너로 Pimple 의 팩토리 메소드를 사용자 정의하여 이 에러 핸들러를 교체할 수 있다.


// Create Slim
$app = new \Slim\App();
// get the app's di-container
$c = $app->getContainer();
$c['notAllowedHandler'= function ($c) {
    return function ($request$response$methods) use ($c) {
        return $c['response']
            ->withStatus(405)
            ->withHeader('Allow', implode(', '$methods))
            ->withHeader('Content-type''text/html')
            ->write('Method must be one of: ' . implode(', '$methods));
    };
};
cs


\Slim\Container 의 새로운 인스턴스를 사용하여 사전 slim 생성 메소드에 대해 Not Found 문서를 확인하라.


이 예에서, 우리는 새로운 notAllowedHandler 팩토리를 정의하고 호출 가능한 것을 반환한다. 반환된 호출 가능한 것은 세가지 매개변수를 가진다.

  • \Psr\Http\Message\ServerRequestInterface 인스턴스
  • \Psr\Http\Message\ResponseInterface 인스턴스
  • 사용 가능한 HTTP 메소드 이름의 숫자 배열


호출 가능한 것은 적절한 \Psr\Http\Message\ResponseInterface 인스턴스를 반환해야 한다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,



각 Slim 프레임워크 어플리케이션은 캐치되지 않은 모든 PHP 예외를 받는 에러 핸들러를 가진다.

이 에러 핸들러는 HTTP 클라이언트에 보내질 적절한 Response 객체를 준비하고 반환하는 등 HTTP 요청과 응답도 다룰 수 있다.



기본 에러 핸들러


페이지에 오류가 있을 경우 Response 상태 코드는 500 으로 지정되고, Content type 은 text/html, 본문에는 일반 에러 메시지가 추가된다.

이것은 런칭된 어플리케이션에서 적절하지 않을 것이므로, 이 에러 핸들러를 구현하는 것을 권장한다.

displayErrorDetails 세팅을 true 로 하여, 기본 에러 핸들러로 상세한 에러 정보를 나타낼 수 있다.


$configuration = [
    'settings' => [
        'displayErrorDetails' => true,
    ],
];
$c = new \Slim\Container($configuration);
$app = new \Slim\App($c);
cs



사용자 정의 에러 핸들러


Slim 의 에러 핸들러는 Pimple 서비스이다.

어플리케이션 컨테이너로 Pimple 의 팩토리 메소드를 사용자 정의하여 에러 핸들러를 교체할 수 있다.


핸들러를 추가하는 두가지 방법이다.


App 정의 전

$c = new \Slim\Container();
$c['errorHandler'= function ($c) {
    return function ($request$response$exception) use ($c) {
        return $c['response']->withStatus(500)
                             ->withHeader('Content-Type''text/html')
                             ->write('Something went wrong!');
    };
};
$app = new \Slim\App($c);
cs


App 정의 후

$app = new \Slim\App();
$c = $app->getContainer();
$c['errorHandler'= function ($c) {
    return function ($request$response$exception) use ($c) {
        return $c['response']->withStatus(500)
                             ->withHeader('Content-Type''text/html')
                             ->write('Something went wrong!');
    };
};
cs


이 예에서, 우리는 새로운 errorHandler 팩토리를 정의하고 호출 가능한 것을 반환한다. 반환된 호출 가능한 것은 세가지 매개변수를 가진다.

  • \Psr\Http\Message\ServerRequestInterface 인스턴스
  • \Psr\Http\Message\ResponseInterface 인스턴스
  • \Exception 인스턴스


호출 가능한 것은 주어진 예외에 대해 적절한 것으로 새로운 \Psr\Http\Message\ResponseInterface 인스턴스를 반환해야 한다.


비활성화

Slim 에러 핸들러를 비활성화 하려면 단순히 컨테이너에서 에러 핸들러를 제거한다.


unset($app->getContainer()['errorHandler']);
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Slim Router

Programming/Slim 2016. 3. 6. 00:22

Slim 프레임워크의 라우터는 nikic/fastroute 컴포넌트로, 매우 빠르고 안정적이다.



라우트 생성하기


\Slim\App 인스턴스에서 프록시 메소드를 사용하여 어플리케이션 라우트를 정의할 수 있다.

Slim 프레임워크는 가장 많이 사용하는 HTTP 메소드들에 대한 메소드를 제공한다.


GET Route

Slim 어플리케이션의 get(pattern, callback) 메소드로 GET HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5

$app = new \Slim\App();
$app->get('/books/{id}'function ($request$response$args) {
    // Show book identified by $args['id']
});
cs


POST Route

Slim 어플리케이션의 post(pattern, callback) 메소드로 POST HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5

$app = new \Slim\App();
$app->post('/books'function ($request$response$args) {
    // Create new book
});
cs


PUT Route

Slim 어플리케이션의 put(pattern, callback) 메소드로 PUT HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5

$app = new \Slim\App();
$app->put('/books/{id}'function ($request$response$args) {
    // Update book identified by $args['id']
});
cs


DELETE Route

Slim 어플리케이션의 delete(pattern, callback) 메소드로 DELETE HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5

$app = new \Slim\App();
$app->delete('/books/{id}'function ($request$response$args) {
    // Delete book identified by $args['id']
});
cs


OPTIONS  Route

Slim 어플리케이션의 options(pattern, callback) 메소드로 OPTIONS HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5

$app = new \Slim\App();
$app->options('/books/{id}'function ($request$response$args) {
    // Return response headers
});
cs


PATCH Route

Slim 어플리케이션의 patch(pattern, callback) 메소드로 PATCH HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5

$app = new \Slim\App();
$app->patch('/books/{id}'function ($request$response$args) {
    // Apply changes to book identified by $args['id']
});
cs


Any Route

Slim 어플리케이션의 any(pattern, callback) 메소드로 모든 HTTP 요청을 다루는 라우트를 추가한다.

1
2
3
4
5
6

$app = new \Slim\App();
$app->any('/books/[{id}]'function ($request$response$args) {
    // Apply changes to books or book identified by $args['id'] if specified.
    // To check which method is used: $request->getMethod();
});
cs


두번째 매개변수에 콜백 클로저 대신 __invoke() 구현이 필요한 클래스를 지정할 수 있다.


1
$app->any('/user''MyRestfulController');
cs


Custom Route

Slim 어플리케이션의 map(array HTTP method, pattern, callback) 메소드로 여러 HTTP 요청을 다루는 라우트를 추가한다.


1
2
3
4
5

$app = new \Slim\App();
$app->map(['GET''POST'], '/books'function ($request$response$args) {
    // Create new book or list all books
});
cs



라우트 콜백


위의 각 라우팅 메소드는 마지막 매개변수로 콜백 루틴을 가진다.

이 매개변수는 PHP 에서 호출 가능한 것이면 무엇이든 될 수 있으며, 기본적으로 세개의 매개변수를 가진다.

  • Request : 첫번째 매개변수로, 현재 HTTP 요청을 나타내는 Psr\Http\Message\ServerRequestInterface 객체
  • Response : 두번째 매개변수로, 현재 HTTP 응답을 나타내는 Psr\Http\Message\ResponseInterface  객체
  • Arguments : 세번째 매개변수로, 현재 라우트 예상 값을 포함하는 배열


응답에 내용 작성

HTTP 응답에 내용을 작성하는 데는 두가지 방법이 있다.

  • 라우트 콜백에 HTTP 응답 객체의 echo() 로 내용을 추가한다.
  • Psr\Http\Message\ResponseInterface 객체를 반환한다.


클로저 바인딩

라우트 콜백에 Closure 인스턴스를 사용한다면, 클로저의 상태는 Container 인스턴스에 바인딩된다.

이 말은, $this 키워드를 통해 Closure 내부의 DI 컨테이너에 접근한다는 것이다.



라우트 전략


라우트 콜백 매개변수는 라우트 전략(strategies)으로부터 결정된다.

기본적으로 Slim 은 Request, Response, Placeholder 배열로 라우트 콜백을 받는다. 이것을 RequestResponse 전략이라고 부른다.

그러나, 단순히 다른 전략을 사용하여 라우트 콜백 매개변수를 바꿀 수 있다.

예를 들어, Slim 은 request 와 response, 별도의 매개변수로 각 라우트 placeholder 를 매개변수로 하는 RequestResponseArgs 라는 대안적인 전략을 제공한다.

아래의 예는 대안적인 전략을 사용한 예이다; 단순히 기본 \Slim\Container 로 제공된 foundHandler 의존성을 대신한다.


1
2
3
4
5
6
7
8
9
$c = new \Slim\Container();
$c['foundHandler'= function() {
    return new \Slim\Handlers\Strategies\RequestResponseArgs();
};
 
$app = new \Slim\App($c);
$app->get('/hello/{name}', function ($request$response$name) {
    return $response->write($name);
});
cs


/hello/foo 로 접근할 경우 기본적으로 $name 은 array('name'=>'foo') 처럼 배열로 넘기겠지만,
위처럼 \Slim\Interfaces\InvocationStrategyInterface 를 구현하여 $name 이 'foo' 를 바로 넘기는 라우트 전략을 제공할 수 있다.



라우트 placeholders


위의 각 라우트 메소드는 HTTP 요청 URI 와 일치되는 URL 패턴 매개변수를 가진다.

라우트 패턴은 HTTP 요청 URI 를 동적으로 매칭하기 위해 placeholder 를 사용할 것이다.


형식

라우트 패턴 placeholder 는 중괄호 { 로 시작하고, placeholder 이름이 오고, 중괄호 } 로 닫는다.


1
2
3
4
$app = new \Slim\App();
$app->get('/hello/{name}', function ($request$response$args) {
    echo "Hello, " . $args['name'];
});
cs


정규 표현식 매칭

기본적으로 placeholder 는 {} 안에 쓰이고, 어떤 값도 들어갈 수 있다.

그러나 placeholder 는 특정 정규 표현식과 매칭하기 위해 HTTP 요청 URI 를 필요로 할 수도 있다.

HTTP 요청 URI 가 placeholder 의 정규 표현식과 일치하지 않으면, 라우트는 호출되지 않는다.

아래는 10진수를 요구하는 id 라는 이름의 placeholder 예이다.


1
2
3
4
5

$app = new \Slim\App();
$app->get('/users/{id:[0-9]+}'function ($request$response$args) {
    // Find user identified by $args['id']
});
cs



라우트 이름


어플리케이션 라우트는 이름을 할당할 수 있다.

라우트의 pathFor() 메소드는 특정 라우트에 URL 을 계획적으로 생성하는데 유용하다.

위에 설명된 각 라우트 메소드는 \Slim\Route 객체를 반환하고, 이 객체는 setName() 메소드를 노출한다.


1
2
3
4
$app = new \Slim\App();
$app->get('/hello/{name}', function ($request$response$args) {
    echo "Hello, " . $args['name'];
})->setName('hello');
cs


어플리케이션 라우트의 pathFor(name, rount pattern array or values) 메소드로 이름 지어진 라우트에 URL 을 생성할 수 있다.


1
2
3
4
5

echo $app->getContainer()->get('router')->pathFor('hello', [
    'name' => 'Josh'
]);
// Outputs "/hello/Josh"
cs



라우트 그룹


논리적인 그룹으로 라우트를 구성하기 위해, \Slim\App 는 group() 메소드도 제공한다.

각 그룹의 라우트 패턴은 그 안에 포함되는 라우트나 그룹을 덧붙이고, 그룹 패턴의 모든 placeholder 매개변수는 궁극적으로 중첩된 라우트에 사용 가능하게 된다.


1
2
3
4
5
6
7
8
9
10
11

$app = new \Slim\App();
$app->group('/users/{id:[0-9]+}'function () {
    $this->map(['GET''DELETE''PATCH''PUT'], ''function ($request$response$args) {
        // Find, delete, patch or replace user identified by $args['id']
    })->setName('user');
    $this->get('/reset-password'function ($request$response$args) {
        // Route for /users/{id:[0-9]+}/reset-password
        // Reset the password for user identified by $args['id']
    })->setName('user-password-reset');
});
cs


그룹 클로져 안에 $this 는 $app 을 가리키는 것에 유의하라.

Slim 은 라우트 콜백을 사용하는 것 처럼 어플리케이션 인스턴스에 클로저를 바인딩한다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Slim Response

Programming/Slim 2016. 3. 5. 01:40

Slim app 의 라우트와 미들웨어는 클라이언트로 반환될 HTTP 응답을 나타내는 PSR-7 응답 객체를 제공한다.

응답 객체는 HTTP 응답 상태, 헤더, 본문을 다룰수 있는 PSR-7 ResponseInterface 를 구현한다.



Response 객체 얻는 방법


PSR-7 응답 객체를 라우트 콜백의 두번째 매개변수로 넣는 예제

1
2
3
4
5
6
7
8
9
10
11
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
 
$app = new \Slim\App;
$app->get('/foo'function (ServerRequestInterface $request, ResponseInterface $response) {
    // Use the PSR 7 $response object
 
    return $response;
});
$app->run();
cs


PSR-7 응답 객체를 미들웨어 콜백의 두번째 매개변수로 넣는 예제

1
2
3
4
5
6
7
8
9
10
11
12
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
 
$app = new \Slim\App;
$app->add(function (ServerRequestInterface $request, ResponseInterface $response, callable $next) {
    // Use the PSR 7 $response object
 
    return $next($request$response);
});
// Define app routes...
$app->run();
cs



Response 상태


모든 HTTP 응답은 숫자로 된 상태 코드를 가진다.

상태 코드는 클라이언트에 반환된 HTTP 응답의 형태를 식별한다.

PSR-7 Response 객체의 기본 상태 코드는 200 (OK) 이다.

getStatusCode() 메소드를 사용하여 상태 코드를 얻을 수 있고, Response 객체를 복사하여 withStatus(number) 메소드로 새로운 상태 코드를 할당할 수도 있다.


1
2
$status = $response->getStatusCode();
$newResponse = $response->withStatus(302);
cs



Response 헤더


모든 HTTP 응답은 헤더를 가진다. 응답 본분에 보이지 않으며 HTTP 응답을 나타내는 메타데이터이다.

PSR-7 응답 객체는 헤더를 검사하는 여러 메소드들을 제공한다.


getHeaders() 는 모든 HTTP 요청 헤더를 배열로 가져온다.

배열의 키는 헤더 이름이 되고, 그 값은 문자열로 된 숫자 배열이다.


1
2
3
4
$headers = $response->getHeaders();
foreach ($headers as $name => $values) {
    echo $name . ": " . implode(", "$values);
}
cs


getHeader($name) 는 하나의 헤더값을 가져온며 지정된 헤더 이름($name)의 값을 배열로 반환한다. 하나의 HTTP 헤더는 하나 이상의 값을 가질 수 있다.

getHeaderLine($name) 는 헤더의 모든 값을 콤마로 구분된 문자열로 가져온다.

hasHeader($name) 는 해당 헤더의 존재 여부를 확인할 수 있다.

withHeader($name, $value) 는 헤더 값을 지정한다. 새로 지정된 헤더 값을 가진 Response 객체의 복사본을 반환한다.

withAddedHeader($name, $value) 는 이미 존재하는 헤더 이름에 새로운 값을 추가한다. 추가된 헤더 값을 가진 Response 객체의 복사본을 반환한다.

withoutHeader($name) 는 헤더를 삭제한다. 삭제된 헤더 값을 가진 Response 객체의 복사본을 반환한다.



Response 본문


모든 HTTP 응답은 본문을 가진다. Slim 은 최종 HTTP 응답 본문을 다룰 수 있는 PSR-7 Response 객체를 제공한다.

PSR-7 Request 객체처럼, PSR-7 Response 객체의 getBody() 로 \Psr\Http\Message\StreamInterface 인스턴스를 얻어 HTTP 응답 본문을 구현한다.

getBody() 메소드는 HTTP 응답 길이를 알 수 없거나 이용 가능한 메모리 보다 더 큰 경우에 사용한다.


\Psr\Http\Message\StreamInterface 인스턴스는 PHP 리소스를 읽고 반복적으로 작성하는 다음의 메소드들을 제공한다.

  • getSize()
  • tell()
  • eof()
  • isSeekable()
  • seek()
  • rewind()
  • isWritable()
  • write($string)
  • isReadable()
  • read($length)
  • getContents()
  • getMetadata($key = null)


가장 자주 사용되는 것은 write() 메소드로 StreamInterface 인스턴스에 내용을 작성하여 PSR-7 Response 객체를 작성할 수 있다.


1
2
$body = $response->getBody();
$body->write('Hello');
cs


또한 완전히 새로운 StreamInterface 인스턴스의 withBody(StreamInterface $body) 메소드로 PSR-7 Response 객체의 본문을 대체할 수도 있다.

이 메소드는 새로운 본문을 포함하는 REsponse 객체의 복사본을 반환한다.

이것은 HTTP 응답으로 원격 대상(파일시스템이나 원격 API) 로부터 pipe 컨텐츠를 원할 때 특히 유용하다.


1
2
$newStream = new \GuzzleHttp\Psr7\LazyOpenStream('/path/to/file''r');
$newResponse = $oldResponse->withBody($newStream);
cs




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,