Remote Debugging with Xdebug and Netbeans

I spoke with Derick Rethans on the last PHP London Conference, who told me that Latest version of Xdebug 2.1 does not require setting up a proxy. If you are planning to set up xdebug remote debugging, ignore this article and follow to Derrick’s website:
With an unknown IP/multiple developers

Go through “Setting up Xdebug on the Centos and Zend Server for Remote debugging” first.

1. Set up ssh key to be able to login to staging without password
2. Installing remote file access

sudo apt-get install sshfs
mkdir -p /home/[username]/remote/staging
adduser [username] fuse
sshfs -o transform_symlinks root@www.staging.net:/home /home/pawel/remote/staging
#Permanent mount in /etc/fstab
#sshfs#user@host:/ /home/you/remote fuse defaults 0 0

3. Install Xdebug Helper – plugin
Get Xdebug Helper add-on here (https://addons.mozilla.org/en-US/firefox/addon/3960).
Another clone can be found here: easy Xdebug (https://addons.mozilla.org/en-US/firefox/addon/58688)
Once installed, go to this add-on’s Options dialog and set the idekey to ‘netbeans-xdebug-username’
Tools->Add-ons->Extentions->Debug Helper->Preferences
Set Exactly the same key in Netbeans->Tools->Options->PHP->General:
Debugger Port: 9000
Session ID: ‘netbeans-xdebug-username’

4. Create project from existing sources
Netbeans->File->New Project->Php App with Existing Sources
Sources Folder: /home/[username]/remote/staging/uapi/html/current
Project Name: userapi@staging
Tick: Put NetBeans metadata into a ….
Metadata Folder: /home/pawel/NetBeansProjects/userapi@staging

Click Next

Local Web Site (…)
Project URL: http://uapi.staging.net/
Index File: public/index.php

Click Finish

Right click on the project folder, then Properties->Run Configuration->Advanced and set:
Host: uapi.staging.net
Port: 9001

Click OK

Done!

Setting up Xdebug on the Centos and Zend Server for Remote debugging

1. Make sure that Zend Debugger is disabled
2 Install Xdebug

/usr/local/zend/bin/pecl install xdebug

In case of problems rename channels folder:

mv /usr/local/zend/share/pear/.channels /usr/local/zend/share/pear/.channels_old

update the channels:

/usr/local/zend/bin/pear channel-update pear.php.net

Run the command again:

/usr/local/zend/bin/pecl install xdebug

Xdebug will be compiled for you now.
3. Add Xdebug setting to php config:

vim /usr/local/zend/etc/php.ini
zend_extension=”/usr/local/zend/lib/php_extensions/xdebug.so”
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_port=9000
xdebug.remote_host=localhost
xdebug.idekey=default

4. Restart Zend Server and make sure that phpini showas that Xdebug is set up properly.

service zend-server restart

5. Download Python Proxy service:

cd /opt
wget http://downloads.activestate.com/Komodo/releases/5.2.4/Komodo-IDE-5.2.4-37659-linux-libcpp6-x86.tar.gz

untar it:

tar -zxf Komodo-IDE-5.2.4-37659-linux-libcpp6-x86.tar.gz

make symlink:

ln -s Komodo-PythonRemoteDebugging-5.2.4-37659-linux-x86 Komodo-PythonRemoteDebugging

Add this line to your /etc/rc.local

/opt/Komodo-PythonRemoteDebugging/bin/pydbgpproxy -i 192.168.0.125:9001 -d localhost:9000

You can run the proxy debugger manually by typing

/opt/Komodo-PythonRemoteDebugging/bin/pydbgpproxy -i 192.168.0.125:9001 -d localhost:9000 &

Done!

Building MySQL prepared queries with ‘IN’ clause and unknown number of parameters

November 13, 2009 Leave a comment

Recently I have faced a problem of building MySQL queries which have an unknown number of parameters in ‘IN’ clause:

SELECT * FROM user WHERE id IN (1,2,3)

SELECT * FROM user WHERE id IN (1,2,3,4,5…)

Here is the solution:

$userId = array(1,2,3,4);

$questionmarks = substr(str_repeat(‘?,’, count($userId)), 0, -1);

$sql = “SELECT * FROM user WHERE id IN ($questionmarks)”;

echo $sql;

//prints  SELECT * FROM user WHERE id IN (?,?,?,?)

Categories: Coding Tags: ,

Debugginng PHP with NetBeans (Ubuntu)

September 20, 2009 Leave a comment

1. Install xdebug on your machine:

sudo apt-get install php5-dev
pecl install xdebug

2. Add these lines to your php.ini

xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_mode=req
xdebug.remote_port=9000
xdebug.remote_host=localhost
xdebug.idekey=default

Make sure that Zend Debuger is disabled.

3. Restart your web-server: sudo apache2ctl restart

4. check your phpinfo() output look for xdebug section if there is no anything about xdebug on phpinfo() page, ensure everything is correct on prev steps and don’t forget to restart web server

5. Get Xdebug Helper add-on here: https://addons.mozilla.org/en-US/firefox/addon/3960.

6. Once installed, go to this add-on’s Options dialog and
set the idekey to ‘netbeans-xdebug’

Tools->Add-ons->Extentions->Debug Helper->Preferences

7. In NetBeans, kick off a debug session and leave it running. That is don’t ‘red button’ stop the session. This, in effect, leaves NetBeans in the typical Xdebug ‘listening’ mode familiar to folks who have used other PHP IDEs.

8. Now you go to your Firefox browser and toggle debugging on and off with a click of the Xdebug Helper icon in the status bar. When on, NetBeans will hear the debug request and you are debugging. Once that page-rendering is done and you are back into Firefox, you can turn your debug session on and off at will.

9. When you are fully done with debugging, click the ‘Finish debugger session’ red button in the NetBeans toolbar and your are out of Xdebug listening mode.

Categories: Coding Tags: , , ,

Windows 7 = Windows NT 6.1

August 25, 2009 1 comment

Edit: this case is closed now. Google Analytics has finally found out that Windows 7 exists!

Everyone is talking these days about new and shiny release of Windows 7, some even call it Windows Vista 7 due to rumours that Windows 7 is simply re-branded Windows Vista.

I have, of course, tried the RTM version, and is seems behaving as a pretty robust OS, however one of my first thoughts was to check the Google Analytics on one of my sites to see how v7 is coping.

I realised that I couldn’t find it on the Operating systems list:
Operating System - Google Analytics

What I have found out, is that any browser installed on Windows 7 computer will present itself by sending a string similar to:

“Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)”

Which basically means that Windows 7 holds in fact number “6” from Windows Vista!

So far there is an open topic on the GA support forum but it seems that Google Analytics is at least ignoring the existence of Windows 7 ;-)

