سرفصل‌های آموزشی
آموزش RESTful API
افزودن قابلیت CRUD برای پروژهٔ تِستِر RESTful API

افزودن قابلیت CRUD برای پروژهٔ تِستِر RESTful API

در این آموزش قصد داریم تا قابلیت CRUD یا به عبارتی افزودن فیچرهایی از جمله «نمایش یک مقاله»، «افزودن یک مقالهٔ جدید»، «ویرایش یک مقاله» و «حذف یک مقاله» را مورد بررسی قرار دهیم.

    به خاطر داشته باشید
سرواژهٔ CRUD برگرفته از کلمات Update ،Read ،Create و Delete است.

به منظور نمایش محتوای یک مقاله،‌ فولدری می‌سازیم تحت عنوان show و داخل آن دو فایل تحت عناوین curl.php و index.php می‌سازیم به طوری که فایل curl.php می‌باید حاوی کدهای زیر باشد:

<?php
$articleId = $_GET['id'];
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/articles/' . $articleId);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['content-type: application/json']);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
    echo $err;
} else {
    $response = json_decode($result, true);
}

در تفسیر کدهای فوق می‌توان گفت که ابتدا متغیری ساخته‌ایم تحت عنوان articleId$ که مقدارش برابر با پارامتر id است که در فایل index.php که در آموزش گذشته تکمیل نمودیم تنظیم شده است به طوری که داریم:

<a href="show/index.php?id=<?= $article['articleId'] ?>">
    <?= $article['articleTitle'] ?>
</a>

الباقی تنظیمات کِرل همچون آموزش گذشته است با این توضیح که CURLOPT_URL حاوی مقداری به صورت زیر است:

curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/articles/' . $articleId);

همان‌طور که می‌بینیم، اِندپوینت مربوطه را نوشته سپس متغیر articleId$ را اصطلاحاً به آن کانکت کرده‌ایم. حال نوبت به تکمیل فایل index.php می‌رسد که داخل پوشهٔ show قرار دارد به طوری که خواهیم داشت:

<!DOCTYPE html>
<html>
    <head>
        <title>Show Article</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Show Article</h1>
        <?php require_once('curl.php'); ?>
        <?php if ($response['response']) { ?>
            <div>
                <strong><?= $response['response']['message'][0]['articleTitle'] ?></strong>
            </div>
            <div>
                <?= $response['response']['message'][0]['articleBody'] ?>
            </div>
            <div>
                Category Name: <?= $response['response']['message'][0]['catName'] ?>
            </div>
            <div>
                Written By: <?= $response['response']['message'][0]['authorFirstName'] . ' ' . $response['response']['message'][0]['authorLastName'] . ' in ' . $response['response']['message'][0]['time'] ?>
            </div>
            <a href="../update/index.php?id=<?= $response['response']['message'][0]['articleId'] ?>">Update this article</a>
            <br>
            <a href="../delete/curl.php?id=<?= $response['response']['message'][0]['articleId'] ?>" onclick="return confirm('Are you sure you want to delete this article?');">Delete this article</a>
        <?php } ?>
    </body>
</html>

