{
  "name": "Alexandru Păvăloi",
  "nickname": "Păvă",
  "age": 25,
  "labPage": "iampava.com/tw",
  "slides": "slides.com/iampava/tw-2020",
  "e-mail": "pava@iampava.com"
}
{ about you }

πŸ‘¨β€πŸŽ“πŸ‘©β€πŸŽ“

πŸ”₯ TW πŸ”₯

Official Lab Page

Official Course Page

By the end of the course you:

πŸ”₯ will have acquired confidence to start basic Web projects on your own
πŸš€ will have worked on a personal project which showcases your skills 
🎈 will have worked with multiple colleagues and thus grow your team-work skills 
πŸ“ will have learned the fundamentals of the Web

You can expect of me to:

πŸ€”

I can expect of you to:

πŸ€”

⭐ Projects will be published soon on https://iampava.com/tw ➑ teams of 2 or 3

⭐ If you don't like any of them, feel free to submit one yourselves

⭐ Read more about the projects & evaluation here: https://profs.info.uaic.ro/~busaco/teach/courses/web/

⭐ Skipping classes is ok, doesn't matter for the final grade

VS Code
Firefox
glitch.com
codepen.io

Tools

πŸ”— devdrive.io

Every Friday I'll post in-advance exercises for the next lab!

One last stop...

OK, let's do this!

😎 An open platform

πŸ”¨ for building apps, games & awesomeness

πŸ”— Shareable with just a link

The Web

internet & the web

⭐ JavaScript

⭐ PhP

⭐ C#

...

usually a browser, but not always!

client ↔ server

built in pretty much any language we can think of

let's inspect the network traffic of a public website

HTML β–Ά

This

is

<img src="...">
<p> Lorem ipsum...</p>
Self-closing
Needs a closing tag!

Elements/tags

<img src="/bob.png">
<p>
  Hi!
  <img src="bob.png">
</p>
Elements can have attributes
Or contain other elements
<button data-speed="1" type="button">
  1x
</button>

... or custom attributes!

<!DOCTYPE html>
<html>
  <head>
    <!-- ... -->
  </head>

  <body>
    <!--  ...  -->
  </body>
</html>

structure of any html page

html best practices

⭐ Organizing  most web pages

<header>
<main>
<footer>
<aside>

⭐ If there's an <img>, let there be an alt

<img src="/images/avatar.png" 
	 alt="Bob's avatar" />

⭐ If it takes you to another page it's an anchor

<a href="/settings"> Settings </a>

⭐ If it does something when clicking it, it's a button

<button type="button">
  Save progress
</button>

⭐ Always put labels on inputs

<label>
  <span> Email or username*</span>
  <input type="text" name="emailOrUsername">
</label>

⭐ If there's an input, there should be a form

⭐ Aaaand, if there's a form ➑ add a submit input/button

<form>
  <label>
    <span> Email or username*</span>
    <input type="text" name="emailOrUsername">
  </label>
  <button type="submit"> Login </button>
</form>

⭐ Keep HTML as minimalist as possible! NO, REALLY!

Any other best practices you'd like to share? πŸ€”

most common tags*

⭐ Containers

header, main, footer, aside, section, div, ul, li

* personal stats

⭐ Text

h1, h2, h3, p, span, strong, pre, code

⭐ Media

img, picture, video, audio

⭐ Forms

form, label, input, select, textarea

⭐ Actions

a, button

Let's code!

#1

#2

#3

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

πŸ’” Β  css Β  πŸ’–

Week #2

Implement this reusable button library!

To be honest...

sometimes css is a pain in the a**

but it can also be 😍

First things first!


??? {
  
     border: 5px solid black;

     background: blue;
}
value
property
selector
@media screen and (max-width: 500px) {
  ??? {
     border: 5px solid black;
     background: blue;
  }
}

@media screen and (orientation: landscape) {
  ??? {
     background: red;
  }
}

Based on device

  • @media (prefers-color-scheme: dark) {
      body { background: black; }
    	
      h1, h2, h3 {
    	color: #fff;	  
      }
    }
