SlideShare uma empresa Scribd logo
1 de 122
Baixar para ler offline
WORDPRESS REST API AND
ANGULARJS
FTW!
Roy Sivan and Josh Pollock
CalderaLearn.com
CalderaLabs.org
Join our Slack
LoopConf Slack: #workshop-wpapi
We will be posting links, taking
questions, and communicating
throughout the day via Slack
CalderaLabs.org
Hi I'm Josh
Lead Developer: Caldera Labs
I make WordPress plugins
I teach about WordPress
I wrote a book about the WordPress REST API
I am a core contributor to WordPress
I am a member of The WP Crowd
CalderaLearn.com
Hi, I'm Roy
Senior Software Engineer:
The Walt Disney Company
I am a member of The WP Crowd
I blog on roysivan.com
I teach on Lynda.com & CalderaLearn
People say Hi to me a lot
What We're Covering Today
REST API 101
Building Custom REST APIs
Unit Testing Custom REST APIs
LUNCH BREAK
AngularJS (1.x) Basics
Building Decoupled Front-ends
Building Plugin Admin Screens
Educational Philosophy
All code is or is based on real world projects
We will show different ways of doing the same
thing.
Please ask why it's different
◇ we may give you a good answer
Stop us and ask questions
Structure For Today
foreach ( $sections as $section ) :
Concepts / Lecture
Example Code Walkthrough (you will be cloning locally)
Hands-on
DIY Group
Walk Through Code Group
endforeach;
WARNING
This workshop is to help you understand the basics
and some advanced technologies. Nothing will be
production ready code.
What you need for today
IDE or text editor (PHPStorm, Sublime, etc.)
Local WP install (VVV, DesktopServer, etc.)
npm
PHPUnit (optional, included in VVV)
Composer (optional)
AngularJS Batarang Chrome Extension
https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehid
hipcmcojjgiloacoafjmpfk?hl=en
CalderaLabs.org
0.
WordPress REST API?
Do we even need it?
CalderaLabs.org
NO
But you can build cool stuff with it.
It’s all about the Data
Data!
Data!
Data!
“
CalderaLearn.com
The API allows you to take WP data and put it in a
bucket. What you do with that bucket is up to you.
-- Morten Rand Hendriksen
@mor10
CalderaLabs.org
What can we
build with it?
Facebooks? Myspaces?
API Powered Stuff
Things you can build that are powered by the API
Phone apps
Custom UI widgets on your site
Why use feed of another site, when you can API
Custom Dashboards in the admin
Custom WP Dashboard (YAS!)
User role based dashboard
CalderaLabs.org
1.
Custom REST APIs
With The WordPress REST API
CalderaLabs.org
Modify Default Routes
CalderaLabs.org
WordPress Gives Us
Routes
Which We Can Extend
CalderaLabs.org
Create Your Own Routes
CalderaLabs.org
Or We Can Make Our Own
With The Same Tools
How The REST API Works
WP_REST_Server ??WP_REST_Request WP_REST_Response
How The REST API Works
WP_REST_Server
Route
Callback
WP_REST_Request WP_REST_Response
ERROR!
ERROR!
CalderaLabs.org
Let's Talk About The
Orange Box
The Route Callback
Customizing The
Defaults
CalderaLabs.org
Extending Defaults
Adding Post Type
Support
add_action( 'init', 'my_book_cpt' );
function my_book_cpt() {
$labels = array(...);
$args = array(
...
'rest_controller_class' => 'WP_REST_Posts_Controller',
'show_in_rest' => true,
'rest_base' => 'books-api',
);
register_post_type( 'book', $args );
}
Add REST API Support To Post Type Registration
add_action( 'init', 'my_custom_post_type_rest_support', 25 );
function my_custom_post_type_rest_support() {
global $wp_post_types;
$post_type_name = 'book';
if( isset( $wp_post_types[ $post_type_name ] ) ) {
$wp_post_types[$post_type_name]->show_in_rest = true;
$wp_post_types[$post_type_name]->rest_base = $post_type_name;
$wp_post_types[$post_type_name]->rest_controller_class =
'WP_REST_Posts_Controller';
}
}
Add REST API Support To An Existing Post Type
CalderaLabs.org
Extending Defaults
Adding A Custom Field
CalderaLabs.org
Custom Field Is Any Data
Not just meta fields
function slug_get_meta_field( $object, $field_name, $request ) {
return get_post_meta( $object[ 'id' ], $field_name );
}
function slug_update_meta( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_post_meta( $object->ID, $field_name, strip_tags(
$value ) );
}
Adding Custom Fields To A Response: Callbacks
add_action( 'rest_api_init', 'slug_register_spaceship' );
function slug_register_spaceship() {
register_api_field( 'post',
'starship',
array(
'get_callback' => 'slug_get_meta_field',
'update_callback' => 'slug_update_meta_field',
)
);
}
Adding Custom Fields To A Response: Registration
CalderaLabs.org
Making Custom REST
APIs
The Basics
How It Works
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/author/(?P<id>d+)', array(
'methods' => 'GET',
'callback' => 'route_callback',
) );
} );
Registering A Route
CalderaLabs.org
Creating Callback Class
Register Route(s)
class my_simple_route {
public function register_routes(){
$namespace = 'my-api/v1';
register_rest_route( $namespace, '/items', [
'methods' => 'GET',
'callback' => [ $this, 'get_items' ],
'permissions_callback' => [ $this, 'get_items_permissions' ]
] );
...
}
}
Registering Route(s)
class my_simple_route {
public function register_routes(){
...
register_rest_route( $namespace, '/items/(?P<id>d+)', [
'methods' => 'GET',
'callback' => [ $this, 'get_item' ],
'permissions_callback' => [ $this,
'get_item_permissions' ]
] );
}
}
Registering Route(s)
CalderaLabs.org
Creating Callback Class
Defining Route Fields
register_rest_route( $this->namespace, '/items/(?P<id>d+)', [
...
'args' => [
'type' => [
'required' => true,
'validate_callback' => [ $this, 'validate_type' ]
],
'number' => [
'default' => 5,
'sanitize_callback' => 'absint'
]
]
] );
Registering Route(s) : Defining Fields
Registering Route(s) : Field Sanitization Callback
Use to ensure data is safe.
Defined using a callable.
Change data to a safe value.
Return prepared value
Registering Route(s) : Field Validation Callback
Use to ensure data is correct.
Defined using a callable.
Used to reject invalid requests
Return true or false
Registering Route(s) : Field Validation Callback
public function validate_type( $value ){
if( !in_array( $value, [ 'big', 'small',
'very-small' ] ) ){
return false;
}
return true;
}
CalderaLabs.org
Creating Callback Class
Permissions Callback
Registering Route(s) : Permissions Callback
Determine if user is authorized.
Return true or false
Registering Route(s) : Permissions Callback
Example: Make require login.
public function get_items_permissions(){
if( is_user_logged_in() ){
return true;
}
return false;
}
Registering Route(s) : Permissions Callback
Example: Limit To Admins
public function get_items_permissions(){
if( current_user_can( 'manage_options' ) ){
return true;
}
return false;
}
Registering Route(s) : Permissions Callback
Example: Allow Always
public function get_items_permissions(){
return true;
}
CalderaLabs.org
Creating Callback Class
Route Callback Function
Registering Route(s) : Callback
Do something with the request
Gets an object of WP_REST_Request
Should return WP_REST_Response or WP_Error
WP_Rest_Response
Represents current request
Contains:
◇ Parameters
◇ Headers
No need to access $_GET, $_POST, $_REQUEST
Implements Arrayaccess
$request->param( 'field_name' );
$request[ 'field_name' ];
Registering Route(s) : Callback
public function get_item( WP_REST_Request $request ){
$id = $request[ 'id' ];
$item = slug_crud_get( $id );
if( ! empty( $item ) && ! is_wp_error( $item ) ){
return rest_ensure_response( $item );
}elseif ( is_wp_error( $item ) ){
return $item;
}else{
$response = new WP_REST_Response( 'No items found', 404 );
return $response;
}
}
CalderaLabs.org
Initializing The Class
The rest_api_init action
CalderaLabs.org
rest_api_init
Use To Load Code Only
Needed In REST API Requests
Registering Route(s) : Initializing
add_action( 'rest_api_init', function(){
$route = new my_simple_route();
$route->register_routes();
});
CalderaLabs.org
2.
Unit Testing Custom
REST APIs
Subtitle
CalderaLearn.com
Goal
Only Test Our Endpoints
CalderaLabs.org
PHPUnit +
WP_UnitTestCase
CalderaLabs.org
Setting Up
Prepare To Test
Unit Testing 101
Make Sure Things Return What They Should Return
$this->assertEquals( 42, function_that_returns_42() );
$this->assertSame( '42', function_that_returns_42() );
$this->assertArrayHasKey( 'roy', array( 'roy' => 'hi' ) );
Google: "Pippin Williamson Unit Tests for WordPress Plugins"
Install PHPUnit
wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
mv phpunit.phar /usr/local/bin/phpunit
wget https://phar.phpunit.de/phpunit.phar
php phpunit.phar
Install WP CLI
curl -O
https://raw.githubusercontent.com/wp-cli/builds/gh-pages/
phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
Initialize Unit Tests
wp scaffold plugin-tests
CalderaLabs.org
Writing Tests
Testing!
CalderaLearn.com
Mock
Requests
An Example
public function test_get_items_author_query() {
$this->factory->post->create( array( 'post_author' => 4 ) );
$this->factory->post->create( array( 'post_author' => 4 ) );
$this->factory->post->create( array( 'post_author' => 2 );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 3, count( $response->get_data() ) );
}
An Example
public function test_get_items_author_query() {
$this->factory->post->create( array( 'post_author' => 4 ) );
$this->factory->post->create( array( 'post_author' => 4 ) );
$this->factory->post->create( array( 'post_author' => 2 );
$request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
$request->set_param( 'author', 4 );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 2, count( $response->get_data() ) );
}
CalderaLearn.com
Test Case
Unit Test Case For REST API Endpoints
Create a reusable class that:
Create Instance of WP_REST_Server
Boot routes
Make sure route is booted
Test Case Outline
class Test_API extends WP_UnitTestCase {
/** @var WP_REST_Server*/
protected $server;
protected $namespaced_route = 'caldera-forms/v1';
public function setUp() {}
public function test_register_route() {}
public function test_endpoints() {}
}
Test Case: Set Up
protected $server;
public function setUp() {
parent::setUp();
/** @var WP_REST_Server $wp_rest_server */
global $wp_rest_server;
$this->server = $wp_rest_server = new WP_REST_Server;
do_action( 'rest_api_init' );
}
Test Case: Test Route Is Registered
public function test_register_route() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( $this->namespaced_route,
$routes );
}
Test Case: Test Endpoints Exist
public function test_endpoints() {
$the_route = $this->namespaced_route;
$routes = $this->server->get_routes();
foreach( $routes as $route => $route_config ) {
if( 0 === strpos( $the_route, $route ) ) {
$this->assertTrue( is_array( $route_config ) );
foreach( $route_config as $i => $endpoint ) {
$this->assertArrayHasKey( 'callback', $endpoint );
$this->assertArrayHasKey( 0, $endpoint[ 'callback' ], get_class( $this ) );
$this->assertArrayHasKey( 1, $endpoint[ 'callback' ], get_class( $this ) );
$this->assertTrue( is_callable( array( $endpoint[ 'callback' ][0], $endpoint[ 'callbac
][1] ) ) );
}
}
}
CalderaLearn.com
Testing
Custom Routes
Test Your API Only!!!
Test internal logic elsewhere
Test control of that logic
Test response format
Trust core
Example Route Test
class Test_Hi extends Test_API {
protected $namespace = '/hi-api/v1/names';
public function test_list() {
$request = new WP_REST_Request( 'GET', $this->namespace );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertArrayHasKey( 'name', $data[0] );
$this->assertEquals( 'shawn', $data[0][ 'name' ] );
$this->assertArrayHasKey( 'name', $data[1] );
$this->assertEquals( 'roy', $data[1][ 'name' ] );
}
}
Example Route Test
class Test_Hi extends Test_API {
protected $namespace = '/hi-api/v1/names';
public function test_single(){
$request = new WP_REST_Request( 'GET', $this->namespace . '/roy' );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$data = $response->get_data();
$this->assertArrayHasKey( 'name', $data );
$this->assertEquals( 'roy', $data[ 'name' ] );
}
}
CalderaLabs.org
3.
Getting Started With
AngularJS 1.x
Controllers, Templates, Services & Factories
CalderaLabs.org
3 con’t
Why Angular?
You know it’s in the title of the workshop, right?
“
CalderaLearn.com
AngularJS is the best JavaScript Framework.
-- Roy Sivan
Senior WordPress Engineer at Disney (so you know he is legit)
Not WordPress
To get you through the basics of
AngularJS we will be using
sample data, not WP
Our First Project
No npm or gulp
We aren’t using any build tools,
this is a pure sample
https://github.com/caldera-learn/angularjs-intro
Quicker & Easier
Quicker to get going to show
overall concepts.
Honest Truth
We already have a few projects
built in it that are ready to go
Why 1.x? 2 is in RC!
Roy is lazy
I am not lazy, but didn’t have
time to learn it deeply enough
yet to give a full workshop on it.
Josh Switched Teams
He used to be team NG1.
Now he is team VueJS.
HTML powered JavaScript
With Angular 1.x you can use
HTML to do most things reserved
for PHP.
Get the data using JS, template
with HTML. No PHP needed.
CalderaLearn.com
Step 1
Setup the APP
Setting up the app
All functionality lives within 1 app
We use ng-app to encapsulate the app in the DOM, it can be used on
any element including HTML.
Using it on the HTML encapsulates the whole DOM
Sample Data JSON
data.json
This file is going to be a sample of data, that we are going to use to build out
a simple Angular App, we will then replace it with the WordPress REST API
Injectables
Injectables are objects which can be injected and used in
controllers, directives, etc.
We will be creating our own later...
AngularJS Controllers
Controller is all about $scope
A Controller is defined by a JavaScript constructor function that is used to
augment the AngularJS Scope. When a Controller is attached to the DOM via
the ng-controller directive, AngularJS will instantiate a new Controller
object, using the specified Controller's constructor function
All new data to be used must be stored within $scope.your_key
ng-controller
All Together - JS
wpNG = {};
wpNG.app = ( function( app ){
console.log( 'initializing..' );
// define our app
app = angular.module('wpAngularApp', [])
.controller( 'listView', ['$scope', '$http', function( $scope, $http ) {
…
}]);
return app;
}(wpNG.app || {});
All Together - HTML
<div ng-app="wpAngularApp" id="app-container">
<div ng-controller="listView">
<!-- List View -->
</div>
</div>
CalderaLearn.com
Step 2
HTML! Looping through the data
First we must get data
$http is a jQuery AJAX wrapper & returns a promise
$http({method: ‘’, url: ‘’})
$http.get(url)
$http.post(url)
Because it returns a promise we use .then()
Say hello to JSON
JSON is the JavaScript Object Notation.
We display JSON with curly brackets
We work with JSON similar to PHP arrays
{{Object.key}} displays that key value
In PHP that would be $object[‘key’];
The loop HTML
<div ng-controller="listView">
<h2>Posts</h2>
<!-- Loop through $scope.posts -->
<article ng-repeat="post in posts">
<h2>{{post.title}}</h2>
</article>
</div>
Add more data
<article ng-repeat="post in posts">
<img ng-src="{{post.image}}" />
<h2>{{post.title}}</h2>
<div
class="post-content"
ng-bind-html="post.content | to_trusted">
</div>
</article>
CalderaLabs.org
4.
Decoupled Front-ends
With AngularJS
A site has no WordPress
Decoupled Front End
Decouple front end is a front end app that doesn’t live within
WordPress at all.
Your website: myawesomesite.com
Decoupled: myawesomeapp.com - but running on the same
data!
How cool is that!
Decoupled Use Cases
Phone App
Piece of functionality that communicates with WP data
Advanced, Unique UI
Combine with other APIs
Different Stack (decoupled app doesn’t need to be PHP)
Our decoupled App
npm
gulp
REST url that is publicly accessible (we will give you one)
Tacos, you always need tacos.
What you will need:
https://github.com/caldera-learn/decoupled-app
CalderaLabs.org
What About CORS?
Cross-Origin Resource Sharing
CORS
Allows browsers to make requests across
domains.
IS NOT SECURITY!!
By default WordPress REST API is same-origin
only.
Set at rest_pre_serve_request hook
Allow All Domains For All Methods
add_action( 'rest_api_init', function() {
remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
add_filter( 'rest_pre_serve_request', function( $value ) {
header( 'Access-Control-Allow-Origin: *' );
header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT,
DELETE' );
header( 'Access-Control-Allow-Credentials: true' );
return $value;
});
}, 15 );
Only Allow GET Requests
add_action( 'rest_api_init', function() {
remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
add_filter( 'rest_pre_serve_request', function( $value ) {
$origin = get_http_origin();
if ( $origin ) {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
}
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) );
header( 'Access-Control-Allow-Methods: GET' );
return $value;
});
}, 15 );
Allows From Certain Origins
add_action( 'rest_api_init', function() {
remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );
add_filter( 'rest_pre_serve_request', function( $value ) {
$origin = get_http_origin();
if ( $origin && in_array( $origin, array(
'https://hiroy.club'
) ) ) {
header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) );
header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' );
header( 'Access-Control-Allow-Credentials: true' );
}
return $value;
});
}, 15 );
CalderaLabs.org
Factories, Storage,
UI-Router, and
Templates
All the things!
AngularJS Factories
Factories allow you to create injectable objects.
Inject $resource into the factory it to create an object that can automatically handle REST calls.
app.factory('Posts',function($resource){
return $resource( ngWP.config.api + ‘/:post_type/:ID?per_page=:per_page’, {
post_type: 'posts',
ID:'@id',
per_page: ngWP.config.posts_per_page,
});
})
AngularJS Factories cont’d
Posts.get()
Posts.query() - like get, but expects array
Posts.save()
Posts.delete()
Posts.remove()
Unlike $http these do not return promises
Local Storage
https://github.com/grevory/angular-local-storage
An AngularJS module that gives you access to the browser’s local storage with
cookie fallback.
Local storage is a key/value store which we call on. In our example the regular posts (blog) will check for
local storage first, before hitting the API.
UI-Router
https://github.com/angular-ui/ui-router
The Angular-UI project adds modules and functionality to Angular (think WP plugins for WP)
State Driven Routing
& a lot of other functionality we won’t need.
Shows its true power when you have 1 view within another (post.detail within post.list)
Templates
Separating out templates into templates directory
Cleaner code
Separation of views
1 controller can have 1 template
1 template can be powered by multiple controllers
Pure HTML (with JSON)
CalderaLabs.org
Now Entering
The Danger Zone
First thing is first
Clone the repo
You will need to run npm install and gulp
The config file
Create a file called config.js in /assets/js
var ngWP = ngWP || {};
ngWP.config = {
api: 'https://calderaforms.com/wp-json/',
posts_per_page: 5
// Not needed for our menu: 'app'
};
Stepping through the code
Main APP file
UI Router Definitions
Small controllers live here
Templates
Blog/Author List
Blog Detail
Product List
CalderaLabs.org
5.
Plugin Admin Screens
With AngularJS
The UI Router
Making Mini-Apps To Make WordPress Better
Very Similar To
Regular NG App
Basic
Use add_admin_menu() to print basic HTML
Use ui-router to switch routes inside admin
page.
Use wp_localize_script() for config
Questions?
Use PHP or HTML files for templates?
How to handle translations?
wp_localize_script()
PHP templates
Let's Look At
Some Code!
What’s Next?
Angular 2 Theme currently in development
github.com/royboy789/Angular-Wordpress-Theme/tree/v7
Vue.JS - The new simple JS framework
ReactJS - What everyone else wants you to learn
Admin Theme Boilerplate
github.com/WordPress-Admin-JavaScript-Boilerplate/ReactJS-Boilerplate
Want more Roy & Josh teachings?
Caldera Learn teaches through 4-week live classroom
style webinars. Teachers are Josh and/or Roy with future
guest teachers
CalderaLabs.org
Josh Pollock
JoshPress.net
CalderaForms.com
CalderaLearn.com
CalderaLabs.org
@Josh412
CalderaLabs.org
Roy Sivan
theWPCrowd.com
RoySivan.com
Lynda.com
CaldraLearn.com
@royboy789
CalderaLabs.org
Want To Learn More?
Coming Very Soon
CalderaLearn.com

