Laravel Apps를위한 CMS로 WordPress 사용

오늘날 많은 개발자들이 WordPress REST API를 JavaScript 프레임 워크와 함께 사용하는 방법에 대해 많은 관심을 보입니다. 이 프로세스가 잘 작동하는 동안 REST API와 PHP MVC 프레임 워크, 특히 Laravel을 연관시키는 방법을 모색하고 있습니다.

이 기사에서는 WordPress REST API를 Laravel에 통합하는 몇 가지 방법에 대해 살펴 보겠습니다.

나는 최근에 유용한 팁과 링크를 제공하는 웹 응용 프로그램을 만들었습니다. WordPress 플러그인 칼데라 양식에 링크되어 있습니다. 그것이 보낸 콘텐 트의 대부분은 WordPress에 존재하므로 Caldera Forms 사이트에서 실행되는 플러그인을 만드는 것에 대해 생각했습니다. 전적으로 가능했지만, WordPress 사이트에이 추가 역할을 부여하는 것과 관련된 확장 성 문제는 싫었습니다.


WordPress 사이트의 작업 부하에 이러한 추가 요청을 모두 추가하는 대신, 메인 사이트의 WordPress REST API를 쿼리하여 다른 서버에 콘텐츠를 가져 오는 작은 Laravel 앱을 만들었습니다. 내 콘텐츠에 권위있는 위치를 제공하기 때문에 이것은 최고의 옵션입니다.

Laravel 기본에 익숙하지 않은 경우 Laravel 문서를 확인하고 Laracast를 확인해보십시오. 또한이 기사의 후반부에 Laravel의 종속성 주입 컨테이너에 대한 서비스를 등록하는 것과 관련하여 의존성 주입 컨테이너에 대한 기사를 계속 읽어보기 전에 고려해야합니다.

시작합시다.

A Few Simple Solutions

A Very Basic API Client

Laravel News의 Eric Barnes는 WordPress REST API를 사용하여 게시물을 Laravel 데이터베이스에 동기화하는 방법에 대한 자습서를 게시했으며이 게시물을 사용하여 내용을 표시합니다. 이 접근법을 더 단순화 할 수도 있습니다. 데이터베이스에 게시물을 작성하는 대신 캐시를 사용하고 오래된 정보를 갱신 할 수 있습니다. https://laravel-news.com/wordpress-api-with-laravel

다음은이 기사에서 채택 된 매우 간단한 WordPress REST API 클라이언트입니다.



그런 다음 컨트롤러의 클라이언트에서 이것을 사용하여 다음과 같이 게시물 또는 게시물을 표시 할 수 있습니다.



namespace AppHttpControllers;

use AppWpApi;

class Posts extends Controller {

    public function post( $id )
    {
        $post = WpApi::getPost( $id );
        return view( 'wp.post', [
            'post' => $post
        ]);
    }

    public function posts( $page )
    {
        $posts = WpApi::getPosts( $page );
        return view( 'wp.posts', [
            'posts' => $posts
        ]);
    }
}



이것은 각 HTTP 요청을 두 개의 요청으로 변환하기 때문에 훌륭한 시스템은 아닙니다. 한 부분이 WordPress에서 관리하는 내용이고 나머지 부분이 아닌 응용 프로그램이있는 경우 유용합니다. 이 특정 시나리오에서 Barnes는 자동화 된 데이터베이스 동기화를 사용하는 방법을 설명합니다.

앞에서 언급 한 솔루션이 모두 실행 가능한 옵션이지만 탐구 할 가치가있는 몇 가지 다른 옵션이 있습니다.

Query the WordPress Database Directly


데이터베이스에 중복 된 데이터를 원하지 않고 두 서버 모두 WordPress 데이터베이스에 액세스 할 수 있다면
Corcel이 좋은 옵션입니다. 그것은 PHP 패키지입니다 - Laravel과 함께 사용할 필요는 없습니다 - WordPress 게시물에서 Laravel Eloquent 모델을 생성합니다.

