Zum Inhalt springen

mathias wellner

ingenieur und schauspieler

Archiv

Tag: php

There are quite some tuto­ri­als on ajax effects out there [1, 2], but most were too com­plex for my needs. I sim­ply wan­ted an enhan­ced index page for pro­jects, which shows some details for each pro­ject and more on demand with a sli­ding effect. So here is what my solu­tion looks like.

Basics

I used cake­PHP 1.3 RC3. I assume that you have a run­ning cake­PHP app­li­ca­tion with an index view of your main objects of con­cern. You also need to down­load the pro­to­type and scripta­cu­lous scripts and put all js-​​files into your /​app/​webroot/​js folder.

Activat­ing ajax

In your default lay­out, you have to include the links to the pro­to­type and scripta­cu­lous scripts in the head sec­tion of the template.

<!-- file app/views/layout/default.ctp -->
<head>
    <!-- existing head settings -->
    <?php
    echo $javascript->link('prototype');
    echo $javascript->link('scriptaculous.js?load=effects');
    ?>
</head>

You also need to activate the AJAX and Java­script hel­pers in the con­trol­ler where you want to use it. I pre­fe­red to update the app con­trol­ler, which enab­les the hel­pers for all con­trol­lers. Your app con­trol­ler (usually at app/app_controller.php, create if necessary) should include the ajax and java­script hel­pers like this:

<!-- file app/app_controller.php -->
<?php
class AppController extends Controller {
    var $helpers = array('Html', 'Form', 'Ajax', 'Javascript');
}
?>

In your view

In your view you can now include id-​​marked divs and ajax links to con­trol the visi­bi­lity of these divs. Assu­ming that your model is named Pro­ject, you need to update your index view at /app/views/project/index.ctp. I use two table rows for that. The first row con­tains the pro­ject name, the ajax links for showing/​hiding details, and the actions. The second row is invi­si­ble at first (display:none) and con­tains the div which is con­trol­led by the ajax links. To my know­ledge it is not pos­si­ble to hide/​show ent­ire table rows, the­re­fore the second row is ren­de­red empty at first. But it looks quite nice with the default alter­nate back­ground color for table rows.

The real trick here was to leave the second argu­ment for the ajax link empty, lin­king to the same page. All other exam­ples had links to sub pages imple­men­ted there what see­med too com­plex for my wis­hes. Of course, this imple­men­ta­tion means that the ent­ire con­tent is loa­ded every time. For huge amounts of data this could be a per­for­mance issue.

<!-- file app/views/project/index.ctp -->
<table cellpadding="0" cellspacing="0">
<tr>
    <th><?php echo $paginator->sort('name');?></th>
    <th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i = 0;
foreach ($projects as $project):
    $id = $project['Project']['id'];
    $i++;
?>
<tr>
    <td>
	<?php echo $project['Project']['name'];?>
        <?php
        // define string for div id
        $div_string = 'project_fold_'.$i;

	// create ajax link which shows project details
	echo $ajax->link(
	    'show details',
	    '',
	    array(
	 	'update' => $div_string,
		'loading' => 'Effect.Appear(\''.$div_string.'\')',
	    )
	);

	// create ajax link which hides project details
	echo $ajax->link(
	    'hide details',
	    '',
	    array(
	 	'update' => $div_string,
		'loading' => 'Effect.Fade(\''.$div_string.'\')',
	    )
	);
	?>
    </td>
    <td class="actions">
	<?php echo $html->link(__('View', true), array('action'=>'view', $id));?>
	<?php echo $html->link(__('Edit', true), array('action'=>'edit', $id));?>
	<?php echo $html->link(
            __('Delete', true),
            array( 'action'=>'delete', $id),
            null,
            sprintf(__('Are you sure you want to delete # %s?', true), $id));
        ?>
    </td>
</tr>

<tr>
    <td colspan="2">
	<!-- display div which can be shown/hidden by ajax links -->
	<?php echo $ajax->div($div_string, array('style' => 'display:none')); ?>

	<!-- project details -->
	<h3><?php echo __('Project details');?></h3>
	<dl>
  	    <dt><?php echo __('Description');?></dt>
	    <dd><?php echo $project['Project']['description'];?></dd>
	    <dt><?php echo __('Budget');?></dt>
	    <dd><?php printf("%.2f kCHF", $project['Project']['budget']);?></dd>
	</dl>

	<?php echo $ajax->divEnd($div_string); ?>
    </td>
</tr>
<?php endforeach; ?>
</table>

If you want to go one step fur­ther, you can try to show/​hide the ajax links as well. At first, only show details is visi­ble. When details are visi­ble, only hide details can be seen.

Refe­ren­ces

[1] Get­ting quickly star­ted quickly with scripta­cu­lous effects, The Bak­ery
[2] AJAX cake­PHP, Rever­se­Folds

Eager to check out cake­PHP, a rapid deve­lop­ment sys­tem for web app­li­ca­ti­ons, I was run­ning into the error mes­sage ‚Cake is NOT able to con­nect to the data­base‘. After hours of try­ing out a num­ber of things, I finally found the pro­blem. The enco­ding was not set and also not men­tio­ned in the docu­men­ta­tion or tutorial.

This is my modi­fied database.php file in the app/​config folder.


var $default = array(
'driver' => 'mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'username',
'password' => 'password',
'database' => 'db',
'ecoding' => 'utf8',
'prefix' => ''
)

Sys­tem con­fi­gu­ra­tion: Ubuntu Linux 9.10, Apa­che, MySQL 5.1.37, PHP 5.2.10