Tumgik
thephpeffect ¡ 10 years
Text
Facet Style PHP Framework
Frameworks are all over these days, each one does something a little bit different than the others, trying to stand out. Honestly MVC does a really good job on the web. Building a website,or application? No problem, there’s an MVC framework for that. Whether it is Zend, CodeIgniter, Symfony or any other, they are used everywhere.
But what about where they aren’t appropriate? What tools do we have for when we want to add a piece of functionality to a site that either isn’t part of a framework, or a tool in the framework doesn’t exist? Well, you are left two options, build it yourself, or find some script someone wrote and do your best to incorporate it into your site.
Now this really isn’t so bad, until you have 3, 4, or 5 of these different classes, and scripts, and then you want them to integrate with each other. That is where the kicker really comes in. Then you have to spend time digging into these unfamiliar classes to patch together a relationship that just wasn’t meant to be.
So is there a better way? Maybe, I’ve lately been pondering the idea of a facet or module driven framework. This kind of framework may still embody some of the MVC patterns (“if it isn’t broken don’t fix it”), but lends itself to being more flexible.
For example, imagine a way to decouple modules of a traditional MVC like Zend or Symfony, and be able to use them on any site with ease. But, when multiple facets/modules are brought together, they know how to talk to each other and integrate.
The first question that arises of course is, “Is it possible to do with a small enough footprint in an easy way to implement and configure?”.
I don’t know.
There is also the question of performance, if you were to place all of the components together into its full framework, how would it stack up? Likely, it would be slower, but then, the idea isn’t to use it as a full blown framework. The idea is to be able to cherry pick framework-like pieces and use them together seamlessly, without being constrained.
Over the next months this is an area I will likely explore. To anyone who happens upon this article, if such a framework/tool exists, I would be more than happy to see it.
0 notes
thephpeffect ¡ 10 years
Text
Traits and Multiple Inheritance
Up until PHP 5.4, there was no multiple inheritance; every line of OO code had to be written with single inheritance in mind. So when PHP 5.4 was released two years ago, many developers asked, “Why would I need Traits?”. This is a good question to ask, we have gotten by without multiple inheritance all this time, we rarely say “Man I wish I had multiple inheritance right now”. However, Traits open up a new door, a new potential path for organization and design. Now that it is possible the question will come up more often. In this post I am going to address this with a perhaps trivial example, but one that does work. This assumes the reader understands Traits and Namespaces in their basic form.
The code has been truncated in favor of a shorter article. Nothing import is missing, just getters and setters really. The full set is available here: TraitsAndMultipleInheritance-Code
  Database
Let us say that we have a basic database setup (perhaps using Symfony2, CodeIgnitor, or your favorite framework). Maybe we have news, maybe we have announcements, and maybe we have videos. These three things. One some of them we can comment, and on all of them we are going to collect stats.
A basic schema could look like this:
              The Current Way