Corcel은 설치가 매우 간단합니다. 두 앱 (Laravel 또는 WordPress)에 동일한 데이터베이스를 사용할지 여부에 대해 생각해보십시오. 그렇지 않은 경우 동일한 서버 또는 자체 서버에 두 개의 데이터베이스를 가질 수 있습니다. 하나의 서버 또는 하나의 데이터베이스를 사용하는 것이 두 개의 데이터베이스 서버보다 쉽습니다. 그러나 두 서버가 확장 성이 뛰어날 수 있습니다. 또한 Laravel은 MySQL과 밀접하게 결합되어 있지 않으며 다른 데이터베이스 기술을 사용하고있어 데이터베이스 공유가 불가능합니다.

Corcel 설정이 완료되면 앱에서 간단한 Posts 컨트롤러를 만든 다음 Corcell을 사용하도록 리팩토링 할 수 있습니다.



<?php
namespace AppHttpControllers;
class Posts extends Controller {
    public function post( $id )
    {
        $post = Posts::find( $id );
        return view( 'wp.post', [
            'post' => $post
        ]);
    }
    public function posts()
    {
        $posts = Posts::paginate(15);
        return view( 'wp.posts', [
            'posts' => $posts
        ]);
    }
}



Caching REST API Queries

나는 동일한 데이터베이스에 연결하는 두 개의 앱에 대한 아이디어를 좋아하지 않는다. 차라리 WordPress REST API를 사용하는 것이 좋습니다. 그것은 WordPress를 격리 된 컨텐츠 제공자로 유지합니다. 먼저 Laravel에서 영구 객체 캐시 Redis (Memcached)를 사용하도록 첫 번째 예제를 수정 해 보겠습니다.

이렇게하면 Laravel에서 데이터의 수명이 짧은 사본이 채워지고 WordPress의로드가 최소화됩니다. 캐싱을 사용하려면 위에 표시된 WordPress REST API 클라이언트를 리펙터링하십시오. Laravel은 캐시 외관을 통해 다양한 캐싱 시스템에 대한 간단한 추상화를 제공합니다.

다음은 리팩토링 된 API 클라이언트입니다.


<?php
namespace App;
use IlluminateSupportFacadesCache;
class WpApi {
    protected static $url = 'https://calderaforms.com/wp-json/wp/v2<a>';
    public static function getPost(int $id )
    {
        $url = self::$url . 'posts/' . $id;
        return self::getJson(  $url  );
    }
    public static function getPosts( int $page )
    {
        $url = self::$url . '/posts?per_page=' . $page;
        return collect( self::getJson( $url ) );
    }
    protected static function getJson( $url)
    {
        $cached = Cache::get( md5( $url ) );
        if( empty( $cached ) ){
            $response = file_get_contents($url, false);
            $json = json_decode( $response );
            //store for 12 hours (12*60 minutes)
            Cache::put( md5( $url ), $json, 720 );
            return $json;
        }else{
            return $cached;
        }
    }
}


Creating a Service Provider

마지막 해결책은 Laravel 앱에 WordPress 관리 블로그를 추가하는 데 사용할 수 있습니다. 필자의 예에서는 로컬 데이터베이스에 저장된 콘텐츠를 제공해야했지만 대신 WordPress에서 REST API를 통해 가져 오는 방법이 필요했습니다.

내 응용 프로그램이 표시하는 내용의 끝 부분은 내용과 소스에 대한 링크입니다. 그래서 WordPress 데이터베이스에 콘텐츠를 복제하는 동안 게시물 제목, 발췌 내용, 범주 배열, 태그 배열, 추천 이미지, URL 및 퍼머 링크를 저장했습니다.


여러 경로를 사용하고 다른 WordPress 사이트에 대한 지원을 쉽게 추가 할 수있는 방식으로이 작업을 수행하기 위해 Model, REST API 클라이언트 및 서비스 공급자를 만들었습니다.

나는 완전하고 추상적 인 시스템을 여기에서 공유 할 수 없다. 그러나 Laravel에 익숙하다면 공유해야 할 것을 사용하여 자신의 시스템을 구성 할 수 있습니다.

여기에 설명 된 모델은 내가 필요한 게시물의 부분 만 가지고 있습니다.