@media (prefers-color-scheme: dark) {
  ??? { background: black; }
	
  ??, ??, ?? {
	color: #fff;	  
  }
}

everything is a box (rect)

units

⭐ percentage (%)

⭐ vh/vw

⭐ em

⭐ rem

⭐ px

Β 

Β 

...

Try to avoid fixel px dimensions whenever

My favorite ❀

Where do we put it?

#1 inline

<p style="font-weight: bold"> 
    A simple styled paragraph...
</p>

πŸ‘Ž Avoid this at all* times

* most

#2 same file

<html>
 <head>
   <style> 
    h1 {
        text-align: center;
    }
   </style>
 </head>
 <body>
   <h1> Smth </h1>   
 </body>
</html>

πŸ‘Ž Avoid this at all* times

* most

#3 External

<!--  index.html -->
<html>
 <head>
   <link rel="stylesheet" href="./style.css">
 </head>
 <body>
   <h1> Smth </h1>   
 </body>
</html>
/* style.css */
h1 {
  text-align: center;
}

πŸ‘ Do this at all* times

* most

Position

Where to "position" an element inside the our Website.

Static

Default position of all elements.

⭐ from Top to Bottom

⭐ from Left to Right

absolute

Position it based on some parent's/ancestor's position

The first one with a position other than static

{
  top: 1em;
  right: 10%;
  bottom: 20px;
  left: 2vh;
}

relative

Position it relative to it's default static position

#1 Slightly adjust it's position by a couple of units

#2 To absolute position children according to itself

Usecases

fixed

Position it based on the viewport or the first ancestor with a transform property.

Scroll to top button on blogs

Fixed side content, ads, etc

Usecases

{
  transform: scale(1.5); 
  /*   transform: rotate(10deg); */
  /*   transform: translateX(5em); */
  /*   ... */
}

Sticky

Default (static) position until the scroll reaches it. Then it sticks!

{ DEMO }

#1

#2

<main>
  <div></div>
  <section></section>
  <div></div>
</main>

#3

<main>
 <div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
 </div>
</main>

#4

<p>
 Text
 <span> Help info </span>
</p>

TEXT

Help info

show the tooltip only on hover

<br />

Selectors

Which HTML element/elements we want to style?

by tag

* {
  font-family: sans-serif;
}

h1,
h2,
h3 {
  text-align: center;
}

by class

<button type="button"> Log In </button>
<button type="button"> Register </button>
<button type="button"> Sign Out </button>
<button type="button" class="btn-round"> 
    Log In 
</button>
<button type="button" class="btn-round"> 
    Register 
</button>
<button type="button" class="btn-green"> 
  Sign Out 
</button>
.btn-round {
  border-radius: 50%;
}

.btn-success {
  color: #fff;
  background: green;
}

by id

<p id="hello"> 
    A simple styled paragraph...
</p>

<style>
    #hello {
        font-weight: bold;
    }
</style>

It's all about how specific you are!

<img 
    class="square-image round-image" 
    id="profile" src="user.jpg" 
    alt="user profile"/>

<style>
    img {
        border: 1px solid black;
    }
    
    .round-image {
        border-radius: 50%;
        border: 5px dotted red;
    }

    .square-image {
        border-radius: 0;
        border: 5px dashed green;
    }
    
    #profile {
        border: 2px solid blue;
}
</style>
1)#ID
2).Class
3) TagName
πŸ’₯ !important
  • <style>
    
    .red {
        color: red;
    }
    
    .blue {
        color: blue;
    }
    
    </style>
    
    <p class="red blue"> Bob </p>
    <p class="blue red"> Alice </p>
    
<style>

.red {
    color: red;
}

.blue {
    color: blue;
}

</style>

<p class="red blue"> Bob </p>
<p class="blue red"> Alice </p>

Hmmmmm...?!

Display

Determines weather it's block or inline + the inner layout of itself.

block

inline-block

inline

all the available width. Next element will come below

just the width it needs. Next element comes inline