با توجه به اینکه برای نمایش دیتا نیاز به اجرای فایل curl.php داریم، می‌بینیم که در خط نهم و با استفاده از دستور ()require_once این فایل را به فایل موجود ایمپورت کرده‌ایم و سپس با استفاده از یک دستور شرطی سنجیده‌ایم ببینیم که آیا آرایهٔ ['response['response$ سِت شده است یا خیر که اگر این گونه بود، محتوای این آرایه را چاپ کرد‌ایم.

در انتهای این صفحه، لینکی به منظور آپدیت این مقاله درج کرده‌ایم با این توضیح که به عنوان مقدار اتریبیوت href از علامت /.. استفاده کرده‌ایم سپس وارد پوشهٔ update شده و فایل index.php را فراخوانی کرده‌ایم؛ در حقیقت، علت درج /.. آن است که برای دستیابی به پوشهٔ update ابتدا می‌باید از پوشهٔ show خارج شویم و علامت /.. همین کار را انجام خواهد داد. در نهایت هم پارامتری تحت عنوان id در نظر گرفته و مقدار آن را برابر با کلید articleId قرار داده‌ایم.

در ادامه، دکمهٔ دیگری به منظور حذف مقاله ایجاد کرده‌ایم که ساختارش شباهت بسیاری به دکمهٔ ویرایش مقاله دارد با این تفاوت که به فولدر delete ارجاع داده می‌شود مضاف بر اینکه برای جلوگیری از حذف سهوی یک مقاله، اتریبویت onclick را با استفاده از جاوااسکریپت نوشته و به عنوان مقدار آن دستور ()confirm را ریترن کرده‌ایم و به عنوان آرگومان این تابع نیز استرینگی با مضمون «آیا از حذف این مقاله اطمینان دارید؟» در نظر گرفته‌ایم به طوری که از این پس با کلیک برای روی دکمهٔ حذف، یک پاپ‌آپ جاوااسکریپتی در معرض دید کاربر قرار می‌گیرد که با کلیک بر روی دکمهٔ OK، پروسهٔ حذف تکمیل خواهد شد.

لازم به یادآوری است که به منظور انجام عملیاتی همچون درج یک مقالهٔ جدید، به‌روزرسانی یا حذف مقالات، نیاز است تا کاربر در این وب سرویس لاگین باشد که در همین راستا، ابتدا به تکمیل پوشه‌های signin و signup پرداخته سپس پوشه‌های update ،create و delete را تکمیل خواهیم نمود.

به منظور افزودن قابلیت ثبت‌نام به این وب اپلیکیشن، فولدری تحت عنوان signup ساخته و فایلی به نام curl.php حاوی کدهای زیر داخل آن می‌سازیم:

<?php
$mail = $_POST['mail'];
$firstName = $_POST['firstName'];
$lastName = $_POST['lastName'];
$pass = $_POST['pass'];
$request = '{
    "request_params": {
        "firstName": "' . $firstName . '",
        "lastName": "' . $lastName . '",
        "mail": "' . $mail . '",
        "pass": "' . $pass . '"
    }
}';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/signup');
curl_setopt($curl, CURLOPT_HTTPHEADER, ['content-type: application/json']);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
    echo $err;
} else {
    $response = json_decode($result, true);
    if ($response['error']) {
        echo $response['error']['message'];
        echo "<br>";
        echo '<a href="index.php">Back</a>';
    } else if ($response['response']['code'] == '406 Not Acceptable') {
        echo $response['response']['message'];
        echo "<br>";
        echo '<a href="index.php">Back</a>';
    } else if ($response['response']) {
        echo $response['response']['message'];
        echo "<br>";
        echo "<a href='../signin'>Sign in</a>";
    }
}

با استفاده از POST_$ که یک به اصطلاح Superglobal است، مقادیر فیلدهای firstName ،pass ،mail و lastName را در متغیرهایی تحت همین عناوین ذخیره کرده‌ایم سپس متغیری ساخته‌ایم به نام request$ که حاوی یک استرینگ طبق همان ساختاری است که ای‌پی‌آی آن را به رسمیت می‌شناسد و متغیرهای فوق‌الذکر را داخل آن گنجانده‌ایم.

اِندپوینت انتخابی در این فایل api/v1/signup است به طوری که با کنترلر UserController و اَکشن signup در پروژهٔ RESTful API به اصطلاح مَپ خواهد شد. الباقی دستورات کِرل مشابه مثال‌های پیشین است با این تفاوت که دو آپشن جدید به صورت زیر نیز اضافه نموده‌ایم:

curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);

لایبرری cURL به صورت پیش‌فرض متد GET را ساپورت می‌کند اما با افزودن آپشن CURLOPT_CUSTOMREQUEST و در نظر گرفتن مقداری همچون POST، می‌توان نوع متد ارسالی را تغییر داد. همچنین آپشن CURLOPT_POSTFIELDS این امکان را در اختیارمان قرار می‌دهد تا بتوانیم پارامترهای مد نظر خود را در بخش Body ریکوئست بگنجانیم و همان‌طور که می‌بینیم، متغیر request$ که پیش از این ساختیم را به عنوان مقدار این آپشن درج نموده‌ایم.

