web-dev-qa-db-ja.com

AngularJSパーシャルファイルでWordPress(PHP)関数を使用する方法

私はWordPressの投稿のリストを読み込むためにAngularJSを使用していますが、PHP関数をパーシャルファイルで使用することはできません。

search.phpの代わりにsearch.htmlのようなものを使用しようとしましたが、そうすると致命的なエラーget_post_metaのようなエラーが発生します.

クライアント側とサーバー側を混在させることは想定されていませんし、PHPを解析するために何らかのサービスを使用することもできますが、その方法についてはわかりません。カスタムフィールドを表示できるようにPHPタグをレンダリングし、そこにあるいくつかのPHP関数を使用するには、search.phpが必要です。

これを行う最善の方法は何ですか?

私のページテンプレート(.php)に私は -

<div id="page" ng-app="app">
        <header>
            <h1>
                <a href="<?php echo home_url(); ?>">Search</a>
            </h1>
        </header>
  <?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>

   <div ng-Cloak ng-controller="MyController" class="my-controller">
<div ng-view></div>     
</div>
  <?php endwhile; ?>
 <?php endif; ?>
<?php rewind_posts(); ?>
<div ng-controller="OtherController" class="other-controller">
          <div class="text-center">
          <dir-pagination-controls boundary-links="true" on-page-change="pageChangeHandler(newPageNumber)" template-url="/partials/dirPagination.tpl.html"></dir-pagination-controls>
          </div>
        </div>
        <footer>
            &copy; <?php echo date( 'Y' ); ?>
        </footer>
    </div>

そして私のPHPファイルに表示させたいのは -

<?php 
$pcomp1b = get_post_meta(get_the_ID(), 'pa_meta_comp1b', true); 
$pcomp1c = get_post_meta(get_the_ID(), 'pa_meta_comp1c', true);
$pcomp1d = get_post_meta(get_the_ID(), 'pa_meta_comp1d', true); ?>

数学 -

if( is_numeric( $price1 ) ) {
    $a1 = $price1;
}
$b1 = $pcomp1d;
$sqft1 = str_replace( ',', '', $b1 );

if( is_numeric( $sqft1 ) ) {
    $b1 = $sqft1;
}

$a2 = $pcomp2f;
$price2 = str_replace( ',', '', $a2 );

if( is_numeric( $price2 ) ) {
    $a2 = $price2;
}
$b2 = $pcomp2d;
$sqft2 = str_replace( ',', '', $b2 );

if( is_numeric( $sqft2 ) ) {
    $b2 = $sqft2;
}

$a3 = $pcomp3f;
$price3 = str_replace( ',', '', $a3 );

if( is_numeric( $price3 ) ) {
    $a3 = $price3;
}
$b3 = $pcomp3d;
$sqft3 = str_replace( ',', '', $b3 );

if( is_numeric( $sqft3 ) ) {
    $b3 = $sqft3;
}
$ppsqft1 = ROUND($price1 / $sqft1);
$ppsqft2 = ROUND($price2 / $sqft2);
$ppsqft3 = ROUND($price3 / $sqft3);

$ppsav = ROUND((($ppsqft1 + $ppsqft2 + $ppsqft3)/3));

$b4 = $property_area;
$parea = str_replace( ',', '', $b4 );

if( is_numeric( $parea ) ) {
    $b4 = $parea;
}
$ehvp = $ppsav * $parea;
$homevalue = number_format($ehvp, 0, '.', ',');
echo '$' . $homevalue; ?>

そして機能 -

<?php if (class_exists('MRP_Multi_Rating_API')){ MRP_Multi_Rating_API::display_rating_result(array('rating_item_ids' => 2, 'show_count' => false, 'result_type' => 'value_rt', 'no_rating_results_text' => 'N/A'));} ?>

それでどうやってこれをng-viewと私のパーシャルテンプレートで動作させることができますか?

_アップデート_

これが私の現在の設定がどのように見えるかです - 最初に私はsearch-results.phpと呼ばれるページテンプレートを持っています -

<?php
/* Template Name:Search Results */ ?>
    <!DOCTYPE html>
<html>
<head>
    <base href="<?php $url_info = parse_url( home_url() ); echo trailingslashit( $url_info['path'] ); ?>">
        <title>Search</title>
<link rel="stylesheet" type="text/css" href="/style.css" media="print" />
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.3.0.min.js"></script>
    <?php wp_head(); ?>
</head>
<body>
    <div id="page" ng-app="app">
        <header>
            <h1>
                <a href="<?php echo home_url(); ?>">Search</a>
            </h1>
        </header>
  <?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>

   <div ng-Cloak ng-controller="MyController" class="my-controller">
<div ng-view></div></div>
  <?php endwhile; ?>
 <?php endif; ?>
<?php rewind_posts(); ?>
<div ng-controller="OtherController" class="other-controller">
          <div class="text-center">
          <dir-pagination-controls boundary-links="true" on-page-change="pageChangeHandler(newPageNumber)" template-url="/partials/dirPagination.tpl.html"></dir-pagination-controls>
          </div>
        </div>
        <footer>
            &copy; <?php echo date( 'Y' ); ?>
        </footer>
    </div>
