Zend Framework and the future of PHP

I always saw PHP as a great language, is really easy to learn, it adapts itself to many levels of coders from total beginners coming from HTML to consummated developers creating advanced frameworks and huge applications, even better the final results are fast running applications that you can deploy in pretty much any hosting service.

PHP is not anymore a new cool proposal but a well established language and as I’m studying Python and RoR I can help but comparing and wondering about the future of the language specially now that I see so many applications based on the Zend framework.

While I love the new functionality in the Zend framework I’m not sure if that’s a step forward or backwards, it seems to tell the world: “thanks for all this years developing code on PHP but you guys haven’t done anything useful yet so now we will come with our advanced Java style coded classes to fill the huge gaps this language has.”

Does PHP lacks a collaborative community capable of really making the language evolve or complementing it?

How’s possible that other languages have now high quality, fully integrated and tested modules to do pretty much everything? Need to connect to Facebook, use a special service, parse data? There’s a package for it, there’s a way to downloading and install it.

The community have put a unified effort in making the languages powerful and complete, as a result developing in those languages is now faster than doing it on PHP and startups and companies looking for Agile style development are opting for those languages.

What happened to Pear? Where are those PHP well coded and tested classes that we all can use to work better and faster?

Why not betting for simplicity?

Zend framework seems to be trying to move PHP to a more complicated Java coding style instead of following the recent trend of super easy languages.

Don’t get me wrong in here I love Java and I know that thanks to Android is more alive than ever, still I wouldn’t recommend it for nearly any company or project over any other technology.

Why? Takes longer to develop, there’s no many qualified people around and the final results are not much better in comparison to other technologies (if they are at all).

So why is Zend using a coding style that makes PHP more inaccessible instead of trying to go for simple, intuitive and powerful ala Ruby or Python? Why not at least keep the PHP tradition of offering powerful functionality encapsulated in simple functions?

Is this the end of lightweight applications?

I remember how much I use to like Visual Basic 5-6, clean, easy, powerful and lightweight, once compiled you got a 200-300k application that you could use in pretty much any windows machine, it was awesome! Then .Net came and the applications become huge you either bundled the .Net framework with the installer or you were not sure that your application will run in your target computer.

PHP applications also use to be so light! You could get great applications in a couple of megabytes but now that’s gone, by the time you finish bundling the Zend framework your application is 35-40 megabytes, ridiculous! Sure you can just write it as a requirement or try to minimize the classes you need but at the end you’ll end up with a huge upload.

Conclusion

Certainly no one is obliged to use any classes or framework and it will be crazy to deny that the framework comes with really good functionality, but couldn’t it have been done in a more PHP’ish way?

And do we really need Zend to come to ‘save us’? Is it true that no valuable code ‘as good as’ was created before to fulfill those needs?

  • If it wasn’t it’s quite sad and perhaps it’s time to look for brighter horizons where smart coders exists (I don’t think so)
  • If it was it’s also sad that the community and the PHP makers didn’t find a way to canalize all that energy in an organized way so that we all could now enjoy¬† better ways to build even greater things on top.

Perhaps I’m getting all wrong but I keep getting this feeling that years and years of great coders work have been lost and that Zend framework recent efforts are going against their base users, the ones that like a simple powerful language to deliver good results.

Searching strings in a database and files

I always find cumbersome to work or maintain someone else systems, to make a small changes you normally lose hours trying to find out where that little string or that link that you have to modify.

Searching in files

For searching in files you can sometimes download all the site and simply use netbeans or other tool to search in files.

If you are lucky and you are in Linux you can SSH to the server and use the system tools. Check this fantastic link on how to do it

http://www.liamdelahunty.com/tips/linux_find_string_files.php

Searching in the database

Now what happens when you discover that what you are looking for is contained in the database?

Sometimes you can just browse the database content or dump the database and search as file but this can be hard with big databases.

So I decided for a very simple solution, create a PHP script that will check for a string in every available string field in all tables.¬† It will echo the name of the tables that have matches or you can go further and echo the ID’s or even further and echo the whole content of the row.

Hope someone else find it useful!

(This script is v.0.2, I updated after Andrew commented on the wrong sql construction) Please let me know of you find bugs.

<?php
/**
* Simple tool to search in a mysql database in all string fields
*
* Browse to search.php?term=yourterm[detailed=1/2]
* searchdb.php?action=search&term=yourterm[&detailed=1/2][&in=table1,table2,...][&notin=table1,table2,...]
*
* To use this class set $dbase to the database you want to use, 
* You might also need to modify line 70 to enter your own server info
* (I left that info hardcoded as it failed to use this info using variables in one server)
*
* If you need it, would be easy to add a web interface, just create one field for every parameter and send the form via GET or change the safeget function to read the POST or REQUEST var instead 
*
* Please let me know of any errors
*
* @author itzco 
* @version 0.2
*/

error_reporting(E_ALL);
set_time_limit(120);
// 1) SET YOUR DB NAME HERE
$dbase = 'yourdbnamehere';

if (empty($_GET)) {
    echo "Please enter a method (or action=help)";
    die();
}

