Yii Framework

jqAutocomplete Extension for Yii

0

It was only a matter of time until I try to develop an extension for the Yii Framework and I have chosen the Ajax Powered Autocomplet plugin for JQuery to exercise with this technology.

How to use the Extension

I have included a test within the downloadable package that shows how to implement this extension. The test includes a TestController, a view and a test_layout; so I hope this will easy the way for you to check it.

First download and unzip its contents

  • Move jqAutocomplete contents (I said contents) into your application’s protected/extension folder
  • Copy TestController.php and paste it in (you guessed well) your application’s protected/controllers folder
  • Move test folder (not the contents but the whole folder this time) into your application’s protected/views folder
  • Finally test_layout.php into your application’s protected/layouts folder

That’s it! Ready for the test. Go to your browser and type http://<replace_with_your_application_url>/index.php?r=test/autocomplete. If everything was good, you will be able to see the first field (JSON TEST) working as an autocomplete.

Please check TestController.php to see an example of AJAX response from the client autocomplete’s Request calls -and yes, you can also do it from a database result query. Look also at the test view’s code for an example on how to use the extension.

Download
** If you have problems to download from below; please try it here.

http://www.ramirezcobos.com/wp-content/plugins/downloads-manager/img/icons/default.gif download: Ajax Powered AutoComplete Extension for Yii (126.83KB)
added: 20/10/2010
clicks: 232

Tweet this!Tweet this!
PHPLib&Yii

How to use PhpTumb Library with Yii

7

I am currently working to build a real estate application with our beloved Yii Framework and, as you may guess, I had to manipulate tones of pictures [uploading and resizing]; in the past I used PHPThumb in my projects for those tasks due to its power and simplicity and that isn’t going to change now just because I use Yii.

For those who still don’t know what is PHPThumb I will take a text from its site that perfectly explains what is it:

PHP Thumb is a light-weight image manipulation library aimed at thumbnail generation. It features the ability to resize by width, height, and percentage, create custom crops, or square crops from the center, and rotate the image. You can also easily add custom functionality to the library through plugins. It also features the ability to perform multiple manipulations per instance (also known as chaining), without the need to save and re-initialize the class with every manipulation.

Installing

Yii allows us to use external libraries in very different ways due to its great flexibility, I just going to explain what I did:

a) download PHPThumb and unpack its contents under your Yii application’s protected folder [www/protected/extensions]. I rather use this folder than vendors or whatever; I like to keep things simpler and not to look in hundreds of folders for different things. You can place it wherever you wish.

b) create a new subfolder in the extensions folder with the name phpthumb and rename ThumbLib.inc.php to PhpThumbFactory.php

c) move the following files within the phpthumb folder: GdThumb.inc.php, PhpThumb.inc.php, ThumbBase.inc.php and also the folder and its contents thumb_plugins. You end up with a file structure like this:

Yii PHPThumbFactory file structure

Yii PHPThumbFactory file structure

d) Now we need to tweak one line of code in PhpThumbFactory.php

//******
// we need to change the following line [31]:
// define('THUMBLIB_BASE_PATH', dirname(__FILE__));
// onto
define('THUMBLIB_BASE_PATH', dirname(__FILE__) . '/phpthumb');