<script>
function getdata($scope,$http){
$http.get("/wp-json/posts?type=property")
.success(function(data)
{$scope.result = data;}
);
}
</script>

    <?php wp_footer(); ?>
</body>
</html>

それから部分的にphpファイルを呼び出さずに私のアプリのスクリプト -

var app = angular.module('app', ['ngRoute', 'ngSanitize', 'angularUtils.directives.dirPagination'])

function MyController($scope) {


$scope.currentPage = 1;

$scope.pageSize = 2;

$scope.posts = [];


$scope.pageChangeHandler = function(num) {

console.log('search page changed to ' + num);
  };
}



function OtherController($scope) {

$scope.pageChangeHandler = function(num) {

console.log('going to page ' + num);
  };
}



app.config(function(paginationTemplateProvider) {
    paginationTemplateProvider.setPath('/partials/dirPagination.tpl.html');
});

app.config(function($routeProvider, $locationProvider) {
    $locationProvider.html5Mode(true);

    $routeProvider
    .when('/search-results', {
        templateUrl: myLocalized.partials + 'main.html',
        controller: 'Main'
    })
    .when('/:ID', {
        templateUrl: myLocalized.partials + 'content.html',
        controller: 'Content'
    });
})
app.controller('Main', function($scope, $http, $routeParams) {
    $http.get('wp-json/posts?type=property').success(function(res){
        $scope.posts = res;
    });
})
app.controller('Content', function($scope, $http, $routeParams) {
    $http.get('wp-json/posts?type=property/?filter["posts_per_page"]=25&filter["orderby"]=date&filter["order"]=desc/' + $routeParams.ID).success(function(res){
        $scope.post = res;
    });
});


app.controller('MyController', MyController);
app.controller('OtherController', OtherController);

それから部分的なファイルは私の最初の質問で示された機能とコードを持つsearch.phpファイルになるでしょう。

1
Rich

1)URL書き換え

私は可愛い partial url rewritees にしています。セットアップ、カスタマイズが簡単で、WordPressのすべてにアクセスできます。

以下のクラスでは、 rewritees が追加されています( rewriteルールをフラッシュします を1回だけ実行する必要があります)。 (regEx - > query_vars )。面白いのは、JSONデータを返すためにいつでもリクエストを強制終了できること、または使用する template ページを指定することに加えてWordPressにそれを実行させることです。

だから我々はフロントエンドの要求をオンにするつもりです:

example.com/api/angular/partial/custom

内部的に使用できるものとして

example.com/index.php?__api_angular=1&partial=custom

rewrite を登録するとき、regExに何か特別なものを追加する必要があります - しかし、これが問題になると思います。

このクラスは実際にはどこにでも追加できます( functions.php // plugins )。それは自分自身をインスタンス化し、それがinit()に必要なものをフックする。個人的には、コードが含まれていて、クラスがどこか他の場所で定義されていても競合しないので、私はクラスを使用するのが好きです。

<?php

if ( ! class_exists( 'AngularEndpoint' ) ):

    class AngularEndpoint {
        const ENDPOINT_QUERY_NAME  = 'api/angular';
        const ENDPOINT_QUERY_PARAM = '__api_angular';

        // WordPress hooks

        public function init() {
            add_filter( 'query_vars', array ( $this, 'add_query_vars' ), 0 );
            add_action( 'parse_request', array ( $this, 'sniff_requests' ), 0 );
            add_action( 'init', array ( $this, 'add_endpoint' ), 0 );
        }

        // Add public query vars

        public function add_query_vars( $vars ) {

            // add all the things we know we'll use

            $vars[] = static::ENDPOINT_QUERY_PARAM;
            $vars[] = 'partial';
            $vars[] = 'filter';
            $vars[] = 'type';

            return $vars;
        }

        // Add API Endpoint

        public function add_endpoint() {
            add_rewrite_rule( '^' . static::ENDPOINT_QUERY_NAME . '/partial/([^/]*)/?', 'index.php?' . static::ENDPOINT_QUERY_PARAM . '=1&partial=$matches[1]', 'top' );

            //////////////////////////////////
            flush_rewrite_rules( false ); //// <---------- REMOVE THIS WHEN DONE
            //////////////////////////////////
        }

        // Sniff Requests

        public function sniff_requests( $wp_query ) {
            global $wp;

            if ( isset(
                $wp->query_vars[ static::ENDPOINT_QUERY_PARAM ],
                $wp->query_vars[ 'partial' ] ) ) {
                $this->handle_partial_request(); // handle it
            }
        }

        // Handle Requests

        protected function handle_partial_request() {
            global $wp;

            $partial_requested = $wp->query_vars[ 'partial' ];

            switch ( $partial_requested ) {

                // example.com/api/angular/partial/ping
                case 'ping':
                    wp_send_json_success( array (
                        'message' => 'Enjoy your partial', 'partial' => $partial_requested,
                    ) );
                    break;

                // example.com/api/angular/partial/custom
                case 'custom':
                    add_filter( 'template_include', function( $original_template ) {
                        return __DIR__ . '/custom.php';
                    } );
                    break;

                // example.com/api/angular/partial/search
                case 'search':
                    add_filter( 'template_include', function( $original_template ) {
                        return get_template_directory() . '/search.php';
                    } );
                    break;
                default:
                    wp_send_json_error( array ( 'message' => 'Invalid Request' ) );
            }
        }
    }

    $wpAngularEndpoint = new AngularEndpoint();
    $wpAngularEndpoint->init();

endif; // AngularEndpoint

custom.php example.com/api/angular/partial/customのテンプレートとして使用されます。

<html>
<body>
<h1>Custom Stuff</h1>
<h2><?php echo "PHP Stuff" ?></h2>
<?php
$posts = get_posts();
?>
<ul>
<?php
    foreach ( $posts as $post ) {
        echo '<li>' . $post->post_title . '</li>' . PHP_EOL;
    }
?>
</ul>
</body>
</html>

2)休憩路

