Udi Mosayev

Programming, Business and my thoughts..

Archive for the ‘Web Development’ Category

New PHP Book: Expert PHP 5 Tools by Dirk Merkel

Recently I came across Expert PHP 5 Tools from Packt Publishing, and I’m getting the review copy very soon.

By the information written in Packt’s book page, I see that the book is about all the surrounding of PHP. The IDE, the server, documenting tools and etc.

I haven’t read the book yet, but I don’t think you really need to be an expert to use the tools, its more then enough to have some experience, at least write few web applications with PHP.

I can’t wait to read the book, I really want to read about “Deploying Applications” and “Continuous Integration”, of course I’ll review the book for you.

You can find more information here: Expert PHP 5 Tools and the Table of Contents here.


View Comments

Written by Udi Mosayev

June 27th, 2010 at 5:49 pm

Posted in General Talk,PHP,Web Development

Tagged with ,

My experience with CloudIgniter

Recently I got an opportunity to use CloudIgniter – Codeigniter Hosting, with your own database and ftp account.
In my account I can have 3 domains, I’ve added the first one: helloworld.co.il and I have few options:

  • Platform – CodeIgniter 1.7.2, CodeIgniter 2.0 beta
  • Application – Different versions of PyroCMS and MyClientBase.

I chose PyroCMS.

What it does, is installing the application on your account, in your Database, and login info to Pyro are automatically the login info to your CloudIgniter account and you can start working.

I’m located in Israel, and I have my experience with hosting servers outside Israel and most of them [Dreamhost for example] are nightmare for me, the FTP connection specially. But CloudIgniter servers are quite good, not as fast as Israeli servers I’m working on but their good [considering the distance].

The CloudIgniter admin panel is very simple to understand and navigate, you can find very simple Domain Management [with all the info you need], Usage information, setup Google Apps account for emails, and account settings.

To sum it up:

  • You have FTP account, Database, phpMyAdmin – everything you need.
  • Can manage more then 1 domain, I believe it will be part of their business plan. Each domain can be different CI installation/application.
  • There’s a backup plan, I don’t know which – but if you change the CI installation for certain domain it backups the old one.
  • Usage information – not full detailed, but good enough.
  • Clean and simple Admin Panel design.

CloudIgniter is at beta phase, you can go to CloudIgniter and ask for beta slot.

Good luck!


View Comments

Written by Udi Mosayev

May 29th, 2010 at 2:38 pm

MY_Model in CodeIgniter

Hi,

I wanted to share with you MY_Model I’ve written and use for most of my CodeIgniter apps.

/**
 * This is the basic model class.
 *
 * @package - Infrastructure
 * @category - Model
 * @author - Udi Mosayev @ umNet
 * @link - udi.mosayev@gmail.com
 * @since - Version 1.0
 */
class MY_Model extends CI_Model {

	// The main table name
	public $table;

	private $modelName;

	public function MY_Model() {
		parent::CI_Model();
		$this->table = '';
		$this->modelName = __CLASS__;
	}

	// Log as Error each time nonexisting method called.
	public function __call($name, $arguments) {
		$args = implode(',',$arguments);
		$this->log('error', $name.'('.$args.') Not exists');
		return FALSE;
	}

	/**
	 * Logs an error
	 * @param String $level
	 * @param String $msg
	 */
	protected function log($level, $msg) {
		log_message($level, __CLASS__.'->'.__METHOD__.' :: '.$msg.' | In: '.__FILE__.' Line: '.__LINE__);
	}
	/**
	 * This method inserts some array of data into the db
	 * @param Array $data
	 */
	public function save($data) {
		if(is_array($data)) {
			$this->db->insert($this->table, $data);
			return $this->db->insert_id();
		} else {
			$this->log('error', 'got non-array param.');
			return FALSE;
		}
	}

	/**
	 * This method updates fields in my table.
	 * @param String $fieldName
	 * @param String $value
	 * @param Integer $RowID
	 */
	public function updateField($fieldName, $fieldValue, $rowID) {
		if(empty($fieldName)) {
			$this->log('error', 'got empty fieldName');
			return FALSE;
		}
		else if(empty($fieldValue)) {
			$this->log('error','got empty fieldValue');
			return FALSE;
		}
		else if(!is_numeric($rowID)) {
			$this->log('error', 'got non-numeric RowID: '.$rowID);
			return FALSE;
		} else {
			// Wrtite the old&new data to history.
			$this->history->write($this->table, $rowID, $fieldName, $fieldValue);

			$this->db->where('ID', $rowID);
			$this->db->update($this->table, array($fieldName => $fieldValue));

			return TRUE;
		}
	}