just like inline-block, only that width/height have no effect

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

css Β  #2

Week #3

FLEX ❀

flex
items
Flex Container

Β most common props

.gallery {
  display: flex;
  flex-flow: row wrap; 
  /*  row no-wrap; column wrap; ... */
  
  justify-content: space-between;
  /*  space-evenly; center; ...  */
  
  align-items: center;
  /* space-between; space-evenly;... */
}

{ DEMO }

some more Selectors

parentΒ  rule

.raining .human {
  /* 
    "human" class elements
    inside "raining"-class  elements
  */
  
  display: hidden; 
  position: under-blanket;/
}

& rule

.valentines.in-love {
  /* 
    both "valentines" & "in-love" 
    classes
  */
  text-decoration: make-up;
}

> selector

main > .card {
  /*  
   * Elements with class 'card' which 
   * are a direct  child of a  
   * 'main' element 
   */
}

BEM: Block element modifier

BEM is naming pattern to keep our CSS clean and our minds sane! πŸ˜…

blocks

Elements that make sense on their own.

eg: image gallery, login form on home page...

<body>
    <div class="gallery">
      
    </div>
</body>

elements

They make sense only as part of a block.

eg: image in an image gallery, form group in a form, etc

<body>
    <div class="gallery">
      <img class="gallery__image" />
    </div>
</body>

modifiers

An element or a block might have a certain state, like success, error, etc

<body>
  <div class="gallery">
    <img class="gallery__image" />
    <img class="gallery__image gallery__image--seen" />
  </div>
</body>

πŸ‘‡ Let's finally style it πŸ‘‡

πŸ‘‡ and this πŸ‘‡

transforms

#logo {
    tranform: scale(1.1) rotate(35deg);
    transform-origin: center;
}

transitions

πŸ”΄

πŸ”΄

.5 sec
#logo {
  transition: transform .5s ease-in;
}

#logo:hover {
  transform: scale(1.1);
}
property
timing
function
duration

animations

πŸ”΄

πŸ”΄

A
A

πŸ”΄

A

πŸ”΄

A
#logo {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }

  50% {
    transform: rotate(180deg);
  }

  100% {
    transform: rotate(360deg)
  }
}
iteration count

THANKS πŸ™

PS: check DevDrive over the weekend for practice exercises

html & css recap

Week #4

to keep in mind

⭐ Valid HTML

⭐ use flex & variable dimensions when possible

⭐ responsive design

⭐ deploy it on Github pages (bonus)

practical recommendations

πŸ€” think of your app as a series of components, some of which could potentially be re'used

✏ sketch the general outline of the website on paper (mobile first)

πŸ“ give each "component" a unique class name so there are no collisions

todos Week #5

πŸ“ Scholarly HTML report

πŸ‘¨β€πŸ’» Responsive webΒ  interface regarding all pages of the app

B

about the essential project specs

M

about everything (also explain why you made certain choices)

πŸ‘ Continue working on the project...

πŸ‘ start small by implementing some reusable CSS components

- or -

THANKS πŸ™

PS: check the Website over the weekend for the timetable

Due to the COVID-19 situation all teaching activities will be moved online.

Week #6

back-end development

Download and install XAMPP if you've chosen PHP!

php basics

⭐ we can have PHP only files or mix them with HTML for inserting content into the page

<!DOCTYPE html>
<html lang="en">
<head>
    <title>PHP & HTML</title>
</head>
<body>
    <h1> Some header </h1>
    <?php 
        $today = date('d/m/Y');
        echo "<h2> Today is " . $today . "</h2>"; 
    ?>
</body>
</html>
index.php
all variables must start with $

concatenate strings with . operator

⭐ there are no type-declarations needed when we create new variables

<?php 

$name = 'Bob';
$age = 31;
$isMarried = false;

// ...

⭐ Arrays are actually key-value pairs & the keys don't necessarily have to be numbes, as we are used to

<?php 

$phones = ['Bob' => 0740000000];
echo sizeof($phones); // 1

