web-dev-qa-db-fra.com

Comment utiliser les fonctions WordPress (PHP) dans les fichiers partiels AngularJS?

J'utilise AngularJS pour charger une liste de mes publications WordPress. Cependant, je ne peux utiliser aucune de mes fonctions PHP avec mon fichier de partiels.

J'ai essayé d'utiliser quelque chose comme search.php au lieu de search.html, mais des erreurs telles que l'erreur fatale get_post_meta ne sont pas définies.

Maintenant, je sais que nous ne sommes pas supposés mélanger le côté client avec le côté serveur, et je peux éventuellement utiliser un type de service pour analyser mon code PHP, mais je ne sais pas comment procéder. J'ai besoin de mon search.php pour générer le rendu de mes balises PHP afin d'afficher des champs personnalisés et d'utiliser plusieurs fonctions PHP dont je dispose.

Quel est le meilleur moyen de le faire?

Sur mon modèle de page (.php), j'ai -

<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>

Et sur mon fichier PHP, je souhaite être appelé avec des fonctions telles que -

<?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); ?>

Math --

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; ?>

Et fonctions -

<?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'));} ?>

Alors, comment puis-je le faire fonctionner avec ng-view et mes modèles de partiels?

METTRE À JOUR

Voici à quoi ressemble ma configuration actuelle - D'abord, j'ai un modèle de page appelé 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>

Ensuite, mon script d'application sans appeler le fichier php comme une partie -

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);

Ensuite, le fichier partiel sera un fichier search.php avec les fonctions et le code indiqués dans ma question initiale.

1
Rich

1) Réécriture d'URL

Je suis jolie partial to url réécrit . Ils sont faciles à configurer, à personnaliser et vous avez accès à tout WordPress.

Dans la classe ci-dessous, vous pouvez voir que rewrites sont ajoutés (vous devez seulement effacer les règles de réécriture une fois) et si une partie de l'URL correspond, les sections peuvent être utilisées comme variables dynamiques (regEx -> query_vars ). La partie amusante est que vous pouvez supprimer la demande à tout moment pour renvoyer des données JSON, ou laisser WordPress s'occuper de cela, en plus de spécifier la page template à utiliser.

Nous allons donc transformer une demande frontale pour:

example.com/api/angular/partial/custom

en quelque chose que nous pouvons utiliser en interne comme:

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

Tout ce qui est extra devrait être ajouté dans le regEx lors de l’enregistrement de rewrite - mais je pense que cela fait passer le message.

Cette classe peut être ajoutée n'importe où vraiment ( functions.php / plugins ). Il s'installe et accroche ce dont il a besoin dans init(). Personnellement, j'aime utiliser une classe parce que le code est contenu et qu'il ne sera pas en conflit si la classe est définie ailleurs ... eh bien, la classe ne sera pas recréée si elle est déjà définie.

<?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 Utilisé comme modèle pour 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) Route de repos

Une autre option, puisque vous utilisez déjà wp-json, consiste à créer une route personnalisée rest . Il y a moins de configuration requise ici, ce qui est un plus.

<?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

Ce qui fonctionne, c'est appeler le point de terminaison Ajax de WP. Notez que ce n'est pas l'adresse de votre partiel, mais l'adresse fixe WP pour tous les appels AJAX

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

fournit l'adresse du noeud final dans l'objet JS myLocalized. Vous envoyez toutes les demandes à cette page et vous vous référez à vos partiels uniquement en tant que paramètres 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'
});

Tous les appels à admin-ajax.php avec un paramètre {action} sont acheminés vers des actions nommées wp_ajax_{action} (pour les utilisateurs connectés) ou wp_ajax_nopriv_{action} (pour les utilisateurs non connectés). Du côté du serveur, vous pouvez vous y connecter et inclure vos partiels:

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' );

De cette façon, WordPress est entièrement initialisé et peut gérer toutes les fonctions normalement disponibles. (Eh bien, en dehors de la boucle.)

Puisque vous gérez la sélection de publications spécifiques à partir du contrôleur et par le biais du terminal wp-json, cela devrait le faire.

1
ccprog