<?php
namespace AppWPAPI;
use AppContractsContent;
class CalderaWP  extends AppAbstractsWPAPI  implements Content {
    protected $root = 'https://calderawp.com/wp-json';
    protected $routeConfig = [
        'posts' => 'wp/v2/posts',
        'cf-addons' => 'calderawp_api/v2/products/cf-addons'
    ];
    public function getAddOns( int $page = 1 ){
        return $this->get( 'posts',
            [
                'cf-addons' => $page
            ]
        );
    }
    public function getAddon( int $id )
    {
        return $this->get( 'cf-addon', [], $id );
    }
    public function getPosts( int  $page = 1, int $per_page = 50 )
    {
        return $this->get( 'posts',
            [
                'page' => $page,
                'per_page' => $per_page
            ]
        );
    }
    public function getPost( int $id )
    {
        return $this->get( 'posts', [], $id );
    }
    
}



이것은 좋은 출발점이지만, Redis와 같이 비 영구적 인 데이터베이스에서 작동하는 것을보고 싶습니다. 따라서 WordPress REST API 앞에 캐시와 같은 역할을합니다. 즉, 모델은 실제로 여기에 필요하지 않습니다. REST API 클라이언트가 서비스 공급자 일 경우 Laravel 컨트롤러에 직접 주입 할 수 있으므로 Laravel 내부에 영구 데이터베이스 저장소가 필요하지 않습니다.

Laravel 데이터베이스에 포스트 데이터를 가져 오는 시스템이 필요했습니다. 나는 두 개의 인터페이스를 사용했다. 첫 번째는 WordPress API 클라이언트 용이었고 두 번째는 콘텐츠 가져 오기 용이었습니다. 내 유스 케이스는 둘 다 구현하지만,이 시스템의 별도 구현은 컨텐트와 제품을 다르게 처리합니다.

다음은 API 클라이언트의 첫 번째 인터페이스입니다.

<?php
namespace AppContracts;
use AppWPAPIRouteCollection;
interface WPAPI {
    /**
     * Get the routes for this API
     *
     * @return RouteCollection
     */
    public function getRoutes() : RouteCollection;
    /**
     * Get root URL for API
     *
     * @return string
     */
    public function getRoot() : string ;
}


그리고 콘텐츠를위한 두 번째 인터페이스 :


<?php
namespace AppContracts;
use AppPost;
interface Content {
    /**
     * Get post by WordPress ID
     *
     * @param int $wp_id WordPress post ID
     *
     * @return Post
     */
    public function getPost( int $wp_id ) : Post;
}



일반 클래스에서 첫 번째 인터페이스를 구현하여 일반 REST API 클라이언트를 작성했습니다.

<?php
namespace AppAbstracts;
use AppWPAPIRoute;
use AppWPAPIRouteCollection;
/**
 * Class WPAPI
 *
 * Base WordPress REST API client
 * @package AppAbstracts
 */
abstract class WPAPI implements AppContractsWPAPI {
    /**
     * Array of routes to be used
     *
     * 'name' => 'url
     *
     * @var array
     */
    protected $routeConfig;
    /**
     * API root URL
     *
     * @var string
     */
    protected $root;
    /**
     * Routes for this API
     *
     * @var RouteCollection
     */
    protected $routes;
    public function __construct( ) {
        $this->routes = new RouteCollection();
        $this->constructRouteCollection();
    }
    public function getRoot() : string {
        $this->root;
    }
    public function getRoutes() : RouteCollection {
        return $this->routes;
    }
    public function get( string  $route, array $params = [], int $id = 0 ){
        try {
            $route = $this->routes->getRoute( $route );
        }catch ( Exception $e ){
            return $e;
        }
        if ( 0 == $id ) {
            $url = $this->trailingslashit( $this->root ) . $route->url . '?' . http_build_query( $params );
        } else {
            $url = $this->trailingslashit( $this->root ) . $this->trailingslashit( $route->url ) . "$id" . '?' . http_build_query( $params );
        }
        return json_decode( file_get_contents( $url ) );
    }
    protected function constructRouteCollection(){
        if( is_array( $this->routeConfig ) && ! empty( $this->routeConfig ) ){
            foreach ( $this->routeConfig as $name => $url ){
                $route = Route::factory( $name, $url );
                $this->routes->addRoute( $route );
            }
        }
    }
    protected function trailingslashit( $string ) {
        return $this->untrailingslashit( $string ) . '/';
    }
    protected function untrailingslashit( $string ) {
        return rtrim( $string, '/\' );
    }
}



해당 클래스에서 라우트가 경로 콜렉션을 빌드하는 데 사용되는 라우트 오브젝트로 표시된다는 것을 알 수 있습니다. 이 개체를 사용하면 WordPress REST API 경로 데이터를보다 쉽게 표현할 수 있습니다. 이 클래스들은 Github에있는 내 Object 라이브러리에 의존합니다.

다음은 라우트 이름과 URL의 컨테이너 인 라우트 클래스입니다.


<?php
namespace AppWPAPI;
use calderawpobjectalmostStdImmutable;
class Route extends almostStdImmutable {
    protected $name;
    protected $url;
    public static  function factory( string $name, string  $url ){
        $obj = new static();
        $obj->name = $name;
        $obj->url = $url;
        return $obj;
    }
}



다음은 경로 객체를 수집하는 routes 콜렉션입니다.



<?php
namespace AppWPAPI;
use calderawpobjectalmostStdImmutable;
class RouteCollection extends almostStdImmutable {
    