$loteryNumbers = [11, 5, 3];
$loteryNumber['smth'] = 'smth else';

echo  sizeof($loteryNumbers); // 3

foreach($loteryNumbers as $element) {
  echo $element;
}

⭐ PHP has support for OOP style programming via Classes

<?php 

class Human {
	public function __construct($name, $age) {
    	$this -> name = $name;
        $this -> age = $age;
    }
    
    public function greet() {
    	echo 'Hello! I am ' . $this -> name . '. Nice to meet you!';
    }
}

class Programmer extends Human {
	public function __construct($name, $age, $preferedLanguage) {
        parent::__construct($name, $age);
        $this -> preferedLanguage = $preferedLanguage;
    }
    
    public function code() {
    	echo 'Nom nom, I am coding in ' . $this -> preferedLanguage;
    }
}

$fiiDeveloper = new Programmer('Bob', 31, 'PHP');

$fiiDeveloper -> greet();
echo '<br/>';
$fiiDeveloper -> code();
?>

reading data from forms

βœ… Add a action attribute to the form specifying the path the the PHP script handling the submit

βœ… Add a method attribute to the form configuring what HTTP Verb to use (usually GET or POST)

On the client

On the server

βœ… Use the global arrays $_GET or $_POST to read the submitted data

βœ… Add the name attribute to all inputs/textareas/selects so that the server can read their values

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Adding two numbers</title>
</head>
<body>
    <header>
        <h1> Math.php </h1>
    </header>
    <form action="./math.php" method="GET"> 
        <div>
            <label for="no1">Number #1 </label>
            <input name="no1" type="number" id="no1">
        </div>
        <div>
            <label for="no2">Number #2 </label>
            <input name="no2" type="number" id="no2">
        </div>
        <button type="submit" name="submit">Submit me! </button>
    </form>
    
</body>
</html>
index.html
<?php 
    if(isset($_GET['submit'])) {
        $no1 = $_GET['no1'];
        $no2 = $_GET['no2'];

        printResult($no1 + $no2);
    }

    function printResult($result) {
        echo '<p> The answer is <strong>'.$result.'</strong>.</p>';
    }
?>
math.php

PHP & JSON

JSON is one of the most popular data formats out there, used frequently on the Web to exchange data from client-server. - Working with JSON

<?php 
    $jsonAsText = file_get_contents("./gallery.json");
    $galleryArr = json_decode($jsonAsText);
    
    foreach($galleryArr as $image) {
    	echo '<div>
        	<img src="'. $image -> src. '">
            <p>'. $image -> description .'</p>
        </div>';
    }
?>
index.php
[{
    "src": "./images/barcelone.png",
    "description": "Sunset in Barcelone",
    "date": "22 June 2019"
}, {
    "src": "./images/madrid.png",
    "description": "Quiet street in Madrid",
    "date": "23 June 2019"
}]

gallery.json

πŸ“Ή YouTube PHP tutorial I recommend watching to deep dive into php:

Β 

https://www.youtube.com/watch?v=NihZYkNpslE

πŸ‘¨β€πŸ’» Then head over to DevDrive.io for the exercises

MVC pattern

Week #7

MVC is one of the most popular back-end patterns out there, and the one I recommend when building your project. πŸ”₯

Controller(s)

Model(s)

view(s)

πŸ‘¨β€πŸ­

⭐ this is where all the interaction with our database happens (storing & retrieving data)

⭐ consists of Classes/Objects/Functions  depending on your app 

⭐ is passed by the Controller to the View for Rendering

Model

⭐ what the User sees and interacts directly with

⭐ will render part of the model/models

⭐ should only contain very simple logic, like iterating through data and simple if-else

views

⭐ where the logic happens

⭐ it connects the Model with the appropriate View based on the URL

⭐ it also responds to form submit and decides what view to render next

controller

πŸ‘¨β€πŸ’» Then head over to DevDrive.io for the exercise

Sessions & Database

Week #8

πŸͺ cookies

&

πŸ’Ύ Sessions

cookies