Mais conteúdo relacionado

Mais procurados

AngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro FrameworkAngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro FrameworkBackand Cohen
 
Bullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-FrameworkBullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-FrameworkVance Lucas
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
Slim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutSlim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutVic Metcalfe
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Eric Palakovich Carr
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Ryan Weaver
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress DevelopmentAdam Tomat
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
Zend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarZend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarRalph Schindler
 
REST in AngularJS
REST in AngularJSREST in AngularJS
REST in AngularJSa_sharif
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Arc & Codementor
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Working with WP_Query in WordPress
Working with WP_Query in WordPressWorking with WP_Query in WordPress
Working with WP_Query in WordPresstopher1kenobe
 

Mais procurados (20)

AngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro FrameworkAngularJS with Slim PHP Micro Framework
AngularJS with Slim PHP Micro Framework
 
Bullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-FrameworkBullet: The Functional PHP Micro-Framework
Bullet: The Functional PHP Micro-Framework
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Slim RedBeanPHP and Knockout
Slim RedBeanPHP and KnockoutSlim RedBeanPHP and Knockout
Slim RedBeanPHP and Knockout
 
Zend framework
Zend frameworkZend framework
Zend framework
 
Developing apps using Perl
Developing apps using PerlDeveloping apps using Perl
Developing apps using Perl
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Getting Started-with-Laravel
Getting Started-with-LaravelGetting Started-with-Laravel
Getting Started-with-Laravel
 
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
Finally, Professional Frontend Dev with ReactJS, WebPack & Symfony (Symfony C...
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
Zend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarZend Framework 1.8 Features Webinar
Zend Framework 1.8 Features Webinar
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
REST in AngularJS
REST in AngularJSREST in AngularJS
REST in AngularJS
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
Building Modern and Secure PHP Applications – Codementor Office Hours with Be...
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Working with WP_Query in WordPress
Working with WP_Query in WordPressWorking with WP_Query in WordPress
Working with WP_Query in WordPress
 

Semelhante a Caldera Learn - LoopConf WP API + Angular FTW Workshop

Using WordPress as your application stack
Using WordPress as your application stackUsing WordPress as your application stack
Using WordPress as your application stackPaul Bearne
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
Building WordPress Client Side Applications with WP and WP-API - #wcmia
Building WordPress Client Side Applications with WP and WP-API - #wcmiaBuilding WordPress Client Side Applications with WP and WP-API - #wcmia
Building WordPress Client Side Applications with WP and WP-API - #wcmiaRoy Sivan
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 
Ruby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails frameworkRuby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails frameworkPankaj Bhageria
 
How to build Client Side Applications with WordPress and WP-API | #wcmia
How to build Client Side Applications with WordPress and WP-API | #wcmiaHow to build Client Side Applications with WordPress and WP-API | #wcmia
How to build Client Side Applications with WordPress and WP-API | #wcmiaRoy Sivan
 
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...King Foo
 
Laravel development (Laravel History, Environment Setup & Laravel Installatio...
Laravel development (Laravel History, Environment Setup & Laravel Installatio...Laravel development (Laravel History, Environment Setup & Laravel Installatio...
Laravel development (Laravel History, Environment Setup & Laravel Installatio...Dilouar Hossain
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress DeveloperJoey Kudish
 
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...LEDC 2016
 
Migrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindMigrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindValentine Matsveiko
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkDaniel Spector
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
Into The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api'sInto The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api'sOrtus Solutions, Corp
 
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Mike Schinkel
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 

Semelhante a Caldera Learn - LoopConf WP API + Angular FTW Workshop (20)

Using WordPress as your application stack
Using WordPress as your application stackUsing WordPress as your application stack
Using WordPress as your application stack
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Building WordPress Client Side Applications with WP and WP-API - #wcmia
Building WordPress Client Side Applications with WP and WP-API - #wcmiaBuilding WordPress Client Side Applications with WP and WP-API - #wcmia
Building WordPress Client Side Applications with WP and WP-API - #wcmia
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
Ruby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails frameworkRuby conf 2011, Create your own rails framework
Ruby conf 2011, Create your own rails framework
 
How to build Client Side Applications with WordPress and WP-API | #wcmia
How to build Client Side Applications with WordPress and WP-API | #wcmiaHow to build Client Side Applications with WordPress and WP-API | #wcmia
How to build Client Side Applications with WordPress and WP-API | #wcmia
 
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
Building Web Services with Zend Framework (PHP Benelux meeting 20100713 Vliss...
 
Fatc
FatcFatc
Fatc
 
Laravel development (Laravel History, Environment Setup & Laravel Installatio...
Laravel development (Laravel History, Environment Setup & Laravel Installatio...Laravel development (Laravel History, Environment Setup & Laravel Installatio...
Laravel development (Laravel History, Environment Setup & Laravel Installatio...
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress Developer
 
Laravel tips-2019-04
Laravel tips-2019-04Laravel tips-2019-04
Laravel tips-2019-04
 
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
 
Migrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mindMigrate yourself. code -> module -> mind
Migrate yourself. code -> module -> mind
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Into The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api'sInto The Box | Alexa and ColdBox Api's
Into The Box | Alexa and ColdBox Api's
 
kRouter
kRouterkRouter
kRouter
 
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 

Último

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 

Último (20)

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 

Caldera Learn - LoopConf WP API + Angular FTW Workshop

  • 1. WORDPRESS REST API AND ANGULARJS FTW! Roy Sivan and Josh Pollock CalderaLearn.com
  • 2. CalderaLabs.org Join our Slack LoopConf Slack: #workshop-wpapi We will be posting links, taking questions, and communicating throughout the day via Slack
  • 3. CalderaLabs.org Hi I'm Josh Lead Developer: Caldera Labs I make WordPress plugins I teach about WordPress I wrote a book about the WordPress REST API I am a core contributor to WordPress I am a member of The WP Crowd
  • 4. CalderaLearn.com Hi, I'm Roy Senior Software Engineer: The Walt Disney Company I am a member of The WP Crowd I blog on roysivan.com I teach on Lynda.com & CalderaLearn People say Hi to me a lot
  • 5. What We're Covering Today REST API 101 Building Custom REST APIs Unit Testing Custom REST APIs LUNCH BREAK AngularJS (1.x) Basics Building Decoupled Front-ends Building Plugin Admin Screens
  • 6. Educational Philosophy All code is or is based on real world projects We will show different ways of doing the same thing. Please ask why it's different ◇ we may give you a good answer Stop us and ask questions
  • 7. Structure For Today foreach ( $sections as $section ) : Concepts / Lecture Example Code Walkthrough (you will be cloning locally) Hands-on DIY Group Walk Through Code Group endforeach;
  • 8. WARNING This workshop is to help you understand the basics and some advanced technologies. Nothing will be production ready code.
  • 9. What you need for today IDE or text editor (PHPStorm, Sublime, etc.) Local WP install (VVV, DesktopServer, etc.) npm PHPUnit (optional, included in VVV) Composer (optional) AngularJS Batarang Chrome Extension https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehid hipcmcojjgiloacoafjmpfk?hl=en
  • 11. CalderaLabs.org NO But you can build cool stuff with it.
  • 12. It’s all about the Data Data! Data! Data!
  • 13. “ CalderaLearn.com The API allows you to take WP data and put it in a bucket. What you do with that bucket is up to you. -- Morten Rand Hendriksen @mor10
  • 14. CalderaLabs.org What can we build with it? Facebooks? Myspaces?
  • 15. API Powered Stuff Things you can build that are powered by the API Phone apps Custom UI widgets on your site Why use feed of another site, when you can API Custom Dashboards in the admin Custom WP Dashboard (YAS!) User role based dashboard
  • 20. CalderaLabs.org Or We Can Make Our Own With The Same Tools
  • 21. How The REST API Works WP_REST_Server ??WP_REST_Request WP_REST_Response
  • 22. How The REST API Works WP_REST_Server Route Callback WP_REST_Request WP_REST_Response ERROR! ERROR!
  • 23. CalderaLabs.org Let's Talk About The Orange Box The Route Callback
  • 26. add_action( 'init', 'my_book_cpt' ); function my_book_cpt() { $labels = array(...); $args = array( ... 'rest_controller_class' => 'WP_REST_Posts_Controller', 'show_in_rest' => true, 'rest_base' => 'books-api', ); register_post_type( 'book', $args ); } Add REST API Support To Post Type Registration
  • 27. add_action( 'init', 'my_custom_post_type_rest_support', 25 ); function my_custom_post_type_rest_support() { global $wp_post_types; $post_type_name = 'book'; if( isset( $wp_post_types[ $post_type_name ] ) ) { $wp_post_types[$post_type_name]->show_in_rest = true; $wp_post_types[$post_type_name]->rest_base = $post_type_name; $wp_post_types[$post_type_name]->rest_controller_class = 'WP_REST_Posts_Controller'; } } Add REST API Support To An Existing Post Type
  • 29. CalderaLabs.org Custom Field Is Any Data Not just meta fields
  • 30. function slug_get_meta_field( $object, $field_name, $request ) { return get_post_meta( $object[ 'id' ], $field_name ); } function slug_update_meta( $value, $object, $field_name ) { if ( ! $value || ! is_string( $value ) ) { return; } return update_post_meta( $object->ID, $field_name, strip_tags( $value ) ); } Adding Custom Fields To A Response: Callbacks
  • 31. add_action( 'rest_api_init', 'slug_register_spaceship' ); function slug_register_spaceship() { register_api_field( 'post', 'starship', array( 'get_callback' => 'slug_get_meta_field', 'update_callback' => 'slug_update_meta_field', ) ); } Adding Custom Fields To A Response: Registration
  • 33. add_action( 'rest_api_init', function () { register_rest_route( 'myplugin/v1', '/author/(?P<id>d+)', array( 'methods' => 'GET', 'callback' => 'route_callback', ) ); } ); Registering A Route
  • 35. class my_simple_route { public function register_routes(){ $namespace = 'my-api/v1'; register_rest_route( $namespace, '/items', [ 'methods' => 'GET', 'callback' => [ $this, 'get_items' ], 'permissions_callback' => [ $this, 'get_items_permissions' ] ] ); ... } } Registering Route(s)
  • 36. class my_simple_route { public function register_routes(){ ... register_rest_route( $namespace, '/items/(?P<id>d+)', [ 'methods' => 'GET', 'callback' => [ $this, 'get_item' ], 'permissions_callback' => [ $this, 'get_item_permissions' ] ] ); } } Registering Route(s)
  • 38. register_rest_route( $this->namespace, '/items/(?P<id>d+)', [ ... 'args' => [ 'type' => [ 'required' => true, 'validate_callback' => [ $this, 'validate_type' ] ], 'number' => [ 'default' => 5, 'sanitize_callback' => 'absint' ] ] ] ); Registering Route(s) : Defining Fields
  • 39. Registering Route(s) : Field Sanitization Callback Use to ensure data is safe. Defined using a callable. Change data to a safe value. Return prepared value
  • 40. Registering Route(s) : Field Validation Callback Use to ensure data is correct. Defined using a callable. Used to reject invalid requests Return true or false
  • 41. Registering Route(s) : Field Validation Callback public function validate_type( $value ){ if( !in_array( $value, [ 'big', 'small', 'very-small' ] ) ){ return false; } return true; }
  • 43. Registering Route(s) : Permissions Callback Determine if user is authorized. Return true or false
  • 44. Registering Route(s) : Permissions Callback Example: Make require login. public function get_items_permissions(){ if( is_user_logged_in() ){ return true; } return false; }
  • 45. Registering Route(s) : Permissions Callback Example: Limit To Admins public function get_items_permissions(){ if( current_user_can( 'manage_options' ) ){ return true; } return false; }
  • 46. Registering Route(s) : Permissions Callback Example: Allow Always public function get_items_permissions(){ return true; }
  • 48. Registering Route(s) : Callback Do something with the request Gets an object of WP_REST_Request Should return WP_REST_Response or WP_Error
  • 49. WP_Rest_Response Represents current request Contains: ◇ Parameters ◇ Headers No need to access $_GET, $_POST, $_REQUEST Implements Arrayaccess $request->param( 'field_name' ); $request[ 'field_name' ];
  • 50. Registering Route(s) : Callback public function get_item( WP_REST_Request $request ){ $id = $request[ 'id' ]; $item = slug_crud_get( $id ); if( ! empty( $item ) && ! is_wp_error( $item ) ){ return rest_ensure_response( $item ); }elseif ( is_wp_error( $item ) ){ return $item; }else{ $response = new WP_REST_Response( 'No items found', 404 ); return $response; } }
  • 52. CalderaLabs.org rest_api_init Use To Load Code Only Needed In REST API Requests
  • 53. Registering Route(s) : Initializing add_action( 'rest_api_init', function(){ $route = new my_simple_route(); $route->register_routes(); });
  • 58. Unit Testing 101 Make Sure Things Return What They Should Return $this->assertEquals( 42, function_that_returns_42() ); $this->assertSame( '42', function_that_returns_42() ); $this->assertArrayHasKey( 'roy', array( 'roy' => 'hi' ) ); Google: "Pippin Williamson Unit Tests for WordPress Plugins"
  • 59. Install PHPUnit wget https://phar.phpunit.de/phpunit.phar chmod +x phpunit.phar mv phpunit.phar /usr/local/bin/phpunit wget https://phar.phpunit.de/phpunit.phar php phpunit.phar
  • 60. Install WP CLI curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/ phar/wp-cli.phar php wp-cli.phar --info chmod +x wp-cli.phar sudo mv wp-cli.phar /usr/local/bin/wp
  • 61. Initialize Unit Tests wp scaffold plugin-tests
  • 64. An Example public function test_get_items_author_query() { $this->factory->post->create( array( 'post_author' => 4 ) ); $this->factory->post->create( array( 'post_author' => 4 ) ); $this->factory->post->create( array( 'post_author' => 2 ); $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); $response = $this->server->dispatch( $request ); $this->assertEquals( 200, $response->get_status() ); $this->assertEquals( 3, count( $response->get_data() ) ); }
  • 65. An Example public function test_get_items_author_query() { $this->factory->post->create( array( 'post_author' => 4 ) ); $this->factory->post->create( array( 'post_author' => 4 ) ); $this->factory->post->create( array( 'post_author' => 2 ); $request = new WP_REST_Request( 'GET', '/wp/v2/posts' ); $request->set_param( 'author', 4 ); $response = $this->server->dispatch( $request ); $this->assertEquals( 200, $response->get_status() ); $this->assertEquals( 2, count( $response->get_data() ) ); }
  • 67. Unit Test Case For REST API Endpoints Create a reusable class that: Create Instance of WP_REST_Server Boot routes Make sure route is booted
  • 68. Test Case Outline class Test_API extends WP_UnitTestCase { /** @var WP_REST_Server*/ protected $server; protected $namespaced_route = 'caldera-forms/v1'; public function setUp() {} public function test_register_route() {} public function test_endpoints() {} }
  • 69. Test Case: Set Up protected $server; public function setUp() { parent::setUp(); /** @var WP_REST_Server $wp_rest_server */ global $wp_rest_server; $this->server = $wp_rest_server = new WP_REST_Server; do_action( 'rest_api_init' ); }
  • 70. Test Case: Test Route Is Registered public function test_register_route() { $routes = $this->server->get_routes(); $this->assertArrayHasKey( $this->namespaced_route, $routes ); }
  • 71. Test Case: Test Endpoints Exist public function test_endpoints() { $the_route = $this->namespaced_route; $routes = $this->server->get_routes(); foreach( $routes as $route => $route_config ) { if( 0 === strpos( $the_route, $route ) ) { $this->assertTrue( is_array( $route_config ) ); foreach( $route_config as $i => $endpoint ) { $this->assertArrayHasKey( 'callback', $endpoint ); $this->assertArrayHasKey( 0, $endpoint[ 'callback' ], get_class( $this ) ); $this->assertArrayHasKey( 1, $endpoint[ 'callback' ], get_class( $this ) ); $this->assertTrue( is_callable( array( $endpoint[ 'callback' ][0], $endpoint[ 'callbac ][1] ) ) ); } } }
  • 73. Test Your API Only!!! Test internal logic elsewhere Test control of that logic Test response format Trust core
  • 74. Example Route Test class Test_Hi extends Test_API { protected $namespace = '/hi-api/v1/names'; public function test_list() { $request = new WP_REST_Request( 'GET', $this->namespace ); $response = $this->server->dispatch( $request ); $this->assertEquals( 200, $response->get_status() ); $data = $response->get_data(); $this->assertArrayHasKey( 'name', $data[0] ); $this->assertEquals( 'shawn', $data[0][ 'name' ] ); $this->assertArrayHasKey( 'name', $data[1] ); $this->assertEquals( 'roy', $data[1][ 'name' ] ); } }
  • 75. Example Route Test class Test_Hi extends Test_API { protected $namespace = '/hi-api/v1/names'; public function test_single(){ $request = new WP_REST_Request( 'GET', $this->namespace . '/roy' ); $response = $this->server->dispatch( $request ); $this->assertEquals( 200, $response->get_status() ); $data = $response->get_data(); $this->assertArrayHasKey( 'name', $data ); $this->assertEquals( 'roy', $data[ 'name' ] ); } }
  • 76. CalderaLabs.org 3. Getting Started With AngularJS 1.x Controllers, Templates, Services & Factories
  • 77. CalderaLabs.org 3 con’t Why Angular? You know it’s in the title of the workshop, right?
  • 78. “ CalderaLearn.com AngularJS is the best JavaScript Framework. -- Roy Sivan Senior WordPress Engineer at Disney (so you know he is legit)
  • 79. Not WordPress To get you through the basics of AngularJS we will be using sample data, not WP Our First Project No npm or gulp We aren’t using any build tools, this is a pure sample https://github.com/caldera-learn/angularjs-intro
  • 80. Quicker & Easier Quicker to get going to show overall concepts. Honest Truth We already have a few projects built in it that are ready to go Why 1.x? 2 is in RC! Roy is lazy I am not lazy, but didn’t have time to learn it deeply enough yet to give a full workshop on it. Josh Switched Teams He used to be team NG1. Now he is team VueJS.
  • 81. HTML powered JavaScript With Angular 1.x you can use HTML to do most things reserved for PHP. Get the data using JS, template with HTML. No PHP needed.
  • 83. Setting up the app All functionality lives within 1 app We use ng-app to encapsulate the app in the DOM, it can be used on any element including HTML. Using it on the HTML encapsulates the whole DOM
  • 84. Sample Data JSON data.json This file is going to be a sample of data, that we are going to use to build out a simple Angular App, we will then replace it with the WordPress REST API
  • 85. Injectables Injectables are objects which can be injected and used in controllers, directives, etc. We will be creating our own later...
  • 86. AngularJS Controllers Controller is all about $scope A Controller is defined by a JavaScript constructor function that is used to augment the AngularJS Scope. When a Controller is attached to the DOM via the ng-controller directive, AngularJS will instantiate a new Controller object, using the specified Controller's constructor function All new data to be used must be stored within $scope.your_key ng-controller
  • 87. All Together - JS wpNG = {}; wpNG.app = ( function( app ){ console.log( 'initializing..' ); // define our app app = angular.module('wpAngularApp', []) .controller( 'listView', ['$scope', '$http', function( $scope, $http ) { … }]); return app; }(wpNG.app || {});
  • 88. All Together - HTML <div ng-app="wpAngularApp" id="app-container"> <div ng-controller="listView"> <!-- List View --> </div> </div>
  • 90. First we must get data $http is a jQuery AJAX wrapper & returns a promise $http({method: ‘’, url: ‘’}) $http.get(url) $http.post(url) Because it returns a promise we use .then()
  • 91. Say hello to JSON JSON is the JavaScript Object Notation. We display JSON with curly brackets We work with JSON similar to PHP arrays {{Object.key}} displays that key value In PHP that would be $object[‘key’];
  • 92. The loop HTML <div ng-controller="listView"> <h2>Posts</h2> <!-- Loop through $scope.posts --> <article ng-repeat="post in posts"> <h2>{{post.title}}</h2> </article> </div>
  • 93. Add more data <article ng-repeat="post in posts"> <img ng-src="{{post.image}}" /> <h2>{{post.title}}</h2> <div class="post-content" ng-bind-html="post.content | to_trusted"> </div> </article>
  • 95. Decoupled Front End Decouple front end is a front end app that doesn’t live within WordPress at all. Your website: myawesomesite.com Decoupled: myawesomeapp.com - but running on the same data! How cool is that!
  • 96. Decoupled Use Cases Phone App Piece of functionality that communicates with WP data Advanced, Unique UI Combine with other APIs Different Stack (decoupled app doesn’t need to be PHP)
  • 97. Our decoupled App npm gulp REST url that is publicly accessible (we will give you one) Tacos, you always need tacos. What you will need: https://github.com/caldera-learn/decoupled-app
  • 99. CORS Allows browsers to make requests across domains. IS NOT SECURITY!! By default WordPress REST API is same-origin only. Set at rest_pre_serve_request hook
  • 100. Allow All Domains For All Methods add_action( 'rest_api_init', function() { remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' ); add_filter( 'rest_pre_serve_request', function( $value ) { header( 'Access-Control-Allow-Origin: *' ); header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' ); header( 'Access-Control-Allow-Credentials: true' ); return $value; }); }, 15 );
  • 101. Only Allow GET Requests add_action( 'rest_api_init', function() { remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' ); add_filter( 'rest_pre_serve_request', function( $value ) { $origin = get_http_origin(); if ( $origin ) { header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) ); } header( 'Access-Control-Allow-Origin: ' . esc_url_raw( site_url() ) ); header( 'Access-Control-Allow-Methods: GET' ); return $value; }); }, 15 );
  • 102. Allows From Certain Origins add_action( 'rest_api_init', function() { remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' ); add_filter( 'rest_pre_serve_request', function( $value ) { $origin = get_http_origin(); if ( $origin && in_array( $origin, array( 'https://hiroy.club' ) ) ) { header( 'Access-Control-Allow-Origin: ' . esc_url_raw( $origin ) ); header( 'Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE' ); header( 'Access-Control-Allow-Credentials: true' ); } return $value; }); }, 15 );
  • 104. AngularJS Factories Factories allow you to create injectable objects. Inject $resource into the factory it to create an object that can automatically handle REST calls. app.factory('Posts',function($resource){ return $resource( ngWP.config.api + ‘/:post_type/:ID?per_page=:per_page’, { post_type: 'posts', ID:'@id', per_page: ngWP.config.posts_per_page, }); })
  • 105. AngularJS Factories cont’d Posts.get() Posts.query() - like get, but expects array Posts.save() Posts.delete() Posts.remove() Unlike $http these do not return promises
  • 106. Local Storage https://github.com/grevory/angular-local-storage An AngularJS module that gives you access to the browser’s local storage with cookie fallback. Local storage is a key/value store which we call on. In our example the regular posts (blog) will check for local storage first, before hitting the API.
  • 107. UI-Router https://github.com/angular-ui/ui-router The Angular-UI project adds modules and functionality to Angular (think WP plugins for WP) State Driven Routing & a lot of other functionality we won’t need. Shows its true power when you have 1 view within another (post.detail within post.list)
  • 108. Templates Separating out templates into templates directory Cleaner code Separation of views 1 controller can have 1 template 1 template can be powered by multiple controllers Pure HTML (with JSON)
  • 110. First thing is first Clone the repo You will need to run npm install and gulp
  • 111. The config file Create a file called config.js in /assets/js var ngWP = ngWP || {}; ngWP.config = { api: 'https://calderaforms.com/wp-json/', posts_per_page: 5 // Not needed for our menu: 'app' };
  • 112. Stepping through the code Main APP file UI Router Definitions Small controllers live here Templates Blog/Author List Blog Detail Product List
  • 113. CalderaLabs.org 5. Plugin Admin Screens With AngularJS The UI Router Making Mini-Apps To Make WordPress Better
  • 115. Basic Use add_admin_menu() to print basic HTML Use ui-router to switch routes inside admin page. Use wp_localize_script() for config
  • 116. Questions? Use PHP or HTML files for templates? How to handle translations? wp_localize_script() PHP templates
  • 118. What’s Next? Angular 2 Theme currently in development github.com/royboy789/Angular-Wordpress-Theme/tree/v7 Vue.JS - The new simple JS framework ReactJS - What everyone else wants you to learn Admin Theme Boilerplate github.com/WordPress-Admin-JavaScript-Boilerplate/ReactJS-Boilerplate
  • 119. Want more Roy & Josh teachings? Caldera Learn teaches through 4-week live classroom style webinars. Teachers are Josh and/or Roy with future guest teachers
  • 122. CalderaLabs.org Want To Learn More? Coming Very Soon CalderaLearn.com