	/**
	 * Updates whole row [unlike updateFIeld()]
	 * @param Array $RowData
	 * @param Integer $RowID
	 */
	public function update($RowData, $RowID) {

		if(!is_array($RowData)) {
			$this->log('error', 'supposed to get an array!');
			return FALSE;
		} else if(!is_numeric($RowID)) {
			$this->log('error', 'got non-numeric RowID: '.$RowID);
			return FALSE;
		} else {
			// write the old&new data to history
			foreach($RowData as $fieldName=>$fieldValue) {
				log_message('debug', 'Running history->write() with: history->write('.$this->table.', '.$RowID.', '.$fieldName.', '.$fieldValue.')');
				$this->history->write($this->table, $RowID, $fieldName, $fieldValue);
			}

			$this->db->where('ID', $RowID);
			$this->db->update($this->table, $RowData);
		}
	}

	/**
	 * This method returns all the rows of this model
	 * @param Array $where
	 */
	public function getWhere($where = "") {
		// if not array, then assign defaultive array for where clause
		if(!is_array($where)) $where = array('IsDeleted' => 0);
		$query = $this->db->get_where($this->table, $where);

		return $query;
	}

	/**
	 * This method gets 1 row from a table and returns it.
	 * @param Integer $RowID
	 */
	public function get($RowID) {
		if(!is_numeric($RowID)) {
			$this->log('error', 'Did NOT got a numeric RowID.');
			return FALSE;
		} else {
			$query = $this->db->get_where($this->table, array('ID' => $RowID));
			return $query;
		}
	}

	public function delete($RowID) {
		if(is_numeric($RowID)) {
			$this->updateField('IsDeleted', 1, $RowID);
			return TRUE;
		} else {
			return FALSE;
		}
	}
}

/* End of file MY_Model.php*/
/* Location: ./application/model/MY_Model.php */

I need to explain few things:

  • I use logical delete, I have field called IsDeleted its TINYINT, and if I want to delete certain row I update its value to 1. This method has lots of benefits which I can’t discuss now.
  • I use two “read” methods, get() and getWhere(), I KNOW that get() should use getWhere inside, but I don’t really have the time for this little fix :P
  • This class rewritten for CodeIgniter 2.0, so that’s why I extend CI_Model, if you’re using CodeIgniter 1.7 just write Model instead.
  • In each app I add more methods, methods that I need in all my models, or at least in some of them. For example a method that re-orders the item in the table.

Ask any thing you want, I’ll be happy to help.

UPDATE:

In line 98 you see this:

$this->history->write($this->table, $RowID, $fieldName, $fieldValue);

if you remember, I wrote about System Restore feature in Must Have Features in you CMS, this is my implementation for this feature. Thank you Zack for noticing!


View Comments

Written by Udi Mosayev

May 17th, 2010 at 5:55 pm

Database Interaction with Codeigniter 1.7

Hi,

Yesterday I wrote about the new CodeIgniter book: CodeIgniter 1.7 Professional Development By Adam Griffiths.
Packt Publishing extracted an article from the book, “Database Interaction with Codeigniter 1.7” which can be very helpful for beginners. You’ll read about the Database class, ActiveRecord and Database Forge class that gives you few methods to perform different [not so casual] operations in your database.

I really recommend you to not use ActiveRecord if you’re not familiar with SQL. If you’ll use ActiveRecord from day 1, you wouldn’t really know whats happening under the hood. My opinion is the same about PHP frameworks, I don’t think its good idea to start working with a framework before you know the language good enough.
Although not using ActiveRecord you won’t enjoy the security of injections-free queries and multiple DB types support – but in the long run its better for you as web developer.

Moreover, consider extending the native Model and writing simple CRUD [Create/Read/Update/Delete] methods that can help you working faster and better. I promise I’ll write about it more, I wrote for my self a quite powerful MY_Model class.

This is it for now,
If you already got the book, share your thoughts with me.


View Comments

Written by Udi Mosayev

May 15th, 2010 at 7:17 pm

Continuous Deployment

I started to hear a lot about continuous deployment, which means to deploy every piece of code you commit right away. But what I found more interesting to me is the strong infrastructure needed in order to do that.

Eric Ries wrote “Continuous deployment in 5 easy steps” and I really liked the idea of automated tests tool and deployment script.
I also read “Deployment Infrastructure for Continuous Deployment” and saw the Deployment tool kaChing developers created.

I’ll keep reading about this subject and think how can I create useful tool with Codeigniter which will help CI developers test their application and deploy the code.
For the beginning I’ll start with simple deployment, connecting to FTP and uploading modified files.

You can read more about Continuous Deployment here


View Comments

Written by Udi Mosayev

May 7th, 2010 at 4:42 pm

Posted in CodeIgniter,PHP,Web Development

Tagged with

“If I let users steer product decisions, the result would be a massive codebase producing a bloated, cluttered product full of features that hardly anyone used at the expense of everyday usability and polish on the features that matter. Like Microsoft Word. Or Firefox.”