Information about a user stored on it's computer (in the browser).

Β 

Primarily used to track us all over the internet... πŸ˜…

<?php
$preferredLang = 'RO';

setcookie("PreferredLanguage", $preferredLang, time() + 3600);
?>
<?php 

if($_COOKIE['PreferredLanguage'] === 'RO') {
	echo 'Salut';
} else {
	echo 'Hello';
}

Setting up a cookie that expires in 1 hour regarding the language preference

Reading the cookie later in a different page

Sessions

Similar to cookies but they store information about a user on the server.

How do they work? πŸ€”

βœ… A cookie having a unique ID - calleΒ  Session ID - is stored on the client (browser)

βœ… On the server there's some data attached to that ID

βœ… When the user goes back to the server, the cookie is read and thus the data attached to that ID is found and can be accessed

<?php    

/** 
	START - Persist session for 2 hours,  
    even after closing the browser.
    
    Needs to be called only once, 
    when starting the server.
*/
 
 $TWO_HOURS = 60 * 60 * 2;
 ini_set('session.cookie_lifetime', $TWO_HOURS);
 ini_set('session.gc_maxlifetime', $TWO_HOURS);
 
 session_start();

 if(isset($_SESSION['count'])) {
   $_SESSION['count'] ++;
 } else {
   $_SESSION['count'] = 1;
 }

 echo $_SESSION['count'];
?>
<?php 
  $CONFIG = [
    'servername' => "localhost",
    'username' => "root",
    'password' => '',
    'db' => 'test'
  ];

  $conn = new mysqli($CONFIG["servername"], $CONFIG["username"], $CONFIG["password"], $CONFIG["db"]);

  if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
  } else { 
    echo "Successfully connected to DB";
  }
?>

Sql + xampp = ❀

πŸ‘‡ Connecting to a MySQL database πŸ‘‡

We're using Prepared Statement to prevent this πŸ‘‡

query'ing the db

inserting data

<?php 
 $username = "Bob";
 $pass = "12345";

 $insertStatement = $conn -> prepare("INSERT INTO users VALUES(?, ?)");
 $insertStatement -> bind_param("ss", $username, $pass);

 $insertStatement -> execute();
 $insertStatement -> close();
?>
<?php 
  $getUsersStatement = $conn -> prepare("SELECT * FROM users WHERE username = ?");
  $getUsersStatement -> bind_param("s", $username);
  $getUsersStatement -> execute();

  $users = $getUsersStatement -> get_result();

  foreach($users as $row) {
      echo $row['username'];
      echo ' -- ';
      echo $row['password'];
      echo '<br/>';
  }
?>

retrieving data

πŸ“ Other resources:

πŸ‘¨β€πŸ’» Then head over to DevDrive.io for the exercise

DOM

Week #9

Document OBJECT MODEL

The DOM is a tree-like structure representing an XML document.

Β 

Most often though, you'll hear about it in the context of HTML but it applies to any XML document.

The DOM provides us with an API (functions) through which we'll interact with it. And since it's a standard, those functions are the same in any programming language.

<?php

$dom = new DOMDocument();

$p = $dom -> createElement('p');
$p -> textContent = 'I am a paragraph';

$img = $dom -> createElement('img');
$img -> setAttribute('src', 'https://www.info.uaic.ro/wp-content/uploads/2019/05/cropped-engl-100x600v2.png');
$img -> setAttribute('alt', 'UAIC logo');

$p -> appendChild($img);
$dom -> appendChild($p);

echo $dom -> saveXML();
PHP example of using DOM
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>DOM</title>
</head>

<body>
    <script>
        var p = document.createElement('p');
        p.textContent = 'I am a paragraph';

        var img = document.createElement('img');
        img.setAttribute('src', 'https://www.info.uaic.ro/wp-content/uploads/2019/05/cropped-engl-100x600v2.png');
        img.setAttribute('alt', 'UAIC logo');

        p.appendChild(img);
        document.body.appendChild(p);
    </script>
</body>

</html>
JS example of using DOM

