File Upload in CakePHP

In this post I will describe how to upload images in CakePHP. It will automatically upload and move the uploaded file to the wanted location. It will automatically rename the file if there is another file with same name exist. A lot of other features are also available.

  • Download Upload Component file and copy it to the location app/Controller/Component/UploadComponent.php
  • Initialize
    1
    var $components = array('Upload');
  • Your add action would looks like:
    PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public function add() {
        if ($this->request->is('post')) {
            if (!empty($this->request->data) && is_uploaded_file($this->request->data['Gallery']['image']['tmp_name'])) {
                
                $this->Upload->upload($this->data['Gallery']['image']);
                if ($this->Upload->uploaded) {
                    $this->Upload->file_new_name_body = 'image_resized';
                    $this->Upload->image_resize = true;
                    $this->Upload->image_x = 400;
                    $this->Upload->image_ratio_y = true;
                    $this->Upload->process(Configure::read('UploadPath'));
                    if ($this->Upload->processed) {
                        $this->Upload->clean();
                        $this->request->data['Gallery']['image'] = basename($this->Upload->file_dst_name);
                    } else {
                        $errors = $this->Upload->error;
                        $this->Session->setFlash(__($errors));
                        exit();
                    }
                }
            }
            $this->Gallery->create();
            if ($this->Gallery->save($this->request->data)) {
                $this->Session->setFlash(__('The gallery has been saved'));
                $this->redirect(array('controller' => 'galleries' ,'action' => 'index'));
            } else {
                $this->Session->setFlash(__('The gallery could not be saved. Please, try again.'));
            }
        }
    }

  • We have setup our controller. Now its time to setup view file add.ctp. The file file should look like following:

    PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <div class="galleries form">
    < ?php echo $this->Form->create('Gallery', array('enctype' => 'multipart/form-data'));?>
        <fieldset>
            <legend>< ?php echo __('Add Gallery'); ?></legend>
        < ?php
            echo $this->Form->input('caption');
            echo $this->Form->input('desc');
            echo $this->Form->file('image');
        ?>
        </fieldset>
    < ?php echo $this->Form->end(__('Submit'));?>
    </div>
    <div class="actions">
        <h3>< ?php echo __('Actions'); ?></h3>
        <ul>
            <li>< ?php echo $this->Html->link(__('List Galleries'), array('action' => 'index'));?></li>
        </ul>
    </div>

  • All done.

UploadComponent class file is well document so you can always find all configuration setting for the uploaded images.

Setting Auth & ACL in CakePHP

In last few days I learned CakePHP and now I am finding it very interesting. I learned the basics about creation of models and their relationships. Now its time to move ahead. I am exploring more features and I started with inbuilt Auth component of CakePHP which I found very interesting. Let me tell you one thing that if you are following the conventions you can save a lot of time.

To set up Auth and ACL for my application I followed Mark Story’s post which is very helpful. I followed the tutorial and I was easily able to setup Auth & ACL for my application.

But in my application every user belongs to some group and it must inherit permission from that group only. There should not be any user wise permission. This case is not handled in the above tutorial. So, whenever I add new user a new ARO record is being created in aros table, which is not required. I dont want any ARO record for my users as they are inheriting permission from their group. To achieve this functionality I modified $actAs variable as follows:

1
2
3
4
5
6
public $actsAs = array(
            'Acl' => array(
                    'type' => 'requester',
                    'enabled' => false
                )
            );

Look at the declaration carefully as I am passing two parameters type and enabled. Second parameter enabled tells the behaviour class not to look for ARO record for User model if there is already a ARO record of parent Group model. Now we have to define a function bindNode to tell that this user is bind to which ARO node. This function must return a reference to group model. So our bindNode function would look like:

1
2
3
public function bindNode($object) {
    return array('Group' => array('id' => $user['User']['group_id']));
}

Lets Bake in PHP using CakePHP

From last week I decided to learn CakePHP, which is a open source web application framework for producing web applications. It is written in PHP, modeled after the concepts of Ruby on Rails, and distributed under the MIT License.

I started with the official documentation. But I am not finding it very useful when you really get stuck somewhere. But CakePHP has active developer team and very active community.

Here’s a quick list of features you’ll enjoy when using CakePHP:

  • Integrated CRUD for database interaction
  • Application scaffolding
  • Code generation
  • MVC architecture
  • Request dispatcher with clean, custom URLs and routes
  • Built-in validation
  • Fast and flexible templating (PHP syntax, with helpers)
  • View Helpers for AJAX, JavaScript, HTML Forms and more
  • Email, Cookie, Security, Session, and Request Handling Components
  • Flexible ACL
  • Data Sanitization
  • Flexible Caching
  • Works from any web site directory, with little to no Apache configuration involved

Thats all what I get from the initial chapters of CakePHP.

How to Bind Multiline Editbox Through Repeat Control