First, let us look at the current single inheritance would work. First we would have some base entity, this entity will hold the id (with its getter and setter), since all entities should have a primary key id:
1 2 3 4 5 6 7
<?php class BaseEntity extends SomeFrameworkClass { protected id;   // ... }
Once we have this we can extend it. Say, we believe that most entities will require a created date and an updated date. We could add this into the base entity, but let us say that for the purpose of this example, we believe there may be a time that we use the base entity, but do not want these dates. So, we would extend the base entity:
1 2 3 4 5 6 7 8
<?php class Timestampable extends BaseEntity { protected $lastUpdated; protected $created;   // ... }
Now we are all set. But… what about commenting? Our db schema shows that we are using comment sets. This allows us to abstractly assign comments to different features without caring which feature they are from. The schema uses enum types to track where the comments come from, but that ultimately is for management, not for the relationships that ultimately pull the comments. (More on using relationship sets in the future perhaps).
So off we go, extending again:
1 2 3 4 5 6 7
<?php class Commentable extends Timestampable { protected commentSetId;   // ... }
We could stop here, but to exaggerate the issue, we are going to add stats. Everyone wants to know if something has been viewed, liked, or shared “X” number of times. So, we can extend the Commentable class to build on that:
1 2 3 4 5 6 7
<?php class Shareable extends Commentable { protected statSetId;   // ... }
Now this could all be avoided, by just defining each individual Entity with all of these attributes, and not doing it this way. But the whole point of OO is to be modular. However, as you can see, it gets bloated quickly. Don’t get me wrong…we can define our News entity now, and extend it from Shareable, and we are good, since Shareable has, Commentable, Timestampable, and the BaseEntity:
1 2 3 4 5 6 7 8 9 10
<?php class News extends Shareable { protected $article; protected $headerImage; protected $title; protected $tags;   // ... }
Now, here is the problem. The next object, is Announcements, I want Announcements to be shareable, but I don’t want people commenting on them. That means I have to extend the Timestamable into say, Shareable2 so there are no comment pieces. After a while, this starts to get large, especially if many different permutations are required. Many have overcome this obstacle by using interfaces. Multiple interfaces can be implemented by a class, the problem here, is that an interface can only specify what methods should exist in the implementing class. They cannot actually contain any code themselves. So while your class will throw an error if it is missing something, duplicate code still must be written. Now, there are certainly times where this is necessary. Many times a single method in a class will be different depending on the purpose of the class, even if it does the same type of task, but in the case of our example, we would just have duplicate code.
Here is the Announcement entity mentioned, as you can see it extends Shareable, which has comments, we would have to generate Shareable2 as mentioned above in order keep commenting out of the Announcements entity and database:
1 2 3 4 5 6 7 8 9
<?php class Announcement extends Shareable2 { protected $announcement; protected $title; protected $tags;   // ... }
Also, if you notice, tags are a commonality between these as well. With so much shared code and potential need for modular behavior, we must turn to Traits for a clean solution.
The Trait Way
Traits act much like a normal class, you can add attributes and methods, you can extend them, you can use a trait within another trait as well. They are quite flexible that way. It is how they are used that ultimately gets them noticed.
To start, we will convert our Timestampable, Commentable, and Shareable classes to traits. each trait is standalone, and does not extend from anything. We will throw in a Taggable trait for good measure as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
<?php trait Updated { protected $lastUpdated;   // ... }   trait Created { protected $created;   // ... }   trait Commentable { protected commentSetId;   // ... }   trait Shareable { protected statSetId;   // ... }     trait Taggable { protected $tags;   // ... }
We can also combine traits into commonly used groups:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<?php trait Timestampable { use Created; use Updated; }   trait FullFeatureEntity { use Timestampable; use Shareable; use Commentable; use Taggable; }
Once these are defined, using them is easy enough. Our News and Announcement entities will now extend the BaseEntity, and “use” the traits, like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
class NewsWithTraits extends BaseEntity { use FullFeatureEntity;   protected $article; protected $headerImage; protected $title;   // ... }   class AnnouncementWithTraits extends BaseEntity {   use Created; use Taggable; use Shareable;   protected $announcement; protected $title;   // ... }
Now as you can see, the AnnouncementWithTraits entity has Created, Taggable, and Shareable, but not Updated, or Commentable. This is because we don’t want comments on AnnouncementsWithTraits and we only plan to post them once and not update them. So those two things aren’t needed. There is no bloat from multiple extends and as little duplicate code as possible (Just the “use” statements of the traits).
This is the new paradigm, and honestly, it is neat and clean. I really don’t mind it.
I never did create the video object detailed in the db mock-up, feel free to do it as an exercise to get a feel for this design methodology.
0 notes
thephpeffect ¡ 12 years
Text
The Rise of the DevOp
Here is a quick reference to what a DevOp is: http://en.wikipedia.org/wiki/DevOps
In the last couple of years a new development position within companies has emerged. The DevOp. The DevOp is a cross between a Developer or Engineer and TechOps. The person who holds the title DevOp should be able to be hired as Developer or as a TechOp, their skills in both areas must be very competent.
The DevOp was born just after cloud servers and services became popular. Cloud services offered independent developers a chance to turn their ideas into marketable and competitive products very easily. There was just one problem, they didn’t have a company behind them with TechOp resources. So out of necessity, they learned how to do everything themselves. This was the beginning of a new breed of programmer.
Today there are many DevOp or DevOp-like positions available in companies. I have noticed a potentially trending problem however. A developer will begin to slowly take on the responsibilities of a DevOp, but the company doesn’t pay them more for that extra skill set they are using. Normally a DevOp is worth more than a regular developer, because his/her skill set is higher. However, when companies slowly integrate their current developers to become DevOps the “promotion” so to speak is overlooked.
Another issues companies might overlook the fact that the company may expect the same development performance from an individual who is now a DevOp. The problem with this is that with the new responsibilities, the DevOp becomes overworked and stressed which in turn negatively affects performance.
Please leave comments about your experiences or observations on a move from Developer to DevOp.
0 notes
thephpeffect ¡ 12 years
Text
Recursive glob() VS. RecursiveDirectoryIterator
The glob() function has been around since PHP4 and it is a very widely used function. Below is an example of a basic recursive glob function as found on php.net.
I did take the liberty of renaming it to “rglob” I felt it was cleaner.
1 2 3 4 5 6 7 8 9 10 11 12
<?php   // Does not support flag GLOB_BRACE function rglob($pattern, $flags = 0) { $files = glob($pattern, $flags); foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) { $files = array_merge($files, rglob($dir.'/'.basename($pattern), $flags)); } return $files; }   ?>
While this is fine, you will discover that unless you had this handy function around already, you will end up searching for one, or creating one yourself. This problem was solved in PHP5 but is little known to many PHP developers. The solution: Iterators! Iterators have become increasingly more popular and more powerful with each new version of PHP5. One of those Iterator objects is the RecursiveDirectoryIterator. Using this class in junction with both the RecursiveIteratorIterator and the RegexIterator brings a powerful combination that allows for faster development.
With a basic understanding of Iterators one can create such a function without some of the research it might take to experiment with glob(). Here is an example:
1 2 3 4 5 6 7 8 9 10 11 12
<?php function rsearch($folder, $pattern) { $dir = new RecursiveDirectoryIterator($folder); $ite = new RecursiveIteratorIterator($dir); $files = new RegexIterator($ite, $pattern, RegexIterator::GET_MATCH); $fileList = array(); foreach($files as $file) { $fileList = array_merge($fileList, $file); } return $fileList; } ?>
As you can see, the Iterators will handle everything for you. How nice is that!
0 notes
thephpeffect ¡ 12 years
Text
The New PHP 5.4
There is a new version of PHP has been released in the couple of weeks or so. PHP 5.4. I would like to highlight a few features that I am excited about. Here is a link to some basic new features from php.net.
  Short Array Syntax
The new short array syntax is such a relief, I don’t know how many times I have typed array() and wished for the short Javascript like syntax. Maybe I’m just lazy but hey, that’s 5 extra characters that I’ve typed thousands of times, it adds up. Here are some examples:
1 2
$myArr = [1, 2, 3, 4 ,5]; $myArr = ['foo; => 'bar', 'test' => 99];
  Function Array Dereferencing
To go along with the the new short array syntax you can do function dereferencing, basically, if a function returns an array, you can access that array immediately instead of using a temp array.
1 2 3 4 5 6 7 8
$myStr = "apples,oranges,bananas";   // Old way $tmpArr = explode(",", $myStr); echo $tmpArr[1]; // Returns "oranges"   // New way echo explode(",", $myStr)[1]; // Returns "oranges"
  Class Member Access Upon Instantiation
In PHP 5.4 they have also added a feature that lets you call a method of a class upon instantiation.
1 2 3 4 5 6 7 8 9
class TestClass { public function __construct(){ /* We will leave this blank for now. */ } public function helloWorld(){ echo "Hello World!"; } }   // How to use it (new TestClass)->helloWorld(); // echos "Hello World"
  Traits
Traits are something I really want to touch on here. The exciting thing about traits is that now we can have multiple inheritance in PHP. Now, some people will say that multiple inheritance is dangerous, or a waste of time. However, one size does not fit all, there may arise situations that need multiple inheritance to make the code more optimal. There is a lot of information on traits, so please read up on the php.net site about them.
In a post in the near future I will give you an example of how to effectively use traits in a meaningful way.
0 notes
thephpeffect ¡ 12 years
Text
A Basic Database Connection Manager
The follow is an extremely simplified version of a database connection manager. It allows you to save multiple mysqli connections to make managing a complex environment more simple. There are many ways to implement a database connection manager this is probably one of the most generic and simple way to do it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<?php class DatabaseManager {   private static $_instances = array();   public static function getInstance($instance_name, $connection_info = array()) { if($connection_info) { list($db_host, $db_user, $db_pass, $db_name) = $connection_info; self::$_instances[$instance_name] = new MySQLi($db_host, $db_user, $db_pass, $db_name); } return self::$_instances[$instance_name]; } }   function db($instance_name='default', $connection_info = array()){ return DatabaseManager::getInstance($instance_name, $connection_info); } ?>
If this makes sense you can jump straight to the usage examples
Otherwise let’s take a look at this piece by piece:
1 2 3 4
<?php class DatabaseManager {   private static $_instances = array();
The $_instances array will contain an instance of each MySQLi connection object. It needs to be static so that you do not lose the connections you have saved.
6 7 8 9 10 11 12
public static function getInstance($instance_name, $connection_info = array()) { if($connection_info) { list($db_host, $db_user, $db_pass, $db_name) = $connection_info; self::$_instances[$instance_name] = new MySQLi($db_host, $db_user, $db_pass, $db_name); } return self::$_instances[$instance_name]; }
The getInstance() function doesn’t just get, it also acts like a setter. An instance name is required, it is how you will distinguish between your different connections. The connection_info array needs to be set when you want to create a new connection, as long as you have all of the values you need to use the MySQLi object in the array and they are in the proper order, you won’t have any problems.
At the end of the class it returns the desired connection to you. There is no error handling built into this class, though I may add that at a later post.
15 16 17 18
function db($instance_name='default', $connection_info = array()){ return DatabaseManager::getInstance($instance_name, $connection_info); } ?>
Next I wrote a little wrapper function to make calling the DatabaseManager a simpler task. Normally you would need to do DatabaseManager::getInstance(‘db_foo’); to retrieve your connection. This can get cumbersome and it is much easier to call db(‘db_foo’); instead.
You will also notice that with this db() function we added another feature. If, when you create a database connection, you save its instance name as ‘default’ you will only have to call db() to retrieve the MySQLi link, this makes it even easier.
Now for some examples:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<?php // First create a connection, we will use this as our default // I choose to instantiate first, and then use because chaining // a query call after you pass connection info is messy db('default', array('localhost', 'my_db_user', 'my_db_pass', 'my_db_foobar')); db('globals', array('localhost', 'my_db_user', 'my_db_pass', 'my_db_globals'));   // Now that the connection is made, I can use it // Notice that because I used 'default' as my instance name, // I do not have to pass an instance name in when retrieving it $results = db()->query('SELECT some_column FROM foobar_table WHERE foo = 1');   $gresults = db('globals')->query('SELECT system_value FROM system_options WHERE system_key = 'foobar'); ?>
0 notes