PHP Framework for Learning

NetBeans Debugging methods

2019-06-17 release

2021-01-14 update


NetBeans Debugging methods (Process flow, Variable value) Autoload

Basic usage of debugging


Debugging Session

e.g. ClassLoader.php autoload

Operation

debugging
ClassLoader.php line 27 check $dir, $this->dirs[]
ClassLoader.php line 37 check foreach
index.php
1    <?php
2 
3    require '../bootstrap.php';
4    require '../MiniBlogApplication.php';
5 
6    $app = new MiniBlogApplication(false);
7    $app->run();
8 

ClassLoader.php (registerDir)
25    public function registerDir($dir)
26    {
27        $this->dirs[] = $dir;
28    }

ClassLoader.php (loadClass)
35    public function loadClass($class)
36    {
37        foreach ($this->dirs as $dir) {
38            $file = $dir . '/' . $class . '.php';
39            if (is_readable($file)) {
40                require $file;
41
42                return;
43            }
44        }
45    }
setting breakpoints
file line
index.php 3 check Process flow (optional)
index.php 4 check Process flow (optional)
ClassLoader.php 27 -
ClassLoader.php 37 -
Process flow
action file line variable value (oher)
Start Session (Ctrl+F5) index.php 3 require '../bootstrap.php';
ClassLoader.php registerDir($dir) check $dir, $this->dirs[]
Resume (F5) ClassLoader.php 27 $this->dirs[] = $dir;
before setting variable  (line 27 before execution)
Step Over (F8) ClassLoader.php 28 }
after setting variable  (line 27 after execution)
hover over variable to see variable value
$dir
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core"
$this->dirs[0]
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core"
$this
  ClassLoader object
Resume (F5) ClassLoader.php 27 $this->dirs[] = $dir;
(set $this->dirs[0])
Step Over (F8) ClassLoader.php 28 }
$dir
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/models"
$this->dirs[0]
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core"
$this->dirs[1]
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/models"
$this
  ClassLoader object