I have a multi-line edit-box on my xpage which is hidden. I want to allow the user to edit its value through repeat control. I don’t want to allow the user to enter multiple values separated by comma.
To achieve this functionality follow these instructions:

  • Add a multi-line edit-box and a repeat control on your xpage. I assume that there is some value already in the edit-box.
  • Set var = item and indexVar = indexItem
  • Go to the iterator code of the repeat control and return the values of the multi-line edit-box as an array.
  • Add an edit-box inside repeat control.
  • To bind it with the multi-line edit-box, select advanced in data tab then select expression language.
  • Write item[index] in the scriptbox.
  • Preview your xpage.

Sample code

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.resources>
<xp:script src="/General_SSJS.jss" clientSide="false"></xp:script>
</xp:this.resources>
<xp:table style="font-family:arial;font-size:8pt;width:100%" id="xc_MainTable">
<xp:tr>
<xp:td style="width:143.0px" colspan="2">
<xp:inputTextarea id="xc_ccSections" multipleSeparator=",">
<xp:this.defaultValue><![CDATA[#{javascript:["1-10","10-20","20-30"]}]]></xp:this.defaultValue>
</xp:inputTextarea>
</xp:td>
</xp:tr>
</xp:table>
<xp:repeat id="xc_Repeat" rows="30" var="sectionRange" indexVar="rowIndex">
<xp:this.value><![CDATA[#{javascript:var lsRange:Array = fpfSLGetArrayFromMV("xc_ccSections");

var ls2DArray:Array = new Array(lsRange.length);

var liCnt = 0;
var lsRow:Array = null;
for(liCnt = 0;liCnt < lsRange.length;liCnt++) {
lsRow = lsRange[liCnt].split("-");
ls2DArray[liCnt] = new Array(lsRow[0], lsRow[1]);
}
return ls2DArray;}]]></xp:this.value>
<xp:table style="width:100.0%" cellpadding="0" cellspacing="0">
<xp:tr>
<xp:td style="width:50.0%;text-align:center;border-left:1px solid #99B7D8; border-bottom:1px solid #99B7D8;border-right:1px solid #99B7D8;height:23px" align="center">
<xp:inputText id="xc_cc_Start" style="width:90%;font-family:Arial;font-size:8pt">
<xp:this.value><![CDATA[#{sectionRange[0]}]]></xp:this.value>
</xp:inputText>
</xp:td>
<xp:td style="width:50.0%;border-bottom:1px solid #99B7D8;border-right:1px solid #99B7D8" align="center">
<xp:inputText id="xc_cc_End" style="width:90%;font-family:Arial;font-size:8pt">
<xp:this.value><![CDATA[#{sectionRange[1]}]]></xp:this.value>
</xp:inputText>
</xp:td>
</xp:tr>
</xp:table>
</xp:repeat>
</xp:view>

Strip Chart

Strip chart is the graphical representation of the work progress of the project. Different colours are being used to represent different stages of progress. Actual work expands in sections from one point to another and is divided into small patches. Each of the sections (read patched) undergo different stages.

Let us understand it with an example. Suppose we have to build a road of 1 KM. The work can start from any portion and it undergoes several (approval) stages. Let us assume that there are four stages S1, S2, S3 and S4. If there is no work done then it is under stage S1 and if the work is completed it is in stage S4. S2 and S3 are intermediate stages. Let us divide the complete road into small segments of 100 meters each. At some point of time let us assume that the status of the complete road is as follows :

Segment Stage
0-100 S3
100-200 S2
200-300 S2
300-400 S1
400-500 S4
500-600 S4
600-700 S3
700-800 S3
800-900 S1
900-1000 S1

To represent this in a easy and meaningful manner, a graphical representation can be very useful, which may depict the sections as well as their current stages with help of coloured lines. We use two array to store this status, one to store the start and end point of the segment and other to store the stage. So our array will have following data:

Segment[] = {0,100,200,300,400,500,600,700,800,900,1000}

Stage[] = {S3,S2,S2,S1,S4,S4,S3,S3,S1,S1}

If Segment array is containing ‘n’ elements then Stage array must contain ‘n-1′ elements. Stage[i] represents stage of the segment Segment[i] to Segment[i+1] where i = 0 to n-1. For example Stage[2] i.e. S2 represents the stage of segment 200-300.

Now, the big question – how have incorporated this. To build the chart in the browser we have to use a table of one row having multiple columns (managed dynamically). We will club same adjacent stages in the strip chart and make it appear as a composite patch. Thus to prepare the strip chart now (with composite patches), we will build new array as follows:

Segment[] = {0,100,300,400,600,800,1000}

Stage[] = {S3,S2,S1,S4,S3,S1}

To display above data in strip chart we need a table with one row and six columns. Before composite patches:

0               100               200               300              400               500              600               700              800              900              1000

After composite patches:

0               100               200               300              400               500              600               700              800              900              1000

We can put the range and status message inside the columns of the table but the width of the column is dynamic so its width may not accommodate the content. So we can put the range and status message in tool-tip.

This article is also published in monthly newsletter F9 of Knowledge Management group of Reliance Infrastructure.