もう1つの選択肢は、既にwp-jsonを使用しているため、カスタムの rest route を作成することです。ここで必要とされるより少ないセットアップがあります。

<?php

if ( ! class_exists( 'AngularJSONEndpoint' ) ):

    class AngularJSONEndpoint {
        const ENDPOINT_NAMESPACE  = 'namespace/v2';

        /**
         * Initialize WordPress hooks
         */
        public function init() {
            add_action( 'init', array ( $this, 'add_endpoint' ), 0 );
        }

        /**
         * Add JSON API Endpoint
         */
        public function add_endpoint() {

            add_action('rest_api_init', function () {

                // http://example.com/wp-json/namespace/v2/angular?partial=custom

                register_rest_route( static::ENDPOINT_NAMESPACE, '/angular', array (
                    'methods'             => 'GET',
                    'callback'            => array($this, 'wp_json_namespace_v2__angular'),
                    'permission_callback' => function (WP_REST_Request $request) {
                        return true;
                    }
                ));
            });

            flush_rewrite_rules(true); // FIXME: <------- DONT LEAVE ME HERE
        }

        /**
         * Handle the endpoint
         * @param $request
         *
         * @return WP_REST_Response
         */
        function wp_json_namespace_v2__angular($request)
        {
            // json-api params

            $parameters = $request->get_query_params();

            // check for partial requests

            if(isset($parameters['partial'])){
                switch($parameters['partial']) {
                    case 'custom':
                        require __DIR__ . '/custom.php';
                        die();
                }
            }

            // return results

            $data = array(
                'success' => false,
                'message' => 'Bad Request'
            );

            return new WP_REST_Response($data, 400);
        }
    }

    $wpAngularJSONEndpoint = new AngularJSONEndpoint();
    $wpAngularJSONEndpoint->init();

endif; // AngularJSONEndpoint
1
jgraup

うまくいっているのは、WPのAjaxエンドポイントを呼び出すことです。これはパーシャルのアドレスではなく、すべてのWP呼び出しの固定のAJAXアドレスです。

wp_localize_script('handle', 'myLocalized', array(
     'ajaxUrl' => admin_url( 'admin-ajax.php' )
) );

jSオブジェクトmyLocalized内のエンドポイントアドレスを提供します。あなたはそのページにすべてのリクエストを送り、あなたのパーシャルをGETパラメータとしてのみ参照します。

$routeProvider.when('/search-results', {
    templateUrl: myLocalized.ajaxUrl + '?action=get_my_partial&partial=' + 'main';
    controller: 'Main'
}).when('/:ID', {
    templateUrl: myLocalized.ajaxUrl + '?action=get_my_partial&partial=' + 'content';
    controller: 'Content'
});

パラメータadmin-ajax.phpを指定した{action}へのすべての呼び出しは、wp_ajax_{action}(ログインユーザーの場合)またはwp_ajax_nopriv_{action}(ログインしていないユーザーの場合)という名前のアクションにルーティングされます。サーバーサイドでは、それらに接続してパーシャルを含めることができます。

function get_the_partials () {
    switch ( $_GET['partial'] ) {
        case 'main':
            // check authorization
            include plugin_dir_path(__FILE__) .'/partials/main.html';
            break;
        case 'content':
            // check authorization
            include plugin_dir_path(__FILE__) .'/partials/content.html';
            break;
        default:
            wp_die( 'Nothing found.' );
            break;
    }
    die();
}
add_action( 'wp_ajax_nopriv_get_my_partial', 'get_the_partials' );
add_action( 'wp_ajax_get_my_partial', 'get_the_partials' );

このようにして、WordPressは完全に初期化され、通常利用可能な機能を処理することができます。 (まあ、ループの外側)

あなたがコントローラからそしてwp-jsonエンドポイントを通して特定の投稿を選択することを扱うので、それはそれをするべきです。

1
ccprog