Marco Arment


View Comments

Written by Udi Mosayev

April 24th, 2010 at 6:09 pm

Book Review: Expert PHP and MySQL

Hi!

I got for my birthday the new book from Wrox – Expert PHP and MySQL by Andrew Curioso, Ronald Bradford and Patrick Galbraith.

“This book examines some of the technologies and techniques needed to make robust and scalable applications perform in today’s high-demand world” (From the Introduction of the book..).

In this book you can learn about:

  • Advanced MySQL concepts [Stored Procedures, different drivers and Storage Engines, Views, Triggers, Replications]
  • PHP Opcode Cache with APC or eAccelerator
  • PHP Caching techniques – Memcached
  • Multi Tasking in PHP and MySQL with Gearman
  • and more…

This book is for developers who had worked on several projects and have some good experience developing with PHP and MySQL and developers whom develop high-demand applications, or applications that handles lots of data and processing. OOP experience recommended.

What I really enjoyed reading in this book is about

  • Gearman – a tool you install in you server and assign jobs [from your client] to those job server. For example – creating thumbnails of the photos your users upload, the thumbnail process done by different server [has Gearman installed and maybe even better for this kind of job] and this allows you to reduce the load on your client server (= faster application).
  • Memcached – Memcached is a “High-performance distributed memory objects caching system”, it provides key=>value cache for your applications to reduce the load on your database. Basically, in uses the free memory in your server and uses this to cache objects of your application. its really simple to work with Memcached and it has lots of performance benefits.
  • APC/eAccelerator – Each time you run php script the PHP compiler compiles your code again and again. In production environment the code isn’t changing that much, APC and eAccelerator [different tools] allows you to cache the compiled code, this way the server isn’t compiling the same code again and you get better performance. In PHP6 will have APC extension natively.

The techniques discussed in this book used by large sites we all know: Digg, Yahoo, Facebook, YouTube and more.. if its good for them I believe its good for you too :D


View Comments

Written by Udi Mosayev

April 23rd, 2010 at 2:03 pm

CodeIgniter 2.0

Hi,

EllisLab recently wrote about CodeIgniter 2.0 Baking and some other cool news. So yes, CodeIgniter 2.0 is in development right now and you can follow their process through BitBucket.

I won’t write the new cool features we already can see in CI 2.0-dev, because other great guys already done it, so I collected all the interesting posts from several developers about CI 2.0, enjoy:

Elliot Haughin – CodeIgniter 2.0 In Progress – The Critical Changes, Implications, and What You Should Know

Phil Sturgeon – CodeIgniter 2.0: Everything you need to know

Michael Wales – CodeIgniter 2.0 and Mercurial Transition

Personally, I’m really excited about this. Some of the features are very very important to me [like the packages for example] and I can’t wait for this version release.

CodeIgniter 2.0 Bakin


View Comments

Written by Udi Mosayev

March 13th, 2010 at 3:10 pm

Lessons I’ve learned working with Flash File Uploaders

For the last two weeks I’ve worked with two Flash File Uploaders:

I this post I’ll describe the problems I had with it and how I solved them.

Lesson 1: NO COOKIES

If you add the uploader to authentication based application you might see no files actually got uploaded.

Why is that? your/clients cookies are not recognizable with the Flash Uploader, so the uploader is like every other intruder that need to perform a login.
How I found out? Luckily I used Fiddler2 [more about it later] and the error/debug messages logging system I had helped me to find out what went wrong.
Solution? All modern uploaders support custom post data, so you can use it for session tokens or PHPSSID.

Lesson 2: Upload URL isn’t Found?

On my old development server I had the strangest problem ever – the existing-not-authenticated url that uploads the files was not found by the script.
I’ve activated Fiddler2 and saw that the response headers were 302 – not found. My logging messages showed me that no one accessed the url.

Why is that? In my case the problem was in my old development server provider – they have some mechanism that filters requests for some reason.
How I found out? This is the place to thank Fiddler2 – Fiddler2 is a HTTP monitoring software and FireFox addon that.. monitors HTTP requests. With Fiddler2 I saw the response headers and after few tryouts I’ve got as a response an abuse page of my server provider.
Solution? I contacted my server provider and they did what they had to in order for my uploader to work.

Lesson 3: Don’t be rude to Mac

Meanwhile, I switched the flash uploader and start using SWFUpload which is much much better in my opinion.
My upload script contains photo resizing and uploading to a distant server. Every special event is logged, every suspicious action is logged.
The nature of those flash uploaders is uploading the file, and then they reach 100% – but no Complete event because my script running now the resizing stuff.When the script finished, the uploader moved to the next file in queue, but for Mac users, even after the resizing, the file never got the “Complete” event.