e) Now we open the main.php file of our Yii application, which is placed in the protected/config folder, and force to autoload our extensions [for the sake of simplicity I will use a wildcar, then you don't need to worry about preloading new extensions]

//
// autoloading model and component classes
'import'=>array(
     'application.models.*',
     'application.components.*',
     'application.extensions.*',  // <--- here!
),

Using our component

Everything is done and our library ready to use. Here I show you how I make use of it in my application:

/*
The following code is taken from a controller's action where
I first check if there is a post submission and the form posted
is of enctype multipart/form-data.
*/
//
// after checking if there was a post
// get and instance of the uploaded file
$picture_file = CUploadedFile::getInstance($model,'picture');
//
// i call a private function to create a unique filename
$picture_name = $this->createPictureName($picture_file->name);
//
// save the uploaded model attributes
$model->attributes = $_POST['Property'];
//
// this requires an update
$model->picture = $picture_name;
$model->save();
//
// now save a temporary file so to work with PHPThumb
// tmp folder is placed in protected/tmp and has
// write privileges
$tmpPicture = Yii::app()->getBasePath() .'/tmp/' . $picture_name;
//
// use CUploadedFile easy saveAs function
$picture_file->saveAs($tmpPicture);
//
// lets use now our PhpThumbLib
// create from temporary picture file
$thumbFactory = PhpThumbFactory::create($tmpPicture);
//
// resize the picture to 182, then crop it, and save it to
// www/images/properties/182x89 folder.
// this folder has read and write privileges
$thumbFactory->resize(182)
        ->cropFromCenter(182,89)
        ->save(Yii::getPathOfAlias('webroot.images.properties.182x89') .'/'.
        $picture_name);

Final Words

That piece of code is just an example from my own application. It is placed in a Controllers Create Action and is within a try, catch block statement. I assume that you know what I am talking as this small tutorial was for you to understand how to use external libraries other than those offered by Yii. Hope it helps you.

Tweet this!Tweet this!
open-source

Adding Content to an iFrame and Print its Contents

0

I was working on a project and I had to create a print friendly version of a bill and even though it sounds so easy to do, I had to face some browser problems. For some reason, that I couldn’t find, there was no universal solution to it -or at least I couldn’t find one that worked with every browser.

After breaking my head towards the wall and throwing some darts to Microsoft’s IE Browser poster I found one that worked.

function iPrint( contentToPrint )
{
	// I have a hidden IFRAME within the document called
        // pfiframe (if you try to use jQuery here fails
	var oIframe = document.getElementById('pfiframe');
        // get a reference to the document
	var oDoc = (oIframe.contentWindow || oIframe.contentDocument);
	if (oDoc.document) oDoc = oDoc.document;
        // now we write an entire HTML doc with the
        // contents we want to print in its body
	oDoc.write("<html><head><title>title</title>");
	oDoc.write("</head><body>");
       // check the function to print that we
       // include here
	oDoc.write( contentToPrint +
		"<script type='text/javascript'>function printIt(){window.print();return false}</" + "script></body></html>");
	oDoc.close();
       // again, I am not using jQuery here
       // for unknown reason, it fails to call
       // differently as it is here
	window.frames[0].printIt();
}

See? Easy right? Well I spent quite a lot of minutes to realize that! Hope this discovery help you guys out there.



Tweet this!Tweet this!
SimplaTable and SimplaPager working together

How to create a Custom Pagination Widget for Yii Framework

20

Yii FrameworkYii Framework is great, I truly like this framework, makes complicated things an easy task and its learning curve quite easy. But… yeah man, is always a but… what happens to all those fellow programmers, like me, that do not like the way ‘automated things’ are? Where are the tutorials to change and improve the framework and make it work just the way we like? There are not many around…

Again, a programmer needs to investigate the guts of the framework, in order to find out how to properly do it. But don’t worry, if you have a question in the format: would I be able to do this with Yii? The answer will be always positive. It is a great framework.

So, I would like to share with you guys my personal experience and put some small tutorials to ‘open’ the minds of others begginning with this framework. This will be the first of a set of small tuts on this Framework.

Creating a Custom Pagination Widget

A pagination Widget is the responsible of displaying a set of numbered links that lead to different pages of target. When you first create a Web application through the yiic tool – this tool creates the skeleton of the application, the automated CMS works with CLinkPager widget and its style and Page Links were not suitable for my project. My project had to end up making AJAX calls and its STYLE like the following picture:

Please not that if you want to just change its style, you can create a skin as exposed here: http://www.yiiframework.com/doc/guide/topics.theming#customizing-widgets-globally. Once I look at the code, I realized that creating a custom widget was easier than I thought. The first thing we need to do is to extend our new Widget class from CLinkPager, my class is named SimplaPager as I have used a template admin theme called SIMPLA.

class SimplaPager extends CLinkPager

Now, there are three methods to override from our father and grandfather classes (CLinkPager and CBasePager). The parent methods we need to override are run and createPageButtons and from our grandfather class createPageUrl.

a)  run Function