echo "<pre>";
$method =safeget('action');


switch($method) {
    case 'getdbpwd':
    // This method to get the user/pwd when it's set in php.ini
        $hk = new db();
        $tmp = $hk->getdata();
        echo 'User: '.$tmp['user'].'Pwd:'. $tmp['pwd'];
        break;
    case 'search':
        $finder = new dbsearch($dbase);
        $finder->exclude(safeget('notin'));
        $finder->useonly(safeget('in'));
        $finder->find(safeget('term'),safeget('detailed'));
        break;
    case 'help':

        echo "<br>Methods:getdbpwd/search<p>getdbpwd<br>?action=getdbpwd&domain=xxx.domain.nl</p>";
        echo "<p>search<br>?action=search&term=<i>yourterm</i>[&detailed=1/2][&in=table1,table2,...][&notin=table1,table2,...]</p>";
        echo "<p>While in/notin are not mutually exclusive setting one is enough";
        break;
}
function safeget($key,$default=false)
{
    return isset($_GET[$key]) ? $_GET[$key] : $default;
}

class db {
    private $link;
    public function getdata() {
        return array('user'=>ini_get('mysql.default_user'), 'pwd' =>ini_get('mysql.default_password'));

    }
    public function connect($dbase)
    {
        $user = ini_get('mysql.default_user');
        $pwd  = ini_get('mysql.default_password');
        if ($user & $pwd)
        {
           $this->link = @mysql_connect();
        }
        else
        {
            echo  '<br>Warning: ini_get user and pwd are not set';
            // 2) Enter here your user pwd and server if required
            $this->link = @mysql_connect('localhost', 'root', 'root');
        }
        if ($this->link === FALSE)
    {
            die ('Not able to connect to the database');
        }
    else
    {
            $db_selected = mysql_select_db ($dbase, $this->link);
            if (!$db_selected) {
                die ('Can\'t use database : ' . mysql_error());
            }
    }

    }
    function query($query)
    {

        if (false === ($this->res = mysql_query($query, $this->link))) {
            echo sprintf('MySQL error #%d: %s.', mysql_errno(), mysql_error());
        } else {
            $this->error = null;
            $result = array();
            while ($row = mysql_fetch_assoc($this->res)) {
                $result[] = $row;
            }
            return $result;
        }
    }
}



class dbsearch
{
    private $db;
    private $targettypes = array('varchar','char','text','tinytext','mediumtext');
    private $dbname;
    private $include=array();
    private $exclude=array();
    public function __construct($dbase)
    {
        $this->db = new db();
        $this->db->connect($dbase);
        $this->dbname = $dbase;
    }
    public function exclude($tables)
    {
        if (!$tables) return;
        $this->exclude = explode(',',$tables);
    }
    public function useonly($tables)
    {
        if (!$tables) return;
        $this->include = explode(',',$tables);
    }
    public function find($string, $detailed=false)
    {
        if (!$string || strlen($string)<3)
        {
            die ("<br>Please enter a search term (3 chars min)");
        }
        $tables = $this->db->query('SHOW TABLES');

        $tblfn = 'Tables_in_'.$this->dbname;
        foreach ($tables as $tablerow)
        {
            $table = $tablerow[$tblfn];
            $use = ($this->include ? in_array($table, $this->include) : true);
            $notuse = ($this->exclude ? in_array($table, $this->exclude) : false);
            if ($use && !$notuse)
            {
            $qryfields = array();
            $key='';

            echo ".";
            $msql = 'SHOW FIELDS IN '. $table;
            //echo "<br>$msql<br>";
            $fields = $this->db->query($msql);
            // use char,varchar and text tinytext
            //print_r($fields);
            foreach($fields as $field)
            {
                $mysqltype = preg_replace('/\s*\(\d+\)\s*/','', $field['Type']);
        $mysqltype = preg_replace('/\s*\(\d+,\d+\)\s*/','', $mysqltype);
                //echo $mysqltype."<br>";
                if ($field['Key'] == 'PRI' && !$key)
                {
                    $key = $field['Field'];
                }
                if (in_array($mysqltype, $this->targettypes ))
                {
                    $qryfields[] = '`'.$field['Field']."` like '%$string%'";
                }
            }
            //echo "<br> PRI: $key";print_r($qryfields);
            if ($qryfields)
            {
                //print_r($table);
                $mSql = "SELECT count(*) as e FROM  `$table` WHERE " . implode(' OR ', $qryfields);
                //echo $mSql."<br>";
                $result = $this->db->query($mSql);
                if ($result[0]['e'] >0)
                {
                    echo "<br>$table (".$result[0]['e'].')';
                    if ($detailed)
                    {
                         $mSql = "SELECT ".($detailed==1 ? $key : '*')." FROM  `$table` WHERE " . implode(' OR ', $qryfields);
                         echo '<div style="border:1px solid #ccc; height:200px;overflow:auto;">';
                         print_r($this->db->query($mSql));
                         echo "</div>";
                    }
                }

            }
        }//if
        }
        echo "Done.";
    }
}

?>