چنانچه ریکوئست ارسالی با اروری مواجه شود وارد بلوک if خواهیم شد و در غیر این صورت وارد else شده و یکسری دستور شرطی دیگر در نظر گرفته‌ایم که بسته به نوع ریسپانس، تَسک خاصی انجام خواهد شد. به طور مثال، در آخرین دستور شرطی گفته‌ایم که اگر مقدار کلید code در آرایهٔ response$ برابر با 201 Created بود، پیام «.New user added» در معرض دید کاربر قرار گیرد. حال نوبت به تکمیل فایل index.php قرارگرفته داخل پوشهٔ signup می‌رسد به طوری که داریم:

<?php 
    if (isset($_COOKIE['token'])) {
        header('Location: ../');
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Sign up</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Sign up</h1>
        <form action="curl.php" method="POST">
            First Name:
            <br>
            <input type="text" name="firstName" required>
            <br>
            Last Name:
            <br>
            <input type="text" name="lastName" required>
            <br>
            Email:
            <br>
            <input type="text" name="mail" required>
            <br>
            Password:
            <br>
            <input type="password" name="pass">
            <br>
            <input type="submit" value="Sign up">
        </form>
        <div>
            If you have an account, <a href="../signin">Sign in</a>
        </div>
    </body>
</html>

همان‌طور که می‌بینیم، ابتدا به ساکن با استفاده از یک دستور شرطی چک کرده‌ایم ببینیم که آیا کوکی‌ای به نام token سِت شده است یا خیر که اگر این گونه بود، با استفاده از تابع ()header کاربر را به هوم‌پیج این وب اپلیکشن ری‌دایرکت می‌کنیم. در حال حاضر این کوکی ساخته نشده است و چنین قابلیتی پس از لاگین کردن کاربر افزوده خواهد شد و هدف از قرار دادن این دستور شرطی آن است که اگر کوکی سِت شده بود، یا به عبارتی کاربر لاگین بود، امکان دسترسی به صفحهٔ ثبت‌نام از وی گرفته شود. در ادامه، یک فرم سادهٔ اچ‌تی‌ام‌ال ساخته‌ایم که حاوی همان فیلدهایی است که در فایل curl.php مقادیر آن‌‌ها را با استفاده از POST_$ دریافت نمودیم.

در این مرحله از کار،‌ قابلیت ثبت‌نام در این وب سرویس تکمیل شده است و حال نیاز به افزودن قابلیت لاگین به سیستم را داریم که برای همین منظور، پوشه‌ای تحت عنوان signin ساخته و داخلش فایلی به نام curl.php حاوی کدهای زیر می‌سازیم:

<?php
$mail = $_POST['mail'];
$pass = $_POST['pass'];
$request = '{
    "request_params": {
        "mail": "' . $mail . '",
        "pass": "' . $pass . '"
    }
}';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/auth');
curl_setopt($curl, CURLOPT_HTTPHEADER, ['content-type: application/json']);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
    echo $err;
} else {
    $response = json_decode($result, true);
    if ($response['error']) {
        echo $response['error']['message'];
        echo "<br>";
        echo '<a href="index.php">Back</a>';
    } else if ($response['response']['code'] == "401 Unauthorized") {
        echo $response['response']['message'];
        echo "<br>";
        echo '<a href="index.php">Back</a>';
    } else if ($response['response']['code'] == "200 OK") {
        echo "You`re successfully logged in.";
        echo "<br>";
        echo '<a href="../">Articles List</a>';
        setcookie('token', $response['response']['message']['token'], time() + (60 * 60), "/");
    }
}

آنچه حائز اهمیت است اینکه اِندپوینت این فایل برابر با api/v1/auth می‌باشد به طوری که پس از رفتن به این لینک، RESTful API با کنترلر UserController و اَکشن ()auth مَپ خواهد شد.

نکته‌ای که در اینجا نیاز به توضیح دارد آن است که پس از لاگین کردن در این وب سرویس، یک توکن در اختیارمان قرار می‌گیرد که در ریکوئست‌های بعدی می‌توان آن در بخش هِدِر برای سرور ارسال نمود تا احراز هویت شویم. حال پرسش اینجا است که «توکن دریافتی را برای استفاده در ریکوئست‌های بعدی به چه شکل می‌توان ذخیره ساخت؟» که در پاسخ به این سؤال می‌توان گفت که راه‌های متفاوتی برای این منظور وجود دارد که یک از آن‌ها ذخیره در Cookie است.