public function run()
{
     //
     // here we call our createPageButtons
     //
     $buttons=$this->createPageButtons();
     //
     // if there is nothing to display return
     if(empty($buttons))
          return;
     //
     // display the buttons
     //
     echo $this->header; // if any
     echo implode("&nbsp;",$buttons);
     echo $this->footer;  // if any
 }

b) createPageButton Function

/**
 * Creates a page button.
 * You may override this method to customize the page buttons.
 * @param string the text label for the button
 * @param integer the page number
 * @param string the CSS class for the page button. This could be 'page', 'first', 'last', 'next' or 'previous'.
 * @param boolean whether this page button is visible
 * @param boolean whether this page button is selected
 * @return string the generated button
 */
protected function createPageButton($label,$page,$class,$hidden,$selected)
{
       //
       // CSS_HIDDEN_PAGE and CSS_SELECTED_PAGE
       // are constants that we use to apply our styles
       //
	if($hidden || $selected)
		$class=' '.($hidden ? self::CSS_HIDDEN_PAGE : self::CSS_SELECTED_PAGE);
	$class .= ' number';
       //
       // here I write my custom link - site.call is a JS function that takes care of an AJAX call
       //
	return CHtml::link($label,'#',array(
                'class'=>$class,
                'onclick'=>"site.call(CONST_MAIN_LAYER,'{$this->createPageUrl($this->getController(),$page)}');"));
}

c) createPageUrl Function

/**
* Creates the URL suitable for pagination.
* This method is mainly called by pagers when creating URLs used to
* perform pagination. The default implementation is to call
* the controller's createUrl method with the page information.
* @param CController the controller that will create the actual URL
* @param integer the page that the URL should point to. This is a zero-based index.
* @return string the created URL
*/
public function createPageUrl($controller,$page)
{
    // HERE I USE POST AS I DO AJAX CALLS VIA POST NOT GET AS IT IS BY
    // DEFAULT ON YII
    $params=$this->getPages()->params===null ? $_POST : $this->getPages()->params;
    if($page>0) // page 0 is the default
       $params[$this->getPages()->pageVar]=$page+1;
   else
      unset($params[$this->getPages()->pageVar]);
   return $controller->createUrl($this->getPages()->route,$params);
}

Styling is controlled by a couple of constants in CLinkPager class, so the only thing we need to do is to override those constants.

const CSS_HIDDEN_PAGE='hidden';
const CSS_SELECTED_PAGE='current';

How to use the Widget

In order to use this widget first we create a widget subfolder in our application’s protected folder (in my case I saved a file named SimplaPager.php) and call it in our views like this:

$this->widget('application.widgets.SimplaPager', array(
    'pages'=>$pagination,
));

I have created another widget to display records in a table because I had the same problems than with the pagination so I use the the pagination within the Table Widget I created like this:

/**
 * @var array the configuration for the pager. Defaults to <code>array('class'=>'CLinkPager')</code>.
* @see enablePagination
 */
public $pager=array('class'=>'application.widgets.SimplaPager');

I promise I will discuss how to create a Table Widget in the next post :) . Nevertheless, you can view how both widgets look at the end:

SimplaTable and SimplaPager working together

DOWNLOAD

Please remember than this class has some AJAX calls in its createPageButton function that is exclusive for my project. Change that part to suit your needs. This class was for you to better understand how to create custom Widgets by extending those from Yii framework.



Tweet this!Tweet this!
create-professional-invoices-for-free-invoice-bubble

Invoice Bubble -Create Professional Invoices for Free

0

I have lately found a very interesting service for those who work as a freelance to create really cool invoices; it is called Invoice Bubble.  With this service, which is totally free (it inserts some ads that can be removed by paying a very low monthly fee $5 USD), you can create your own invoices, send them to your clients and get paid via Paypal.