    protected $routes;
    /**
     * @param $name
     *
     * @return Route
     * @throws Exception
     */
    public function getRoute( $name ) : Route
    {
        if( array_key_exists( $name, $this->routes) ){
            return $this->routes[ $name ];
        }
        throw new Exception( 'No matching route' );
    }
    public function addRoute( Route $route ) :bool
    {
        $this->routes[ $route->name ] = $route;
        return true;
    }
}



이 모든 것을 통해 내 사이트의 구현을 위해 REST API 클라이언트를 확장 할 수있었습니다.



<?php
namespace AppWPAPI;
use AppContractsContent;
class CalderaWP  extends AppAbstractsWPAPI  implements Content {
    protected $root = 'https://calderawp.com/wp-json';
    protected $routeConfig = [
        'posts' => 'wp/v2/posts',
        'cf-addons' => 'calderawp_api/v2/products/cf-addons'
    ];
    public function getAddOns( int $page = 1 ){
        return $this->get( 'posts',
            [
                'cf-addons' => $page
            ]
        );
    }
    public function getAddon( int $id )
    {
        return $this->get( 'cf-addon', [], $id );
    }
    public function getPosts( int  $page = 1, int $per_page = 50 )
    {
        return $this->get( 'posts',
            [
                'page' => $page,
                'per_page' => $per_page
            ]
        );
    }
    public function getPost( int $id )
    {
        return $this->get( 'posts', [], $id );
    }
    
}



마지막으로, 수입업자 컨트롤러에 주입 할 수있는 서비스 제공 업체를 만들고 등록했지만 콘텐트를 표시하기 위해 컨트롤러에 주입 할 수도 있습니다.



<?php
namespace AppProviders;
use AppContentCalderaWP;
use IlluminateSupportServiceProvider;
class CalderaWPContentServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind( AppContractsContent::class, function(  $app ){
            return new CalderaWP( );
        });
    }
    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return ['AppContentCalderaWP'];
    }
}


Great Options In PHP

WordPress REST API는 다양한 방법으로 WordPress를 사용할 수있는 기회를 제공합니다. 또한 여러 가지 기술을 배우는 동기가되었습니다. Laravel은 내가 배웠던 것이 정말 기쁜 도구입니다. 이 기사가 WordPress REST API에서 Laravel 또는 다른 Symfony 기반 PHP 프레임 워크를 사용하기위한 옵션을 보는 데 도움이되기를 바랍니다.














Comments

Category
반응형 구글광고 등
State
  • 현재 접속자 5 명
  • 오늘 방문자 76 명
  • 어제 방문자 282 명
  • 최대 방문자 420 명
  • 전체 방문자 65,851 명
  • 전체 게시물 311 개
  • 전체 댓글수 2 개
  • 전체 회원수 20 명
Facebook Twitter GooglePlus KakaoStory NaverBand