jump to navigation

Javascript Links February 23, 2006

Posted by rossoft in CakePHP.
6 comments

When you want to execute a Javascript method to the current page with an anchor link, you have two methods:

Creating a link with <a href=”javascript:new Effect(xxx)”> or with <a href=”#” onClick=”new Efect(xxxx); return false”>

Only the second method worked for me, and is the most standard way. I have created a method in a custom helper for doing it automatically.

        /**
         * Link to a javascript method
         * @param $title Title for the link
         * @param url Javascript methods to execute. Separate with a ‘;’         
         */
        function linkJavascript($title,$url, $htmlAttributes = array(), $confirmMessage = false, $escapeTitle = true,$return=false)
        {           
            $htmlAttributes[‘onclick’]=$url . “; return false;”;   
            return $this->link($title,’#’,$htmlAttributes,$confirmMessage,$escapeTitle,$return);
        }       

The usage is very simple:
$myhtml->linkJavascript(‘Click this’,’new Effect(xxxx’));

Advertisements

Complex Types – 2 February 17, 2006

Posted by rossoft in CakePHP.
12 comments

Working more on complex types. Now you can describe a complex type simply telling the name of the model. Automatically the webservice checks the model and defines the variable in the xsd.
I  have updated the controller class

A more complete example:

<?php
vendor(‘nusoap/web_services_controller’);
class ArticulosServicesController extends WebServicesController
{
    var $name=’ArticulosServices’;
    var $uses=array(‘Articulo’,’Familia’);
   
    var $api=array(
            ‘add’=>array (    ‘doc’=>’agregar articulo’,
                            ‘input’=>array(‘codigo’=>’xsd:string’,
                                            ‘nombre’=>’xsd:string’,
                                            ‘precio’=>’xsd:float’)),
               ‘browse’=>array(‘doc’=>’precio articulo’,                                      
                             ‘output’=>array(‘return’=>’Array_Articulos’)),

               ‘read’=>array(‘doc’=>’lee todos los campos de un articulo’,                                      
                            ‘output’=>array(‘return’=>’Articulo’)),

               ‘read2’=>array(‘doc’=>’lee algunos campos de un articulo’,                                      
                            ‘output’=>array(‘return’=>’Articulo2’)),

                                           
               ‘precio’=>array(‘doc’=>’precio articulo’,
                                ‘input’=>array(‘codigo’=>’xsd:string’),
                             ‘output’=>’xsd:integer’)
                );
    var $complexTypes=array(
                ‘Array_Articulos’=>array(‘array’=>’MyArticulo’),
                ‘MyArticulo’=>array(‘struct’=>array(
                            ‘codigo’=>’xsd:string’,
                            ‘nombre’=>’xsd:string’,
                            ‘precio’=>’xsd:float’)),
                ‘Articulo’=>array(‘model’=>’Articulo’),
                ‘Articulo2’=>array(    ‘model’=>’Articulo’,
                                        ‘fields’=>array(‘codigo’,’nombre’,’precio_pvp’=>’precio’,’descripcion’))               
                );
                   
    function add($codigo,$nombre,$precio)
    {
        $data[‘Articulo’][‘codigo’]=$codigo;
        $data[‘Articulo’][‘nombre’]=$nombre;
        $data[‘Articulo’][‘precio_pvp’]=$precio;
        $this->Articulo->save($data);
    }
   
   
    /**
     * returns the price of one article
     */
    function precio($codigo)
    {       
        $data=$this->Articulo->findAll(“Articulo.codigo =’$codigo'”);
        if ($data)
        {
            return $data[0][‘Articulo’][‘precio_pvp’];
        }
        else
        {
            return new soap_fault(‘Client’,”,’Este artículo no existe.’,”);
        }
       
    }

    /**
     * retuns one array of custom struct type
     */   
    function browse()
    {
        $ret=array();
        $data=$this->Articulo->findAll();
        foreach ($data as $art)
        {
            $ret[]=array(‘codigo’=>$art[‘Articulo’][‘codigo’],
                                         ‘nombre’=>$art[‘Articulo’][‘nombre’],
                                         ‘precio’=>$art[‘Articulo’][‘precio_pvp’]);
                         
        }       
        return $ret;            
    }
   
    /**
     * return one element of model Articulo
     */
    function read($codigo)
    {
        $ret=array();
        $data=$this->Articulo->findAll(“Articulo.codigo=’$codigo'”,null,null,50,1,0);
        return $data[0][‘Articulo’];
    }   

    /**
     * return one element of model Articulo
     * (it will return only certain columns of it)
     * precio_pvp column is renamed to precio
     */
    function read2($codigo)
    {
        $ret=array();
        $data=$this->Articulo->findAll(“Articulo.codigo=’$codigo'”,null,null,50,1,0);
        $data[0][‘Articulo’][‘precio’]=$data[0][‘Articulo’][‘precio_pvp’];
        unset($data[0][‘Articulo’][‘precio_pvp’]);
        return $data[0][‘Articulo’];
    }   
       
}

?>

Web services in CakePHP – complex types February 17, 2006

Posted by rossoft in CakePHP.
12 comments

I’ve updated the 3 files referenced in the previous post. Now it is easy to pass arrays and structs.

Complete example of usage of server side:

vendor(‘nusoap/web_services_controller’);
class ArticulosServicesController extends WebServicesController
{
    var $name=’ArticulosServices’;
    var $uses=array(‘Articulo’,’Familia’);
   
    var $api=array(
            ‘add’=>array (    ‘doc’=>’agregar articulo’,
                            ‘input’=>array(‘codigo’=>’xsd:string’,
                                            ‘nombre’=>’xsd:string’,
                                            ‘precio’=>’xsd:float’)),
               ‘browse’=>array(‘doc’=>’precio articulo’,                                      
                             ‘output’=>array(‘return’=>’Array_Articulos’)),
                                           
               ‘precio’=>array(‘doc’=>’precio articulo’,
                                ‘input’=>array(‘codigo’=>’xsd:string’),
                             ‘output’=>array(‘return’=>’xsd:integer’))
                );
    var $complexTypes=array(
                ‘Array_Articulos’=>array(‘array’=>’Articulo’),
                ‘Articulo’=>array(‘struct’=>array(
                            ‘codigo’=>’xsd:string’,
                            ‘nombre’=>’xsd:string’,
                            ‘precio’=>’xsd:float’)));
                   
    function add($codigo,$nombre,$precio)
    {
        $data[‘Articulo’][‘codigo’]=$codigo;
        $data[‘Articulo’][‘nombre’]=$nombre;
        $data[‘Articulo’][‘precio_pvp’]=$precio;
        $this->Articulo->save($data);
    }
   
    function precio($codigo)
    {       
        $data=$this->Articulo->findAll(“Articulo.codigo =’$codigo'”);
        if ($data)
        {
            return $data[0][‘Articulo’][‘precio_pvp’];
        }
        else
        {
            return new soap_fault(‘Client’,”,’Este artículo no existe.’,”);
        }
       
    }
   
    function browse()
    {
        $ret=array();
        $data=$this->Articulo->findAll();
        foreach ($data as $art)
        {
            $ret[]=array(‘codigo’=>$art[‘Articulo’][‘codigo’],
                                         ‘nombre’=>$art[‘Articulo’][‘nombre’],
                                         ‘precio’=>$art[‘Articulo’][‘precio_pvp’]);
                         
        }       
        return $ret;            
    }   
}

?>

Webservices in CakePHP [other approach] February 16, 2006

Posted by rossoft in CakePHP.
29 comments

I was thinking other approach for webservices for having the code more clean and easier.

Installation
1. Copy this little hacked version of nusoap to /vendors/nusoap/nusoap.php
2. Copy this controller class to /vendors/nusoap/web_services_controller.php
3. Copy this component (nusoap client) to /app/controllers/components/soap.php

Usage
Developing a server

The services will be in the url http://myhost/customer_services/
(open that url in your browser for see the info of the webservice)

1. The controller

vendor(‘nusoap/web_services_controller’);
class CustomerServicesController extends WebServicesController
{
var $name=’CustomerServices’;
var $uses=array(‘Customer’);
var $api=array(
‘add’=>array (    ‘doc’=>’create a customer’,
‘input’=>array(‘code’=>’xsd:integer’,
‘name’=>’xsd:string’)),
‘name’=>array(‘doc’=>’gets the name of a customer’,
‘input’=>array(‘code’=>’xsd:integer’),
‘output’=>array(‘return’=>’xsd:string’)),
);
function add($code,$name)
{
$data[‘Customer’][‘id’] = $code;
$data[‘Customer’][‘name’] = $name;
$this->Customer->save($data);
}

function name($code)
{
$this->Customer->id=$code;
$data=$this->Customer->read();
return $data[0][‘Customer’][‘name’];
}
}
That’s all!

Developing a client

class TestController extends AppController
{
var $components=array(’aaa’,’bbb’,’soap’);

function test()
{
$url=”http://localhost/customer_services/”;
$func=’delete’;
$param=array(’code’=>’34′);
$name=$this->soap->client($url,$func,$param);
$this->set(’name’,$name); //for the view
}
}

Web services in CakePHP February 16, 2006

Posted by rossoft in CakePHP.
4 comments

I can’t wait to 1.0 for having web services and I started a simple soap component.

Installation
1. Copy this file to /app/controllers/components
2. Download nusoap library and put the file nusoap.php on /vendors/nusoap
3. Replace all the ocurrences of “soapclient” to “soap_client” on that file. This is for compatibility with PHP5, it has another soapclient class.

Usage
Developing a server

The service will be in the url http://myhost/test/get_info
(open that url in your browser for see the info of the webservice)

1. The controller

class TestController extends AppController
{
    var $components=array(‘aaa’,’bbb’,’soap’);
   
    function get_info()
    {
       $this->soap->service();
    }
}

2. The service.
With this line $this->soap->service() we’re telling the soap component to register the service at the file /app/controllers/soap_services/test/get_info.php , so we need to create that file:

global $api;
$api=array(    ‘doc’=>’Returns the price of the article’,
            ‘input’=>    array(‘code’=>’xsd:string’),
            ‘output’=>     array(‘return’=>’xsd:float’));
           
function get_info($code)
{
    global $controller;
            $data=$controller->Article->findAll(array(“‘Article.code’=’$code”));
    return $data[0][‘Article’][‘price’];
}           
?>
That’s all. The method can access the Test controller through the controller global variable. Then it can call a method of the model.
Important: the $api variable must be declared. It has a description of the method (‘doc’), the array of input values (‘input’) and the array of output values (‘output’).

Developing a client

class Test2Controller extends AppController
{
    var $components=array(‘aaa’,’bbb’,’soap’);
   
    function price()
    {
       $url=”http://localhost/test/get_info&#8221;;
       $func=’get_info’;
       $param=array(‘code’=>’W03921’);
       $price=$this->soap->client($url,$func,$param);
       $this->set(‘price’,$price);
    }
}
Then, create the view for this action and put on it

Final solution to checkbox problem February 14, 2006

Posted by rossoft in CakePHP.
9 comments

When you have a form with a checkbox, if you submit the form and the checkbox isn’t checked, then it doesn’t return anything.
In the wiki there is a good solution mixing javascript and hidden inputs.

I have improved this by overriding the tag in tags.ini.php, for doing something like this automatically without any change on your app code.
The tag is:

checkbox = "<input type="hidden" name="data[%1\$s][%2\$s]"  id="tag_hidden_%3\$s"/><input type="checkbox" id="tag_%3\$s"  onClick="change_%1\$s_%3\$s()" %4\$s /><script type="text/javascript">function change_%1\$s_%3\$s(){	hidden=document.getElementById('tag_hidden_%3\$s');	checkbox=document.getElementById('tag_%3\$s'); 	hidden.value=(checkbox.checked)? 1:0;} change_%1\$s_%3\$s();</script>"

Saving a model object on session vars February 13, 2006

Posted by rossoft in CakePHP.
3 comments

I am coding the typical cart application. One of the model classes are the cart itself. This class is a normal class, it doesn’t extends AppModel. That object is saved in the session.

When you save a instance of the class in the session there isn’t any problem; but for reading it from the session, you need to have defined the class of the object BEFORE of the call session_start(), if you don’t then you will get a incomplete php object (this is a simple array of it’s properties, you can’t call any of it’s methods).

CakePHP does the call session_start() before loading the classes, so you must do a little hack. A simple hack that seems to work (I don’t know if it has side effects) is to close and reopen the session every time you read a variable (I don’t know if this is too slow, but works…):

I have changed that to the component /app/controllers/components/session.php

function read($name = null)
{
session_write_close();
session_start();
return $this->CakeSession->readSessionVar($name);
}

IP Mask validator February 12, 2006

Posted by rossoft in CakePHP.
add a comment

Added to my validator vendor package more validators (IpValidator and NetmaskValidator)

Example of usage (read the phpdoc info on the source files for full doc):

$validate=array(
  'ip'=>array(
       array(VALID_NOT_EMPTY,'Not blank'),
       array(VALID_IP,'Not valid ip',array(true,'network','mask'))),
  'network'=>array(
       array(VALID_NOT_EMPTY,'Not blank'),
       array(VALID_IP,'Not valid ip network')),
  'network_mask'=>array(
       array(VALID_NOT_EMPTY,'Not blank'),
       array(VALID_NETMASK,'Not valid network mask',array(false))));

This will validate:

  • The network_mask field is a valid mask. It can’t be in the short format because the param is false. If the param is true, then the mask could be in the short format.
  • The network field is a valid ip (it’s in the form xxx.xxx.xxx.xxx)
  • The ip field is a valid ip AND is a ip within the range of the network indicated in the field ‘network’ with the mask indicated in the field ‘mask’. If the first param is false, then the 2nd and 3rd parameter are the values directly, nor fields that holds these values.

Custom validation credit card February 12, 2006

Posted by rossoft in CakePHP.
3 comments

A credit card custom class validator.
Usage:

$validate=array('creditcard'=>array(
array(	VALID_NOT_EMPTY,'Not blank'),
array(	VALID_CREDITCARD,'Invalid card',array(false,'Visa'))));

Explanation of the param: array(false,’Visa’)

the first element indicates if the second element is a field name (when is true) that holds the card type, or the cardtype directly (when is false).

Copy this to /vendors/validator/validators/creditcard.php

Override CSS for an specific action February 11, 2006

Posted by rossoft in CakePHP.
3 comments

Sometimes I have a view that I need to override CSS and I can’t change the .thtml (because I do something like scaffolding). So I have done a little snippet code for doing this.

If exists any of these files, then it will be referenced automatically by a link stylesheet tag:

  • /app/webroot/{controller_name}/css.css
  • /app/webroot/{controller_name}/ie.css ( referenced only for ie <=6)
  • /app/webroot/{controller_name}/{action_name}.css
  • /app/webroot/{controller_name}/{action_name}_ie.css ( referenced only for ie <=6)

Put this code snippet in your head section of your layout file:

<?php
$file=THEME . DS . Inflector::underscore($this->controller->name) . DS . 'css';
if (file_exists(CSS . $file . '.css'))
{
echo $html->css($file);
}

$file=THEME . DS . Inflector::underscore($this->controller->name) . DS . $this->controller->action;
if (file_exists(CSS . $file .'.css'))
{
echo $html->css($file);
}

$file=THEME . DS . Inflector::underscore($this->controller->name) . DS . 'ie';
if (file_exists(CSS . $file . '.css'))
{
echo '<!--[if lt IE 7]>';
echo $html->css($file);
echo '<![endif]-->';
}

$file=THEME . DS . Inflector::underscore($this->controller->name) . DS . $this->controller->action . '_ie';
if (file_exists(CSS . $file .'.css'))
{
echo '<!--[if lt IE 7]>';
echo $html->css($file);
echo '<![endif]-->';
}

?>