در همین راستا، در خط سی‌وپنجم از این فایل با استفاده از دستور ()setcookie پس از لاگین موفقیت‌آمیز کاربر در وب سرویس با استفاده از ایمیل و پسورد، یک کوکی سِت کرده‌ایم با این توضیح که آرگومان اول تابع ()setcookie استرینگی دلخواه همچون token است، پارامتر دوم نیز همان توکنی است که در پروسهٔ لاگین کردن توسط وب سرویس ریترن می‌شود، پارامتر سوم تاریخ انقضای این کوکی است به طوری که گفته‌ایم زمان فعلی سرور گرفته شده + یک ساعت شود (به عبارتی اعتبار این کوکی فقط یک ساعت است.) و در نهایت به عنوان آرگومان چهارم از علامت "/" استفاده کرده‌ایم که بدین معنا است که این کوکی در کل فایل‌های این وب اپلیکیشن در دسترس خواهد بود. اکنون می‌توان اقدام به تکمیل کدهای فایل index.php قرارگرفته داخل پوشهٔ signin کرد به طوری که خواهیم داشت:

<?php 
    if (isset($_COOKIE['token'])) {
        header('Location: ../');
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Sign in</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Sign in</h1>
        <form action="curl.php" method="POST">
            Email:
            <br>
            <input type="text" name="mail" required>
            <br>
            Password:
            <br>
            <input type="password" name="pass">
            <br>
            <input type="submit" value="Sign in">
        </form>
        <div>
            If you don`t have any account, <a href="../signup">Sign up</a>
        </div>
    </body>
</html>

همچون روال قبل، با استفاده از یک دستور شرطی گفته‌ایم که اگر کوکیِ token سِت شده بود، کاربر به صفحهٔ هوم‌پیج سایت ری‌دایرکت گردد و در ادامه هم یک فرم ساخته‌ایم حاوی دو فیلد mail و pass که کاربر می‌باید دیتای صحیحی وارد آن‌ها نماید تا بتواند در سیستم لاگین کند.

پیش از این گفتیم که به منظور ایجاد یک مقالهٔ جدید و یا به‌روزرسانی/حذف یک مقاله،‌ نیاز است تا در سیستم لاگین باشیم که تا این مرحله از آموزش چنین فیچری افزوده شده و حال می‌توانیم به تکمیل قابلیت افزودن مقالات کنیم که برای این منظور، پوشه‌ای تحت عنوان create ساخته و فایل curl.php آن را به صورت زیر تکمیل می‌کنیم:

<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $catId = $_POST['catId'];
    $articleTitle = $_POST['articleTitle'];
    $articleBody = $_POST['articleBody'];
    $token = $_COOKIE['token'];
    $request = '{
        "request_params": {
            "articleTitle": "' . $articleTitle . '",
            "articleContent": "' . $articleBody . '",
            "catId": "' . $catId . '"
        }
    }';
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/articles');
    curl_setopt($curl, CURLOPT_HTTPHEADER, [
        "content-type: application/json",
        "Authorization: Bearer $token",
    ]);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
    $result = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);
    if ($err) {
        echo $err;
    } else {
        if ($result == "Expired token") {
            echo "The token is expired and you need to resignin";
            echo "<br>";
            echo "<a href='../signin'>Sign in</a>";
        } else {
            $response = json_decode($result, true);
            if ($response['response']['code'] == '201 Created') {
                echo $response['response']['message'];
                echo "<br>";
                echo '<a href="../">Show all articles</a>';
            }
        }
    }
} 

نیاز به توضیح نیست که سوپرگلوبال ['SERVER['REQUEST_METHOD$ حاوی متد ارسالی اچ‌تی‌تی‌پی است و گفته‌ایم چنانچه این متد برابر با POST بود، عملیات مد نظر عملی گردد و در غیر این صورت هیچ تَسکی اجرا نگردد.

طبق روال گذشته، فیلدهای فرمی که داخل فایل index.php خواهیم ساخت را با استفاده از آرایهٔ POST_$ گرفته و در متغیرهایی هم‌نام ذخیره‌ کرده‌ایم مضاف بر اینکه متغیر جدیدی ساخته‌ایم به نام token$ و مقدار آن را برابر با ['COOKIE['token_$ قرار داده‌ایم؛ به عبارتی، کوکی‌ای که قبلاً سِت کرده‌ بودیم را بدین طریق به دست خواهیم آورد.

    نکته

همچنین جهت اطمینان بیشتر، در این طور مواقع می‌توان با استفاده از فانکشن ()isset چک کرد دید که آیا ['COOKIE['token_$ سِت شده است یا خیر. 

آنچه در این فایل به نسبتِ سایر دستورات کِرل تفاوت دارد این است که علاوه بر مشخص‌سازی نوع محتوا در آپشنِ CURLOPT_HTTPHEADER، از هِدِر دیگری تحت عنوان Authorization استفاده کرده و به عنوان مقدارش نیز واژهٔ Bearer را نوشته و پس از یک اِسپیس متغیر token$ را درج نموده‌ایم و همچنین در نهایت گفته‌ایم که اگر مقدار کلید code برابر با 201 Created بود، پیام «.New article added» در معرض دید کاربر قرار گیرد. حال نوبت به تکمیل فایل index.php درون پوشهٔ create می‌رسد به طوری که خواهیم داشت:
<?php 
    if (!isset($_COOKIE['token'])) {
        header('Location: ../signin');
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Create a new article</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Create a new article</h1>
        <?php require_once('curl.php'); ?>
        <form action="curl.php" method="POST">
            Article Category:
            <br>
            <select name="catId">
                <option value="1">Linux</option>
                <option value="2">PHP</option>
            </select>
            <br>
            Article Title:
            <br>
            <input type="text" name="articleTitle">
            <br>
            Article Content:
            <br>
            <textarea name="articleBody"></textarea>
            <br>
            <input type="submit" value="Create">
        </form>
    </body>
</html>

ابتدا گفته‌ایم که اگر کاربر لاگین نبود، به پوشهٔ signin ری‌دایرکت شود تا بتواند در سیستم لاگین کرده و اقدام به درج یک مقالهٔ جدید کند و الباقی کدها نیز همچون فایل‌های پیشین هستند.

در این مرحله،‌ قصد داریم تا قابلیت آپدیت یک مقاله را به این وب اپلیکیشن بیفزاییم که برای این منظور، پوشه‌ای تحت عنوان update ساخته و فایل curl.php قرارگرفته داخل آن را به صورت زیر تکمیل می‌کنیم:

<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $articleId = $_POST['id'];
    $articleTitle = $_POST['articleTitle'];
    $articleBody = $_POST['articleBody'];
    $token = $_COOKIE['token'];
    $request = '{
        "request_params": {
            "articleTitle": "' . $articleTitle . '",
            "articleContent": "' . $articleBody . '",
            "catId": "2"
        }
    }';
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/articles/' . $articleId);
    curl_setopt($curl, CURLOPT_HTTPHEADER, [
        "content-type: application/json",
        "Authorization: Bearer $token",
    ]);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
    curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
    $result = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);
    if ($err) {
        echo $err;
    } else {
        if ($result == "Expired token") {
            echo "The token is expired and you need to resignin";
            echo "<br>";
            echo "<a href='../signin'>Sign in</a>";
        } else {
            $response = json_decode($result, true);
            if ($response['response']['code'] == '200 OK') {
                echo $response['response']['message'];
                echo "<br>";
                echo "<a href=\"../show/index.php?id=$articleId\">Show the article</a>";
            }
        }
    }
} else {
    $articleId = $_GET['id'];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/articles/' . $articleId);
    curl_setopt($curl, CURLOPT_HTTPHEADER, ['content-type: application/json']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $result = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);
    if ($err) {
        echo $err;
    } else {
        $response = json_decode($result, true);
    }
}

ابتدا به ساکن با استفاده از یک دستور شرطی چک کرده‌ایم ببینیم که آیا متد ارسالی برابر با POST است یا خیر که اگر این گونه بود، وارد بلوک if خواهیم شد و در غیر این صورت وارد بلوک else می‌شویم. به بیانی دیگر، چنانچه کاربر فرمی که داخل فایل index.php است که در ادامه خواهیم ساخت را سابمیت کند، از آنجا که متد فرم POST است، فلذا وارد بلوک if خواهیم شد اما اگر هیچ گونه سابمیتی صورت نگیرد وارد بلوک else می‌شویم که این وظیفه را دارا است تا به ای‌پی‌آی یک ریکوئست ارسال کرده تا دیتای فعلی مقاله را به دست آورد.

چیزی که در ارتباط با این فایل حائز اهمیت است اینکه متد PUT را برای آپشن CURLOPT_CUSTOMREQUEST در نظر گرفته‌ایم چرا که این متد برای آپدیت یک ریسورس در معماری REST به کار می‌رود. همچنن گفته‌ایم چنانچه مقدار کلید code در ریسپانس برابر با 200 OK بود، پیام «.The article updated» در معرض دید کاربر قرار گیرد. در ادامه، فایل index.php این پوشه نیز حاوی کدهای زیر خواهد بود:

<?php 
    if (!isset($_COOKIE['token'])) {
        header('Location: ../signin');
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Update Article</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>Update Article</h1>
        <?php require_once('curl.php'); ?>
        <?php if ($response['response']) { ?>
            <form action="curl.php" method="POST">
                Article Title:
                <br>
                <input type="text" name="articleTitle" value="<?= $response['response']['message'][0]['articleTitle'] ?>">
                <br>
                Article Content:
                <br>
                <textarea name="articleBody"><?= $response['response']['message'][0]['articleBody'] ?></textarea>
                <br>
                <input type="hidden" name="id" value="<?= $response['response']['message'][0]['articleId'] ?>">
                <input type="submit" value="Update">
            </form>
        <?php } ?>
    </body>
</html>

با توجه به اینکه می‌باید محتوای قبلی مقاله را داخل فرم آپدیت درج نماییم، می‌بینیم که برای فیلد‌های فرم از اتریبیوت value استفاده کرده و مقدار آن‌ها را با کلیدهای مربوطه پُر نموده‌ایم.

حال نوبت به افزودن آخرین فیچر این وب اپلیکیشن می‌رسد که قابلیت حذف یک مقاله است. برای این منظور، پوشه‌ای تحت عنوان delete ساخته و فایل curl.php آن را به صورت زیر تکمیل می‌کنیم:

<?php
$articleId = $_GET['id'];
$token = $_COOKIE['token'];

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://rest-api-blog.local/api/v1/articles/' . $articleId);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    "content-type: application/json",
    "Authorization: Bearer $token",
]);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
    echo $err;
} else {
    if ($result == "Expired token") {
        echo "The token is expired and you need to resignin";
        echo "<br>";
        echo "<a href='../signin'>Sign in</a>";
    } else {
        $response = json_decode($result, true);
        if ($response['response']['code'] == '200 OK') {
            echo $response['response']['message'];
            echo "<br>";
            echo "<a href='../'>Articles List</a>"; 
        }
    }
}

همان‌طور که می‌بینیم، متد DELETE را برای آپشن CURLOPT_CUSTOMREQUEST در نظر گرفته‌ایم چرا که برای حذف یک ریسورس در معماری REST، می‌باید از این متد استفاده نمود و در نهایت چنانچه این عملیات با موفقیت انجام گردد، پیامی همچون «.The article deleted» در معرض دید کاربر قرار خواهد گرفت (لازم به یادآوری است با توجه به اینکه عملیات حذف نیاز به ویو ندارد، نیازی به ساخت فایلی تحت عنوان index.php در پوشهٔ delete نخواهیم داشت.)

جمع‌بندی

در این آموزش دیدیم که به چه شکل می‌توان یک پروژهٔ وب اپلیکیشن ساده ساخت که بتواند به طور عملی با پروژهٔ RESTful API که در این دورهٔ آموزشی ساختیم ارتباط برقرار سازد. در این تِستِر، کلیهٔ تَسک‌هایی که وب سرویس مذکور گنجانده شده بودند را پیاده‌سازی نمودیم اما در عین حال توجه داشته باشیم که می‌توان این وب اپلیکیشن تست‌کننده را بهبود به مراتب بیشتری بخشیده و اصول توسعهٔ نرم‌افزار را بیشتر در آن رعایت نمود (سورس‌کد کامل این پروژهٔ تِستِر از لینک زیر در دسترس است.)

سورس‌کد کامل پروژهٔ تِستِر

online-support-icon