😍See, the exact same functions!

πŸ‘¨β€πŸ’» head over to DevDrive.io for the exercise

Simple XML & SAX

Week #10

DOM is just one way of parsingΒ  an XML document. Let's look at two more: Simple XML & SAX

SIMPLE XML

SimpleXML allows us to easily read an XML document and than iterate through it like a normal PHP data-structure.

<?xml version="1.0" encoding="utf-8"?>
<travel-list>
    <country>
        <name>Portugal</name>
        <year>2022</year>
    </country>
</travel-list>

Let's say we have the following XML document regarding travel destinations

<?php

$travelList = simplexml_load_file('travel.xml');

for ($index = 0; $index < sizeof($travelList); $index++) {
    echo 
    	"<p> I want to travel to " . 
        $travelList->country[$index]->name . 
        " in " . $travelList->country[$index]->year . 
        "</p>";
}

πŸ‘‡ This is how we would parse it to show that info in an HTML page πŸ‘‡

However, since SimpleXML and DOM store the entire XML in memory, they cannot be used for huge XML files (GBs).

Enter SAX 😎

SAX

SAX is used to efficiently (from a memory perspective) parse huge XML docs.

It "iterates" through the XML and emits events whenever it stumbles upon a start tag, end tag, or content data.

Β 

We "hook" into those events to read the data.

In the example below I've created a custom ParserΒ  class to make things more readable.

<?php

$parser  = new Parser('travel.xml');
$parser->parseAndPrint();

class Parser
{
    private $xml_parser;
    private $index  = 0;
    private $filename;

    public function __construct($filename)
    {
        $this->filename = $filename;

        $this->xml_parser = xml_parser_create();
        xml_set_object($this->xml_parser, $this);
        xml_set_element_handler($this->xml_parser, "startElement", "endElement");
        xml_set_character_data_handler($this->xml_parser, "characterData");
    }

    public function parseAndPrint()
    {
        if (!($fp = fopen($this->filename, "r"))) {
            die("Could not open XML input");
        }

        while ($data = fread($fp, 4096)) {
            if (!xml_parse($this->xml_parser, $data, feof($fp))) {
                die(sprintf(
                    "XML error: %s at line %d",
                    xml_error_string(xml_get_error_code($this->xml_parser)),
                    xml_get_current_line_number($this->xml_parser)
                ));
            }
        }

        xml_parser_free($this->xml_parser);
    }

    private function startElement($parser, $name, $attrs)
    {

        switch ($name) {
            case 'COUNTRY':
                echo '<p> I want to travel ';
                break;
            case 'NAME':
                echo " to <strong>";
                break;
            case 'YEAR':
                echo " in <strong>";
                break;
            default:
                break;
        }
    }

    private function endElement($parser, $name)
    {
        switch ($name) {
            case 'COUNTRY':
                echo '</p>';
                break;
            case 'NAME':
            case 'YEAR':
                echo '</strong>';
                break;
            default:
                break;
        }
    }

    private function characterData($parser, $data)
    {

        $data = preg_replace("/^\s+/", "", $data);
        $data = preg_replace("/\s+$/", "", $data);

        if (!($data == "")) {
            echo $data;
        }
    }
}

⭐ startElement function: gets called whenever the parser detects a start of an XML element. Depending on the tag we print a different message

⭐ endElement function: gets called whenever the parser detects the end of an XML element. We're using to to close HTML tags.

⭐ characterData function: gets called whenever the parser detects content inside an XML element. We use it to print the actual country name & year.

πŸ‘¨β€πŸ’» head over to DevDrive.io for the exercise

soap web servics

Week #11

A Web service is a software system designed to support machine-to-machine interaction over a network.

Web Services are similar to real-life services.

Β 

For example: we have Food Delivery Services so that we don't have to drive to the store. Similarly, OpenWeatherMap offers weather information, or AWS S3 offers a Storage Service.

😍 What I love about Web Services is that you can combine them and create brand new products.

These types of products are called "mash-ups".

⭐ Maps Service