Resume (F5) index.php 4 require '../MiniBlogApplication.php';
ClassLoader.php loadClass($class) check foreach
Resume (F5) ClassLoader.php 37 foreach ($this->dirs as $dir) {
$class
  "Application"
Step Over (F8) ClassLoader.php 38 $file = $dir . '/' . $class . '.php';
$this->dirs[0]
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core"
$this->dirs[1]
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/models"
$dir
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core"
$this
  ClassLoader object
Step Over (F8) ClassLoader.php 39 if (is_readable($file)) {
$file
  "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core/Application.php" (Note there is no line feed)
  $file = $dir . '/' . $class . '.php';

reference
if there is $class . '.php' in models, loop one more time
Step Over (F8) ClassLoader.php 40 require $file;
Step Into (F7) Application.php 9 {
Step Into (F7) ClassLoader.php 42 return;
index.php 6 $app = new MiniBlogApplication(false);
Finish Session (Shift+F5)

Caution

basically there is no need to use URL during debugging
use action (Step Into etc) for Process flow
exception (Contribution list)  http://mini-blog.localhost/user/user3  ('Follow' button)


Breakpoints Window (right-click)
Disable All debug state OFF  (until just before debug process   OFF)
Enable All debug state ON

  you can switch between Disable All and Enable All for efficient debugging See


NetBeans IDE 8.2 bug
variable value Variables Window See

Operation

breakpoint
set click line's left margin to set breakpoint
unset click square shape at line number to cancel breakpoint
right-click in Breakpoints Window, select Delete All
variable value
check hover over variable to see variable value
check (details) you can also check in Variables Window
all items not displayed by "how to use mouse pointer" are also displayed

bug  (subwindow in Variables Window)
contents change when you use Cancel button or Close in subwindow that displays value.
(measures: use OK button every time)
right   "C:\XAMPP\xampp_5.6.31\htdocs\mini-blog.localhost/core"
wrong "C:(new line)MPP(new line)mpp_5.6.31\htdocs\mini-blog.localhost/core"
action
Step Into (F7) Step into a function call  (use properly Step Over (F8))
Step Over (F8) Step over an execution statement  (use properly Step Into (F7))
Resume (F5) Resume debugging session
Finish Session (Shift+F5) Finish debugging session
Run to Cursor (F4) Run execution to the position of the cursor
start debugging
menu click Debug | Debug Project(mini-blog.localhost)
icon click Debug Project(mini-blog.localhost) (Ctrl+F5) icon
Breakpoints Window (right-click) (Described above)
Disable All debug state OFF  (until just before debug process   OFF)
Enable All debug state ON
Variables Window Superglobals
Superglobals example
$_POST $_POST[_token] "117d0e6d9da8ec9e595110d7e517993901ee77ce"
$_REQUEST $_REQUEST[_token] "117d0e6d9da8ec9e595110d7e517993901ee77ce"
$_SERVER $_SERVER[REQUEST_METHOD] "POST"
$_SESSION $_SESSION[csrf_tokens/account/signup][0] "117d0e6d9da8ec9e595110d7e517993901ee77ce"
Variables Window
variable value you can also manually change variable value by clicking in value column

Convenient Operation

action
jump where method is defined Ctrl+B or Ctrl+left-click
cursor history (back, forward) ALT+← (arrow key),  ALT+→ (arrow key)
bootstrap.php
1    <?php
2 
3    require 'core/ClassLoader.php';
4 
5    $loader = new ClassLoader();
6    $loader->registerDir(dirname(__FILE__).'/core');    /* Ctrl+B or Ctrl+left-click */
7    $loader->registerDir(dirname(__FILE__).'/models');
8    $loader->register();

Ctrl+B or Ctrl+left-click on registerDir, jump ClassLoader.php line 25



ClassLoader.php
25        public function registerDir($dir)    /* ALT+← (arrow key) */
26        {
27         $this->dirs[] = $dir;
28        }

ALT+← (arrow key), back bootstrap.php line 6


NetBeans Debugging methods (Change Variable value to change Process flow)

in order to follow error processing, an error is generated intentionally


render404Page execution

e.g. Process flow (Transition to Login)

Application.php (run)
173    public function run()
174    {
175        try {
176            $params = $this->router->resolve($this->request->getPathInfo());
177            if ($params === false) {
178                throw new HttpNotFoundException('No route found for ' . 
    $this->request->getPathInfo());
179            }
180
181            $controller = $params['controller'];
182            $action = $params['action'];
183
184            $this->runAction($controller, $action, $params);
185        } catch (HttpNotFoundException $e) {
186            $this->render404Page($e);
187        } catch (UnauthorizedActionException $e) {
188            list($controller, $action) = $this->login_action;
189            $this->runAction($controller, $action);
190        }
191
192        $this->response->send();
193    }

changed $params value to false

Application.php (render404Page)
247    protected function render404Page($e)
248    {
249        $this->response->setStatusCode(404, 'Not Found');
250        $message = $this->isDebugMode() ? $e->getMessage() : 'Page not found.';
251        $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
252
253        $this->response->setContent(<<<EOF
254<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
255"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
256<html>
257<head>
258    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
259    <title>404</title>
260</head>
261<body>
262    {$message}
263</body>
264</html>
265EOF
266        );
267    }

Application.php (isDebugMode)
83    public function isDebugMode()
84    {
85        return $this->debug;
86    }
setting breakpoints
file line
Application.php 177 -
Process flow
action file other line
Start Session (Ctrl+F5) Application.php 177 Variables Window
change $params value to false
(input false, output 0)
Step Over (F8) Application.php 178 throw new HttpNotFoundException('No route found for ' . $this->request->getPathInfo());
Step Over (F8) Application.php 186 $this->render404Page($e);
Step Into (F7) Application.php 249 $this->response->setStatusCode(404, 'Not Found');
Step Over (F8) Application.php 250 $message = $this->isDebugMode() ? $e->getMessage() : 'Page not found.';
Step Into (F7) Application.php 85 return $this->debug;
(use index.php)
change debug value to true (debug mode)
Resume (F5) browser Page not found.
 or
No route found for
(debug mode)
Finish Session (Shift+F5)

forward404 execution (POST check)

e.g. Process flow (Account registration screen (User registration screen) & User registration)

AccountController.php (registerAction)
25    public function registerAction()
26    {
27        if ($this->session->isAuthenticated()) {
28            return $this->redirect('/account');
29        }
30
31        if (!$this->request->isPost()) {
32            $this->forward404();
33        }
34
... it is omitted below

Request.php (isPost)
15    public function isPost()
16    {
17        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
18            return true;
19        }
20
21        return false;
22    }

changed Superglobals $_SERVER['REQUEST_METHOD'] value to "GET"

Controller.php (forward404)
94    protected function forward404()
95    {
96        throw new HttpNotFoundException('Forwarded 404 page from '
97            . $this->controller_name . '/' . $this->action_name);
98    }

Application.php (run)
173    public function run()
174    {
175        try {
176            $params = $this->router->resolve($this->request->getPathInfo());
17            if ($params === false) {
178                throw new HttpNotFoundException('No route found for ' . 
    $this->request->getPathInfo());
179            }
180
181            $controller = $params['controller'];
182            $action = $params['action'];
183
184            $this->runAction($controller, $action, $params);    /* registerAction in runAction */
185        } catch (HttpNotFoundException $e) {
186            $this->render404Page($e);
187        } catch (UnauthorizedActionException $e) {
188            list($controller, $action) = $this->login_action;
189            $this->runAction($controller, $action);
190        }
191
192        $this->response->send();
193    }

Application.php (render404Page)
247    protected function render404Page($e)
248    {
249        $this->response->setStatusCode(404, 'Not Found');
250        $message = $this->isDebugMode() ? $e->getMessage() : 'Page not found.';
251        $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
252
253        $this->response->setContent(<<<EOF
254<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
255"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
256<html>
257<head>
258    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
259    <title>404</title>
260</head>
261<body>
262    {$message}
263</body>
264</html>
265EOF
266        );
267    }

Application.php (isDebugMode)
83    public function isDebugMode()
84    {
85        return $this->debug;
86    }
setting breakpoints
file line
AccountController.php 31 -
Process flow
action file other line
Start Session (Ctrl+F5) Login
click Account registration or New User registration
User ID: user4, Password: password
click Registration button
AccountController.php 31 if (!$this->request->isPost()) {
Step Into (F7) Request.php 17 if ($_SERVER['REQUEST_METHOD'] === 'POST') {
Variables Window
change Superglobals $_SERVER['REQUEST_METHOD']
value to "GET"
(change to string other than "POST")
Step Over (F8) Request.php 21 return false;
Step Over (F8) AccountController.php 32 $this->forward404();
Step Into (F7) Controller.php 96 throw new HttpNotFoundException('Forwarded 404 page from '
Step Over (F8) Application.php 186 $this->render404Page($e);
Step Into (F7) Application.php 249 $this->response->setStatusCode(404, 'Not Found');
Step Over (F8) Application.php 250 $message = $this->isDebugMode() ? $e->getMessage() : 'Page not found.';
Step Into (F7) Application.php 85 return $this->debug;
(use index.php)
change debug value to true (debug mode)
Resume (F5) browser Page not found.
 or
Forwarded 404 page from account/register
(debug mode)
Finish Session (Shift+F5)

redirect execution (Token check)

e.g. Process flow (Account registration screen (User registration screen) & User registration)

index.php
1    <?php
2 
3    require '../bootstrap.php';
4    require '../MiniBlogApplication.php';
5 
6    $app = new MiniBlogApplication(false);
7    $app->run();
8 

AccountController.php (registerAction)
25    public function registerAction()
26    {
27        if ($this->session->isAuthenticated()) {
28            return $this->redirect('/account');
29        }
30
31        if (!$this->request->isPost()) {
32            $this->forward404();
33        }
34
35        $token = $this->request->getPost('_token');
36        if (!$this->checkCsrfToken('account/signup', $token)) {
37            return $this->redirect('/account/signup');
38        }
39
... it is omitted below

changed $token value

Controller.php (checkCsrfToken)
148    protected function checkCsrfToken($form_name, $token)
149    {
150        $key = 'csrf_tokens/' . $form_name;
151        $tokens = $this->session->get($key, array());
152
153        if (false !== ($pos = array_search($token, $tokens, true))) {
154            unset($tokens[$pos]);
155            $this->session->set($key, $tokens);
156
157            return true;
158        }
159
160        return false;
161    }

Controller.php (redirect)
105    protected function redirect($url)
106    {
107        if (!preg_match('#https?://#', $url)) {
108            $protocol = $this->request->isSsl() ? 'https://' : 'http://';
109            $host = $this->request->getHost();
110            $base_url = $this->request->getBaseUrl();
111
112            $url = $protocol . $host . $base_url . $url;
113        }
114
115        $this->response->setStatusCode(302, 'Found');
116        $this->response->setHttpHeader('Location', $url);
117    }
118

Response.php (send)
18    public function send()
19    {
20        header('HTTP/1.1 ' . $this->status_code . ' ' . $this->status_text);
21
22        foreach ($this->http_headers as $name => $value) {
23            header($name . ': ' . $value);
24        }
25
26        echo $this->content;
27    }

DbManager.php (__destruct)
109    public function __destruct()
110    {
111        foreach ($this->repositories as $repository) {
112            unset($repository);
113        }
114
115        foreach ($this->connections as $con) {
116            unset($con);
117        }
118    }
setting breakpoints
file line
index.php 3 check Process flow (not optional) & for Disable All
AccountController.php 36 change $token value
AccountController.php 37 -
Controller.php 160 -
Controller.php 115 -
Response.php 20 -
DbManager.php 111 check Process flow (not optional)
Process flow
action file other line
Start Session (Ctrl+F5) index.php 3 require '../bootstrap.php';
Breakpoints Window (right-click)
Disable All
Resume (F5) browser Login
click Account registration or New User registration
Account registration screen
User ID: user4, Password: password
Breakpoints Window (right-click)
Enable All
click Registration button
User registration
index.php 3 require '../bootstrap.php';
Resume (F5) AccountController.php 36 if (!$this->checkCsrfToken('account/signup', $token)) {
Variables Window
change $token value
"add" + "original value" (change to string other than "original value")
Step Into (F7) Controller.php 150 $key = 'csrf_tokens/' . $form_name;
Resume (F5) Controller.php 160 return false;
Resume (F5) AccountController.php 37 return $this->redirect('/account/signup');
Step Into (F7) Controller.php 107 if (!preg_match('#https?://#', $url)) {
Resume (F5) Controller.php 115 $this->response->setStatusCode(302, 'Found');
Step Over (F8) Controller.php 116 $this->response->setHttpHeader('Location', $url);
Resume (F5) Response.php 20 header('HTTP/1.1 ' . $this->status_code . ' ' . $this->status_text);
$this->status_code
  302
$this->status_text
  "Found"
Step Over (F8) Response.php 22 foreach ($this->http_headers as $name => $value) {
Step Over (F8) Response.php 23 header($name . ': ' . $value);
$name
  "Location"
$value
  "http://localhost/mini-blog.localhost/web/index.php/account/signup"
Resume (F5) DbManager.php 111 foreach ($this->repositories as $repository) {
Account registration screen
Resume (F5) index.php 3 require '../bootstrap.php';
Resume (F5) Response.php 20 header('HTTP/1.1 ' . $this->status_code . ' ' . $this->status_text);
$this->status_code
  200
$this->status_text
  "OK"
Resume (F5) DbManager.php 111 foreach ($this->repositories as $repository) {
Resume (F5) browser Account registration screen
Finish Session (Shift+F5)
Page Top
Page Bottom