It is quite good and has an excellent design; also, you can create recurring invoices and keep track of the payments from the control panel.

Tweet this!Tweet this!
Captura de pantalla 2010-09-12 a las 12.00.32

Less Framework 2

0

All of us know how hard is to get a proper CSS layout for our pages. Thanks to 960 grid system we developers were able to solve some of the issues that we face when we design for different browsers. Now, new devices coming aboard such as Android, iPhones, Blackberry’s and their browsers and the nightmare continues. Nevertheless, nice people like those of 960 grid system give away their approaches and solutions in order to make our life’s easier. Less Framework 2 comes to help us:

A CSS framework for cross-device layouts

Everyone writes CSS differently. Less Framework takes this into account by having a minimal set of features, and does away with things like predefined classes.

No more 960 px

Less Framework uses inline CSS3 media-queries to switch between three layouts:

  • a two-column layout at 320 px, for smartphones
  • a five-column layout at 768 px, for iPads and netbooks
  • and an eight-column layout at 1280 px, for desktops and laptops.

No hacks, unless you want them

Less Framework works beautifully in Firefox, Chrome, Safari, Opera, IE9 (hopefully), Android phones, and all iOS devices (that’s all iPhones, iPads, and iPod Touches). It even behaves nicely in landscape mode.

Tweet this!Tweet this!

Captura de pantalla 2010-07-12 a las 16.03.00

PalmStudios Model Agency

2

Hi there,

I would like to introduce you my last web project: http://www.palmstudios.com

For this project I have developed a sort of MVC (Model View Controller) over the RedBeanPHP DB library (PHP 5.3.2).  This project even though it looks quite simple it has a very power CMS (Content Management System) on its backend that allows the model agency to control most of the aspects of its business:

  1. - Clients Management
  2. - Models Management (Men, Women, Children & Extras) -contact details, measurements, pictures, and so on…
  3. - Promotional Packages Management – this is a special addon which allows the agency to create model promotional bundles to send to its clients

There is a ton of client and server libraries that this application makes use of, such as:

  • JQuery FancyBox
  • JQuery Livequery
  • JQuery AjaxQ
  • PHPMailer
  • RedBeanPHP
  • Savant3 Template Engine
  • PHPThumb
  • TinyMCE

The CMS has a configuration section where site administrator can configure:

  • Web site languages (has multiple language support)
  • Web site translations (you can even ask GOOGLE about a translation depending of the languages installed on the system)
  • Model properties (size, height, waist, etc…)
  • Hair Colors
  • Eye Colors
  • Users

Here is a snapshot gallery of the Site and its CMS

I am open for Freelance Jobs

If any of you would like to create a model agency application like this, let me know, I will be more than happy to collaborate with you on it. I will also sell the source code of its panel for any of you who is interested.



Tweet this!Tweet this!
Yii Framework

Yii Framework -Final Decision

2

I never felt comfortable with external libraries, those created by other people. Always, since my old times with Visual Basic, have created my own and until now, everything I created was good enough but… Suddenly, after I found that marvellous library called RedBean, I found my self re-programming all my libraries and end up creating a controller and a base model class for a sort of MVC library – I will post it one of these days so you guys can look at it and find out how easy is to implement that incredible library is (thanks Gabor de Mooij!) on your libraries.

But, as a programmer, I started to think that, even though my own libraries speed up my development processes, I want it to be hands on a bigger and more ambitious projects -that happened long time a go but never felt impressed by any library out there. My libraries lacked on scalable development architecture and had to find for a better solution for a much bigger project I am jumping right now. I google around and found interesting offers as exposed on one of my old posts:

Actually, far too many, so I took my time to decide for one to suit all my needs. Checked around and read some good articles about Yii framework and then, telling the truth, I was very impressed with (information taken from http://programmersnotes.info:

  • 100% OO architecture. It is really good application design.
  • Authentication & roles mechanism
  • Caching techniques
  • DB access, which is based on PDO
  • Active record and relational active record implementation
  • Validation – that is really, really nice. To create quite complex register form (check if login is unique, if email is unique, email match with confirmation, passwords match, validate integer/string values, check empty fields and give nice error messages for each field you need only template (view) and model with rules defined. It took me 10-15 mins to do that!)
  • Component concept. Just to give an idea, why is it nice – you can define getter and setter methods for properties, you can define read-only properties for components, define and invoke events, attach event handlers and additional features to the class without modifying it, just by attaching additional behaviour to it
  • Also, check its graphical benchmarking against other MVC frameworks http://www.yiiframework.com/performance.

Wondering whether DooPHP (claiming is the fastest at the moment) or Yii, I finally decided to use the latest due that DooPHP is quite new and Yii has a huge amount of features and tweaks that, even its documentation is not the best (I just read their Definitive Guide and I think I will have to read to a couple of hundreds articles more to be ‘good’ at it), I think at the end will become the Toolset for highly scalable projects -using its automation tool called Gii, I did the skeleton of a project in less than 30 seconds -duh!.

In addition. last but not least, you can integrate Zend components easily and jQuery is nativelly implemented -and I loooooove jQuery.

For the small ones I still like my own libraries though :)

Tweet this!Tweet this!
Picture-121-300x157

Speed Up Your Pages With Lazy Load JQuery Plugin

2

I would like to introduce you this simple but very efficient plugin that will help us speed up the downloading time of our web pages. I am talking about mr Mika Tuupola’s Lazy Load JQuery Plugin.

This plugin loads the images of a web page as the user scrolls to their position, that is, images wont load until they are not within the visible viewport margins of the window.

How to use

First we need to insert the following references into our code

<!-- insert a reference to jquery and the jquery.lazyload plugin -->
<script src="jquery.js" type="text/javascript"></script>
<script src="jquery.lazyload.js" type="text/javascript"></script>

And now this few lines of code in our document.ready function

<script type="text/javascript">
$(function() {
          $("img").lazyload({
              placeholder : "img/grey.gif",
              effect      : "fadeIn"
           });
       });
< /script>

And that’s it! Easy right?

Tweet this!Tweet this!
open-source

Uri Class for PHP

0

For years, we developers tend to keep functions that we find useful into our projects, after certain time they become obsolete or you move one to higher level ways of programming. Some of us, can’t get rid of the code that was once collected-created and I thought let’s see if I post one of my silly old classes what can we get out of it? Let’s make it open source hahahaha.

I propose you the following: Here is my small old good set of Uri PHP functions encapsulated into one class, I know is not a great deal but, let’s see what can we all do with it. For every programmer that posts a function, I will write his reference into the class and post his/her site link in this post.

There are certain rules though:

  1. Functions cannot be greater than 20 lines of code
  2. Functions cannot depend of far too many external components (maximum one)
  3. If functions depend of an external component/class, a URL indicating its reference must be provided
  4. Functions are not to be repetitive, if there is one better written that the ones exposes we will replace it

The Uri Class

Here is my class:

<?php
/**
 * @author Antonio Ramirez <contactme@atmyblog.com>
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @link http://www.ramirezcobos.com/
 *
 *
 */