⭐ Weather Service

}

show realtime weather information on the Map so you can plan your trip

When creating a Web Service it is recommended to follow a set of patterns & best practices.

Β 

Thus, in the following slides we're gonna be talking about 2 approaches: SOAP and REST.

SOAP (Simple Object access protocol)

⭐it can be adapted to any communication protocol, not just HTTP

⭐the functionality provided by the Service (including data types) is described in WSDL

<?xml version="1.0"?> 
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
    <soap:Header> </soap:Header> 
    <soap:Body> 
        <m:GetStockPrice xmlns:m="http://www.example.org/stock/Surya"> 
        <m:StockName>IBM</m:StockName> 
        </m:GetStockPrice> 
    </soap:Body> 
</soap:Envelope> 

⭐transfered information (for both request and response) must be in XML format and should respect a standard format of Envelope, Headers and Body

PHP already has two utility classes SoapServer and SoapClient for easily building and talking to SOAP Services.

Here's a demo of using them to build a dummy Game of Thrones Service (no spoilers πŸ˜…)

<?php

$client = new SoapClient(NULL, [
    "location" => "http://localhost:1234/soap-live/got-service.php",
    "uri" => "http://got-soap-service.com"
]);

// var_dump($client -> __getFunctions());
// var_dump($client -> __getTypes());

echo $client -> getEpisodesCount() . "<br/>";
echo $client -> getSynopsis(62) . "<br/>";
Client
<?php

$service = new SoapServer(NULL, [
    "uri" => "http://got-soap-service.com"
]);


class Episode {
    public function __construct($name)
    {
        $this -> episodName = $name;
    }
}

class GotService
{
    public function getSynopsis($args)
    {

        if ($args['seasonNo'] === 6 && $args['episodeNo'] === 3) {
            return new Episode("Battle of the bastards: fight between good and evil!");
        }

        return "Episode not found!";
    }

    public function getEpisodesCount()
    {
        return 73;
    }
}

$service->setObject(new GotService());
$service->handle();
Server

We haven't used Headers yet so let's modify our example by adding authentication

⭐the Client will need to send a header named CustomAuthHeader with two propertis: username & pass

⭐the Server will read this header and only allow access to the getSynopsis function if the credentials match

<?php

$client = new SoapClient(NULL, [
    "location" => "http://localhost:1234/soap-live/got-service.php",
    "uri" => "http://got-soap-service.com"
]);

// var_dump($client -> __getFunctions());
// var_dump($client -> __getTypes());

class CustomAuthHeader
{
    public $username;
    public $pass;
    
    public function __construct()
    {
        $this->username = "bob";
        $this->pass = "1234";
    }
}

$header = new SoapHeader(
    "http://got-soap-service.header.com",
    "CustomAuthHeader",
    new CustomAuthHeader()
);

echo $client->__soapCall("getSynopsis", [
    [
        "seasonNo" => 6, 
        "episodeNo" => 3
    ]
], NULL, [$header]) -> episodName;
Client
<?php

$service = new SoapServer(NULL, [
    "uri" => "http://got-soap-service.com"
]);

class Episode {
    public function __construct($name)
    {
        $this -> episodName = $name;
    }
}

class GotService
{
    private $isAuthenticated = false;

    public function CustomAuthHeader($header)
    {
        if (
            $header->username === "bob" &&
            $header->pass === "1234"
        ) {
            $this->isAuthenticated = true;
        }
    }

    public function getSynopsis($args)
    {
        if (!$this->isAuthenticated) {
            throw new Error("Must be authenticated!");
        }

        if ($args['seasonNo'] === 6 && $args['episodeNo'] === 3) {
            return new Episode("Battle of the bastards: fight between good and evil!");
            // return "Battle of the bastards: fight between good and evil!";
        }

        return "Episode not found!";
    }

    public function getEpisodesCount()
    {
        return 73;
    }
}

$service->setObject(new GotService());
$service->handle();
Server

πŸ‘¨β€πŸ’» head over to DevDrive.io for the exercise