Posted on Leave a comment

Undestanding PHP Namespaces

I have hard time understanding PHP namespace. So, this post is things I learn from working with it.

Namespace keyword starts the file.

When you include the class that has namespace defined, you also need to type the keyword use and the namespace you want to use follows. Without using namespace, this would work. However, with namespace, the keyword use is required.

The main purpose of namspaces in PHP is to avoid name conflict.

Namespace is used in class. You cannot declare a namespace and in that file don’t declare a class.

In one file, you can have class definition and code (functions, variables) outside of that class. This is strange for me since I learn OOP first from Java. You cannot access such functions/properties from other files though (even if you include it). However, these functions, variables are accessible in the classes of the same file. Maybe it’s a way of code sharing without declaring a class with static functions/properties.

Posted on Leave a comment

[Ultimate] Guide to PHP Autoload

Calling spl_autoload_register without argument

  • spl_autoload_register() without arguments will invoke (call) another function called spl_autoload when php script tries to access an unknown class. The name of the unknown class will be passed to spl_autoload. spl_autoload first then find if there is a file name identical to the class name (lower and upper case, php 7) with the extension .php or .inc in: First, the include path then the local directory. The search will stop once the file is found (not when the class is found). Sounds confusing? Let me demonstrate:

Let’s make it clearer:

So, I have the root folder with two files: index.php and cat.php (lowercase C). One folder called animal that contains Cat.php (uppercase)

Here are the code in each file:

cat.php

<?php

class Cat
{
    function __construct($name)
    {
        echo "I am a cat in the local directory";
    }
}

Cat.php (inside animal folder)

<?php

class Cat
{
    function __construct($name)
    {
        echo "I am the cat in the ANIMAL directory";
    }
}

index.php (root folder)

<?php

set_include_path(get_include_path() . PATH_SEPARATOR . "animal");
spl_autoload_register();

$x = new Cat("jane");

When I access the index.php file in the browser, here is what I get:

As you can see, the Cat inside animal is used. It is because of this line in the index.php file

set_include_path(get_include_path() . PATH_SEPARATOR . "animal");

I set the animal to the include path. PHP will search for file names with extensions .php or .inc in those paths first. If the file name is found (in this case is Cat.php/Cat.inc/cat.php/cat.inc), then the search will stop. Remember that the search doesn’t care if the class exists. It only cares if the file exists. If I comment out the implementation of the Cat class in animal/Cat.php and access the index.php again, I’ll get an error:

Fatal error: Uncaught Error: Class ‘Cat’ not found in C:\xampp\htdocs\lab\oop\index.php:6 Stack trace: #0 {main} thrown in C:\xampp\htdocs\lab\oop\index.php on line 6

Now, if I comment out the set_include_path line in index.php, I’ll get the Cat class in the root directory:

// set_include_path(get_include_path() . PATH_SEPARATOR . "animal");
spl_autoload_register();

$x = new Cat("jane");
Posted on Leave a comment

Adding new tab to WooCommerce Product Data Panel

Adding new tab to WooCommerce Product Data panel is simple. First, you need to add the tab item. The name of the hook is:

woocommerce_product_write_panel_tabs

So, the add_action would be:

add_action( 'woocommerce_product_write_panel_tabs', 'wc_custom_tab_head' );

And the function wc_custom_tab_head is responsible for outputting the tab’s head HTML

Here is an implementation of wc_custom_tab_head

function wc_custom_tab_head()
{
    echo '<li class="product_tabs_tab"><a href="#woocommerce-custom-tab">Custom tab</a></li>';
}

Adding content to the tab

We have successfully add the tab, however, the tab is still blank. How to add content to that tab?

To add content to the Product Data panel, you’ll need to use the following hook:

woocommerce_product_data_panels

The add_action would be:

add_action( 'woocommerce_product_data_panels', 'wc_custom_tab_content' );

The implementation of wc_custom_tab_content could be:

function wc_tab_manager_product_tabs_panel_content() {

    ?>
    <div id="woo-custom-tab" class="panel wc-metaboxes-wrapper">
        <div class="woocommerce_product_tabs wc-metaboxes">
            <!-- Tab content -->
            <h1>hello</h1>
            <!-- End tab content -->
        </div>
    </div>
<?php 
}
Posted on Leave a comment

The Ultimate Guide/Troubleshooting To Install OsTicket On Nginx

OsTicket is an awesome ticketing system. It’s better than Hesk in my opinion. However, the sad thing about this ticketing software is it doesn’t support nginx server officially. However, if you are running Nginx, you can make it work.

Nginx configuration for OsTicket

server_name server_name;
root /path-to-your-root/;
include         mime.types;
default_type    application/octet-stream;
sendfile        on;
charset         utf- ;
gzip            on;
gzip_types      text/plain application/xml text/javascript;
gzip_min_length  ;

index index.php index.html index.htm;

set $path_info "";

# Deny access to all files in the include directory
location ~ ^/include {
deny all;
return  ;
}

# Deny access to apache .ht* files (nginx doesn't use these)
location ~ /\.ht {
deny all;
}


# Requests to /api/* need their PATH_INFO set, this does that
if ($request_uri ~ "^/api(/[^\?]+)") {
set $path_info $ ;
}

# /api/*.* should be handled by /api/http.php if the requested file does not exist
location ~ ^/api/(tickets|tasks)(.*)$ {
try_files $uri $uri/ /api/http.php;
}

# /scp/ajax.php needs PATH_INFO too, possibly more files need it hence the .*\.php
if ($request_uri ~ "^/scp/.*\.php(/[^\?]+)") {
set $path_info $ ;
}


# Make sure requests to /scp/ajax.php/some/path get handled by ajax.php
location ~ ^/scp/ajax.php/(.*)$ {
try_files $uri $uri/ /scp/ajax.php;
}

# Set index.php as our directoryindex
location / {
index index.php;
}

# Send php files off to the PHP-FPM listing on localhost: 
location ~ \.php$ {
try_files $uri = ;
fastcgi_pass    php;
fastcgi_index   index.php;
fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
fastcgi_param   PATH_INFO               $path_info;
include fastcgi_params;
}

# Make sure requests to /ajax.php/some/path get handled by ajax.php
location ~ ^/ajax.php/(.*)$ {
try_files $uri $uri/ /ajax.php;
}

How to fix file upload undefined 400 in OSTicket

Kudos to this original post: https://github.com/osTicket/osTicket-1.7/issues/538#issuecomment-16049117

If you/your users have problem uploading files when opening a ticket like this:

Then, open the file include/class.osticket.php and find the function get_path_info. Replace its definition with the block above.

    function get_path_info() {
        if(isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']))
            return $_SERVER['PATH_INFO'];

        if(isset($_SERVER['ORIG_PATH_INFO']) && !empty($_SERVER['ORIG_PATH_INFO']))
            return $_SERVER['ORIG_PATH_INFO'];

        $request_uri = preg_replace('@\?.*$@', '', $_SERVER['REQUEST_URI']);

        if (strpos($request_uri, $_SERVER['SCRIPT_NAME']) !== false) {
            $guessed_pathinfo = preg_replace('#^'.preg_quote($_SERVER['SCRIPT_NAME']).'#', '', $request_uri);
        } else {
            $guessed_pathinfo = preg_replace('#^'.preg_quote(preg_replace('@/([^/]+)$@', '', $_SERVER['SCRIPT_NAME'])).'#', '', $request_uri);
        }
        if (!empty($guessed_pathinfo))
            return $guessed_pathinfo;

        return null;
    }

Save the file and you can now upload the attachment when opening a ticket.

Posted on Leave a comment

React Notes

List and keys

  • Don’t use index as key
  • Key must be unique
  • Passing key to the child of the list, not in the render function


Form

  • Textarea uses value attribute
  • Select doesn’t use selected attribute but specify the selected value in the value attribute of select opening tag
  • If passing value in as an array to a select element and multiple is set to true, select enables multiple value selected
  • What is a controlled component (vs uncontrolled component)