Why is that? As I said, every little even in the upload process is logged, if something bad happens I know how to handle it. I didn’t echo/print any response, because I don’t need to, but Mac have to get some kind of response in order to move on. Its not clear to me why, but that’s the way it works.
How I Found Out?
really, just searched the web.
Solution?
just echo something..it might be useful if you wish to return event to the uploader and let him handle it.


View Comments

Written by Udi Mosayev

February 8th, 2010 at 1:21 am

Developing Content Managment System with CodeIgniter – Part 3

Hi.
Well, As my development process continues I would like to write you about the features and structure of my application now.

I’ve talked about the basics in my previous posts, I covered the structure of my application [modules], I showed you how I extend CI_Controller and CI_Model. Now I want to share with you the which features I have in my application that makes my live easier AND how I extended Controller and Model even more.

Features

    1. I Followed Phil Sturgeon’s How-To article for Support multiple production environments in CodeIgniter. This way I defined what to log and where, in what level, and the url’s of the local server, development server and production server [and Databases too].
    2. I’ve extended CI_Log class so its sending me email if some Error happens in PRODUCTION server [this is the application that the client is using].
    This way I can easily know what went wrong when I get the phone call from my client.
    3. History Class -> I wrote you in my Must have features in your CMS post about System Restore. So I wrote a simple model that has this method in it:
	/**
	 * This method writes data to history.
	 * @param String $table
	 * @param Integer $row
	 * @param String $field
	 * @param String $oldValue
	 * @param String $newValue
	 */
	public function write($table,$row, $field, $newValue) {

		// select only the field I need
		$this->db->select($field);
		// get the right row
		$data = $this->db->get_where($table, array('ID' => $row));
		// take the row and break to array
		$currentState = $data->row_array();
		// store the old value
		$oldValue = $currentState[$field];

		if($oldValue != $newValue) {
			$history = array(
				'TableName' => $table,
				'RowIndex' => $row,
				'FieldName' => $field,
				'OldValue' => $oldValue,
				'NewValue' => $newValue,
				'Created' => time()
			);
			$this->db->insert('history', $history);
			return TRUE;
		} else {
			return FALSE;
		}
	}

*I already see a mistake in this method – I have $this->table property in each model, and I don’t use it here – I write the table name directly in the insert method.*
This method activates before each update() method in my Models. The update() method written once in my MY_Model class, so I don’t really writing data to this “system restore” table myself [by calling this method each time] – everything happens in the background.

Extended CI_Controller

Well, I can’t share with you the whole code [I'm not allowed, I'll share certain methods], But I can write you the properties and methods I have and the purpose of them.

	// Module name. gallery/cart/content/contact/users...
	protected $module;

	// Basic authentication and permission system, UserLevel gets the
	// minimum level needed to enter this controller
	protected $userLevel;

	// The name of the controller
	protected $controllerName;

	public function MY_Controller() {
		parent::Controller();
		if(ENV == 'dev' OR ENV == 'local') $this->output->enable_profiler(TRUE);
		else if(ENV == 'live') $this->output->enable_profiler(FALSE);
		$this->controllerName = get_class($this);
	}

As you can see, If its a development environment I’m enabling the profiler, I use controllerName for better logging [knowing where error happened or any other message level].

I also have 2 methods that are loading views and models:

	/**
	 * This method is a shortcut for loading a view in my controllers.
	 * @param String $name The name of the view I want to load, inside the module folder.
	 * @param Text $content The HTML content I want the view to show.
	 * @param Bool $return Return the view content, or just show it?
	 */
	protected function _view($name, $content, $return = FALSE) {
		return $this->load->view($this->module.'/'.$name, $content, $return);
	}

The reason I did it is that I got tired writing

$this->load->view($this->module.'/viewName', '', TRUE)

And the current method really saves some time.

Extended CI_Model

	// The main table name
	public $table;
	private $modelName;

	public function MY_Model() {
		parent::Model();
		$this->table = '';
		$this->modelName = get_class($this);
	}

	// Log as Error each time none-existing method called.
	public function __call($name, $arguments) {
		$args = implode(',',$arguments);
		log_message('error', $this->modelName.'-> '.$name.'('.$args.') Not exists.');
		return FALSE;
	}

Well, everything is clear here I believe. I think that most of the developers don’t use __call method, but the use I did here is pretty useful.
Each method I have in the models and ofcourse MY_Model using $this->modelName for logging errors – if I didn’t got any $ID for updating some row its highly important for me to know why and where.

Well, I shared with you as much as I could. I don’t know if I’ll write another post in this area, I’ll see how my project goes and if there is something interesting to write about.

I really think I chose the wrong title for this post series :D but that’s ok.

Hope you learned something new, if you have any questions I’ll be happy to answer.


View Comments

Written by Udi Mosayev

January 1st, 2010 at 10:00 pm