Just to remind you this is how Microsoft used to assign numbers in the past:

windows 1.x (dos)
windows 2.x (dos)
windows 3.x (dos)
windows nt 3.x (nt)
windows 4.x (windows 95, 98 and me)
windows nt 4 (nt)
windows 2000 (windows nt 5.0) (nt)
windows xp (windows nt 5.1) (nt)
windows sever 2003 (windows nt 5.2) (nt)
windows vista / server 2008 (windows nt 6.0) (nt)
windows 7 (windows nt 6.1) (nt)

Quick DDOS check

August 21, 2009 1 comment

This little command-line tool helps quickly checking weather someone is attempting a Distributed Denial Of Service attack on the server.

netstat -anp |grep 'tcp\|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n

What you need to do now, is to take this code and save it on the server, for instance in /usr/local/bin/.
I suggest calling it as “ddos_check” in order to find it easily when problems occur.
Finally execute flags must be enabled, chmod 755 … will do the job.

Now just run the command:

[user@server ~]# ddos_check

As a result you should see the list of the most active IP addresses with number of connections to your server.

Categories: Sysadmin Tags: ,

Dynamic Zend Form + Ajax + Doctrine

July 19, 2009 1 comment

In this example I want to show how to build a form with dynamic numer of elements using Zend_Form, Doctrine ORM and a little bit of AJAX.

Objective: dynamic form, easy to manage by users, must be able to use all Zend_From features including data validation.

As an example I have created a ‘Partner Links’ page where partner Urls can be managed.

See working example here (Successful saving is disabled)

To have a full picture I suggest downloading the source

Step one: Concept
To make a form with a dynamic number of elements , it must be pre-built just before validating or displaying.
The easiest way to achieve this is to check the POST data before validating or count Database records when displaying the form. Once we know the desired number of blocks to be displayed, we can generate the form and send it to the browser.
The initform function will perform a check based on the given data:

public function initform($form_params)
{
if(is_array($form_params['form_data']))
{
$form_params['partner_links'] = $this->getFormIDs($form_params['form_data']);
}
else
{
$this->readData();
$form_params['partner_links'] = $this->getDbIDs();
}
$this->form = new Cms_PartnerlinkForm(null, $form_params);
}

Step two: adding new blocks

Adding new form blocks is possible through AJAX request, which retrieves Zend_Subform elements. Thanks to this, form structure is defined only once – without necessity of building it using JavaScript. Moreover all Zend_Form validators can be used as usual:

public function buildBlock($params)
{
$id = $params['id'];
$subform = new Zend_Form_SubForm();
$subform->removeDecorator(‘DtDdWrapper’);
$subform->removeDecorator(‘HtmlTag’);
$subform->setAttrib(‘class’, ‘partner_link_block’);
$subform->setAttrib(‘id’, ‘partner_link_block_’.$id);
//Partner name
$partner_name = new Zend_Form_Element_Text(‘partner_name_’.$id);
$partner_name->setLabel(”);
$partner_name->setRequired(true);
$partner_name->setAttrib(‘class’, ‘partner_name’);
$partner_name->setAttrib(‘title’, ‘Partner name’);
$this->mrProper($partner_name);
//Partner url
$partner_url = new Zend_Form_Element_Text(‘partner_url_’.$id);
$partner_url->setLabel(”);
$partner_url->setRequired(true);
$partner_url->setAttrib(‘class’, ‘partner_url’);
$partner_url->setAttrib(‘title’, ‘Partner url’);
$this->mrProper($partner_url);
//Partner order
$partner_order = new Zend_Form_Element_Text(‘partner_order_’.$id);
$partner_order->setLabel(”);
$partner_order->setRequired(true);
$partner_order->setAttrib(‘class’, ‘partner_order’);
$partner_order->setAttrib(‘title’, ‘Order’);
$this->mrProper($partner_order);
$partner_delete = new Zend_Form_Element_Image(‘partner_delete_’.$id);
$partner_delete->src = ‘/images/fam/delete.png ‘;
$partner_delete->setLabel(”);
$partner_delete->setAttrib(‘class’, ‘partner_delete’);
$partner_delete->setValue($id);
$this->mrProper($partner_delete);
return $subform->addElements(array($partner_name, $partner_url, $partner_order, $partner_delete));
}

Step three: AJAX call

Every time when Add button is pressed, a new form block is being generated:

public function getsubformAction() {

 $id = 'new'.time();
 $this->PartnerlinkForm = new Cms_PartnerlinkForm();
 $this->view->subform = $this->PartnerlinkForm->buildBlock(array('id' => $id));
 $this->view->subform->setName('block_'.$id);

 echo $this->view->subform->render();exit;

 }

Step four: JavaScript

As expected JavaScript is responsible for deleting records and adding new ones. To make things easier, I have used Prototypejs framework.

<script type="text/javascript">
document.observe("dom:loaded", function() {

 var processing_form = 0
 addDeleteObservers()

 if($('partner_add')) {
 $('partner_add').observe('click', function(e){
 e.stop()
 processing_form += 1
 new Ajax.Request('/php-zend_form-ajax-doctrine-example/getsubform',
 {
 method:'post',
 parameters: {},
 onSuccess: function(transport){
 var data = transport.responseText;
 Insertion.Before('submit_request-label', data);
 addDeleteObservers()
 processing_form -= 1
 },
 onFailure: function(){ alert('Something went wrong...') }
 });

 });

 }

 function addDeleteObservers(){

 $$('.partner_delete').each(function(item){
 item.stopObserving('click')
 item.observe('click', function(e){
 deletePartnerLink(e);
 });
 })
 }

 function deletePartnerLink(e){
 if(e.originalTarget)
 e.originalTarget.parentNode.remove()
 else if(e.srcElement && e.srcElement.parentNode.id){//IE{
 $(e.srcElement.parentNode.id).remove()
 }
 e.stop()
 }

});

</script>

That’s all folks. Any questions – please give me a shout!

Follow

Get every new post delivered to your Inbox.