class Uri
{
	/**
	 * Encodes the parameter to hide
	 * its contents to user
	 *
	 * @param string $val
	 */
	function uriEncode($val)
	{
		return rawurlencode(base64_encode($val));
	}
	/**
	 * Decodes a parameter string that
	 * was previously encoded with uriEncode
	 * function
	 *
	 * @param string $val
	 */
	function uriDecode($val){
		return base64_decode(rawurldecode($val));
	}
	/**
	 * Translates a given url to
	 * tinyurl version -curl required
	 *
	 * @param string $url
	 * @access public
	 * @return string $data
	 */
	function getTinyUrl($url){
		$ch = curl_init();
		$timeout = 5;
		curl_setopt($ch,CURLOPT_URL,'http://tinyurl.com/api-create.php?url='.$url);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
		$data = curl_exec($ch);
		curl_close($ch);
		return $data;
	}
	/**
	 * Translates a given url to
	 * ToLyUrl version -curl required
	 *
	 * @param string $url
	 * @access public
	 * @return string $data
	 */
	function getToLyUrl($url){
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, 'http://to.ly/api.php?longurl='.urlencode($url));
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		$data = curl_exec ($ch);
		curl_close ($ch);
		return $data;
	}
	/**
     * Gets Request param
     *
     * @param string $paramName
     * @param string $slash
     * @access public
     * @return string $param or boolean $false
     */
	function getParam($paramName, $slash=false)
	{
		return (isset($_REQUEST[$paramName])?($slash?addslashes($_REQUEST[$paramName]):$_REQUEST[$paramName]):false);
	}
	/**
     * Serializes Request params
     *
     * @param string $notThisOne
     * @access public
     * @return string $query_string
     */
	function getParams($notThisOne=false)
  	{
		global $REQUEST_METHOD, $HTTP_GET_VARS, $HTTP_POST_VARS;
		$query_string='';
		if (strpos($_SERVER['REQUEST_URI'],"?"))
		{
			list($fullfile, $voided) = explode("?", $_SERVER['REQUEST_URI']);
			$cgi = $_SERVER['REQUEST_METHOD'] == 'GET' ? $HTTP_GET_VARS : $HTTP_POST_VARS;
			reset ($cgi);
			while (list($key, $value) = each($cgi)) {
			  if ($key != $notThisOne)
				$query_string .= "&" . $key . "=" . $value;
			}
		}
		return $query_string;
  	}
	/**
     * Makes a Soap Call
     *
     * @param string $uri
     * @param string $command
     * @param string $xml
     * @access public
     * @return string $response
     *
     * Requires Soap
     */
	function makeSoapCall($uri,$command,$xml)
	{
		try{
			ini_set('default_socket_timeout',10); // ten seconds, that is all we wait
			$client = new SoapClient($uri,array("connection_timeout"=>10));
			$response =  $client->__soapCall($command,array(new SoapParam($xml,'Peticion')));
		}
		catch(Exception $e){
			$response = false;
		}
		return $response;
	}
	/**
	 * Parses a given $url for validation
	 *
	 * @param string $url
	 * @access public
	 * @return $parsed_url
	 */
	function getParsedUrl($url)
	{
		$parsed_url = parse_url($url);
		if (!isset($parsed_url['scheme']) or $parsed_url['scheme'] != 'http'){
			echo 'Unsupported URL sheme given, please just use "HTTP".';
			exit();
		}
		if (!isset($parsed_url['host']) or $parsed_url['host'] == ''){
			echo 'Invalid URL given!';
			exit();
		}
		$host = $parsed_url['host'];
		$host .= (isset($parsed_url['port']) and  !empty($parsed_url['port'])) ? ':'.$parsed_url['port'] : '';
		$path = (isset($parsed_url['path']) and  !empty($parsed_url['path'])) ? $parsed_url['path'] : '/';
		$path .= (isset($parsed_url['query']) and  !empty($parsed_url['query'])) ? '?'.$parsed_url['query'] : '';
		return 'http://' . $host . $path;
	}
	/**
     * Requests a Url and returns its contents
     *
     * @param string $url
     * @access public
     * @return string $query_string
     * @uses Snoopy class http://sourceforge.net/projects/snoopy/
     */
	function getUrlContent($url)
	{
		App::import('component','snoopy');
		$url = Uri::getParsedUrl($url);
		$snoopy = new Snoopy();
		$snoopy->agent = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; es-ES; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12';
		$snoopy->referer = '';
		$results = false;
		if($snoopy->fetch($url)){
			$results = $snoopy->results;
			// empty buffer:
			$snoopy->results = '';
		}
		return $results;
	}
}
?>
Tweet this!Tweet this!
Go to Top