Monday, April 30, 2012

Joining JOINs

It has been suggested that I need to use a manyToMany approach to solve this problem.

http://readthedocs.org/docs/doctrine-orm/en/latest/reference/association-mapping.html#one-to-many-unidirectional-with-join-table

Here is the YAML from that page (with a corrected typo)
User:
  type: entity
  manyToMany:
    phonenumbers:
      targetEntity: Phonenumber
      joinTable:
        name: users_phonenumbers
        joinColumns:
          user_id:
            referencedColumnName: id
        inverseJoinColumns:
          phonenumber_id:
            referencedColumnName: id
            unique: true
I tried to do some conversion, but have run into some barriers, which I'll detail.  Its worth noting that this YAML does not work... now I'm trying to figure out if its meant to be stand alone, or if requires the other Entities to be declared on their own..

[thinks for a few minutes]

I am pretty sure they do need their own separate entities.

So we'll have Names and Matches, like normal, and this new entity is a Joining entity, so it just builds a bridge between the two.

So lets take it from the beginning.

Names should have {id} and {name},  Matches should have {id}, {name1} and {name2} or some permutation thereof.  

[types furiously]

Okay, so I have the following test YAML code:

ORM\Testing\Names:
  type: entity
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
  manyToMany:
    tennis:
      targetEntity: Matches
      joinTable:
        name: names_to_matches
        joinColumns:
          name_id:
            referencedColumnName: character1
        inverseJoinColumns:
          matches_id:
            referencedColumnName: id
            unique: true
#
 works fine for generating entities and proxies, but when I try to generate the SQL schema I get:
Column name `character1` referenced for relation from ORM\Testing\Names towards ORM\Testing\Matches does not exist.
[still later]

Hm.  The example on the previously provided link seems to be to link just two unrelated fields.  Like if I had a firstNames entity and a lastNames entity, firstAndLast would use code much like in that example to link them together..

.... in progress...

Thursday, April 26, 2012

More JOINs

This has been confounding me for a few days now.


I am attempting what I call a double join.  Let me describe what I'm trying to do, then we'll dive into the meat of it.


I have a table called Matches that has three fields
id, character1_id, character2_id.
I have another table called charnames that has only two fields.
id, charname.


For example sake, let's say that this is to track tennis matches between people.  So in 'Charnames' I have a bunch of id's and a bunch of names.
1  Jeremy
2  Bob
3  Gandalf
4  Frodo


And 'Matches' pairs them up by id.
1  3  4
2  1  2


So if I queried this and joined it, I'd get something like this:
Match 1: Gandalf(3) and Frodo(4)
Match 2: Jeremy(1) and Bob(2)


(We'll tackle triple joins later!  ugh!)


And that's it.  The trick is that I have to join it twice, because 'Matches' contains two character fields, both of which tie back to the primary key index on 'Charnames'.


So here's the code involved at the moment (which is not working), and all the assorted details.


YAML for 'Charnames'



ORM\Testing\Charnames:
  type: entity
  table: test_charnames
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
    charname:
      type: string
      length: 255
And the entity file for 'Charnames'

 <?php
namespace ORM\Testing;
use Doctrine\ORM\Mapping as ORM;
/**
 * ORM\Testing\Charnames
 */
class Charnames
{
    /**
     * @var integer $id
     */
    private $id;
    /**
     * @var string $charname
     */
    private $charname;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set charname
     *
     * @param string $charname
     * @return Charnames
     */
    public function setCharname($charname)
    {
        $this->charname = $charname;
        return $this;
    }
    /**
     * Get charname
     *
     * @return string
     */
    public function getCharname()
    {
        return $this->charname;
    }
}
Table structure:
CREATE TABLE IF NOT EXISTS `test_charnames` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `charname` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=11 ; 
And now 'Matches'.  YAML first.
 ORM\Testing\Matches:
  type: entity
  table: test_matches
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
  manyToOne:
    character1:
      targetEntity: ORM\Testing\Charnames
    character2:
      targetEntity: ORM\Testing\Charnames
 Entity file:

<?php
namespace ORM\Testing;
use Doctrine\ORM\Mapping as ORM;
/**
 * ORM\Testing\Matches
 */
class Matches
{
    /**
     * @var integer $id
     */
    private $id;
    /**
     * @var ORM\Testing\Charnames
     */
    private $character1;
    /**
     * @var ORM\Testing\Charnames
     */
    private $character2;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set character1
     *
     * @param ORM\Testing\Charnames $character1
     * @return Matches
     */
    public function setCharacter1(\ORM\Testing\Charnames $character1 = null)
    {
        $this->character1 = $character1;
        return $this;
    }
    /**
     * Get character1
     *
     * @return ORM\Testing\Charnames
     */
    public function getCharacter1()
    {
        return $this->character1;
    }
    /**
     * Set character2
     *
     * @param ORM\Testing\Charnames $character2
     * @return Matches
     */
    public function setCharacter2(\ORM\Testing\Charnames $character2 = null)
    {
        $this->character2 = $character2;
        return $this;
    }
    /**
     * Get character2
     *
     * @return ORM\Testing\Charnames
     */
    public function getCharacter2()
    {
        return $this->character2;
    }
}
Table Structure:
CREATE TABLE IF NOT EXISTS `test_matches` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `character1_id` int(11) DEFAULT NULL,
  `character2_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `IDX_DA67C172F6129E9E` (`character1_id`),
  KEY `IDX_DA67C172E4A73170` (`character2_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; 
Here is the data actually in my tables:
test_matches:
id    character1_id    character2_id
1          7                        2
2          8                         4
3          10                       3
4          2                        1
test_charnames:
1         Gandalf
2         Gollum
3         Bilbo
4         Frodo
5         Samwise
6         Gimili
7         Legolas
8         Thorin
9         Saurumon
10       Treebeard

 And now, some querying and code.

Here is my query at present:


$query = $this -> doctrine -> em -> createQuery ("SELECT a.id, b.charname, c.charname
            FROM ORM\Testing\Matches a
            JOIN a.character1 b
            JOIN a.character2 c
            ");
$result = $query->getResult();
 \Doctrine\Common\Util\Debug::dump($result); 

This returns the following data:
array(4) {
[0]=> array(2) { ["id"]=> int(1) ["charname"]=> string(6) "Gollum" }
[1]=> array(2) { ["id"]=> int(2) ["charname"]=> string(5) "Frodo" }
[2]=> array(2) { ["id"]=> int(3) ["charname"]=> string(5) "Bilbo" }
[3]=> array(2) { ["id"]=> int(4) ["charname"]=> string(7) "Gandalf" } } 
So it is returning the 2nd character name.  But not the first.

I also tried this query:

$query = $this -> doctrine -> em -> createQuery ("SELECT a, b, c
            FROM ORM\Testing\Matches a
            JOIN a.character1 b
            JOIN a.character2 c
            ");
And the output:
array(4) {
[0]=> object(stdClass)#42 (4) { ["__CLASS__"]=> string(19) "ORM\Testing\Matches" ["id"]=> int(1) ["character1"]=> string(21) "ORM\Testing\Charnames" ["character2"]=> string(21) "ORM\Testing\Charnames" }
[1]=> object(stdClass)#71 (4) { ["__CLASS__"]=> string(19) "ORM\Testing\Matches" ["id"]=> int(2) ["character1"]=> string(21) "ORM\Testing\Charnames" ["character2"]=> string(21) "ORM\Testing\Charnames" }
[2]=> object(stdClass)#72 (4) { ["__CLASS__"]=> string(19) "ORM\Testing\Matches" ["id"]=> int(3) ["character1"]=> string(21) "ORM\Testing\Charnames" ["character2"]=> string(21) "ORM\Testing\Charnames" }
[3]=> object(stdClass)#73 (4) { ["__CLASS__"]=> string(19) "ORM\Testing\Matches" ["id"]=> int(4) ["character1"]=> string(21) "ORM\Testing\Charnames" ["character2"]=> string(21) "ORM\Testing\Charnames" } }  
So, I *think* that the problem is with my query.  But its entirely possible that it is a problem with my entities or table structure.


Friday, April 20, 2012

Doctrine JOINs

Lets talk about JOINs in Doctrine.

We'll use a simple example.  Lets say that we want to record first and last names, but since we'll be doing entire families, there will be overlap in last names: Joe Smith, Sally Smith, Bobby Smith, and so on.  We'll have a table for first names, and a table for last names.  The first names should all link back to their corresponding last name.
So our tables might look like this:

Firstnames:
id first_name mylastname
1 Joe 15
2 Sally 15
3 Lisa 15
4 Mark 16
5 Betty 16
6 Henry 16

Lastnames:
id last_name
15 Smith
16 Jones

So when we execute a query after its JOINed we'll get: Joe Smith, Sally Smith, Lisa Smith, Mark Jones, Betty Jones, Henry Jones.

As I'm currently understanding, this is considered a manyToOne unidirectional relationship.  mylastname should be a foreign key that references the id field in the Lastnames table.

Lets look at my YAML entity files:


ORM\Testing\Firstnames:
  type: entity
  table: test_firstnames
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
    firstname:
      type: string
      column: first_name
  manyToOne:
    mylastname:
      targetEntity: ORM\Testing\Lastnames
       

ORM\Testing\Lastnames:
  type: entity
  table: test_lastnames
  fields:
    id:
      type: integer
      id: true
      generator:
        strategy: AUTO
    lastname:
      type: string
      column: last_name

This generates the following SQL schema:


CREATE TABLE test_lastnames (id INT AUTO_INCREMENT NOT NULL, last_name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB;

CREATE TABLE test_firstnames (id INT AUTO_INCREMENT NOT NULL, mylastname_id INT DEFAULT NULL, first_name VARCHAR(255) NOT NULL, INDEX IDX_23D7305696EC0FA4 (mylastname_id), PRIMARY KEY(id)) ENGINE = InnoDB;

ALTER TABLE test_firstnames ADD CONSTRAINT FK_23D7305696EC0FA4 FOREIGN KEY (mylastname_id) REFERENCES test_lastnames (id)

If I put some data into the tables and then run the following:

$whichFamily = '2';
$query = $this -> doctrine -> em -> createQuery ("SELECT a.firstname, b.lastname FROM ORM\Testing\Firstnames a JOIN a.mylastname b WHERE b.id = $whichFamily");
$result = $query->getResult();
\Doctrine\Common\Util\Debug::dump($result); 

it returns
array(3) { [0]=> array(2) { ["firstname"]=> string(5) "Sarah" ["lastname"]=> string(5) "Jones" } [1]=> array(2) { ["firstname"]=> string(5) "Bobby" ["lastname"]=> string(5) "Jones" } [2]=> array(2) { ["firstname"]=> string(6) "Martha" ["lastname"]=> string(5) "Jones" } }

Which looks muddled, but its exactly what I want!

 Then I add


foreach ($result as $val1 => $val2) {
//echo $val2;
foreach ($val2 as $val3 => $val4) {
echo $val4;
echo " ";
}
echo "</br>";
}
and I get:
Sarah Jones
Bobby Jones
Martha Jones  




Wednesday, April 18, 2012

I made a ton of progress week before last and did not stop to do updates here like I should have done.  I made some changes to the doctrine entities and my db schema, which I think I have well in hand.  The big thing I'm trying to do now is to figure out Association Mapping (like sql join), and I've posted here and here about it, hoping for some advice or a breakthrough.

Doctrine and CI make it incredibly easy to write code, and fast.  More soon, hopefully.

Monday, April 9, 2012

Boy do I have some catching up to do.

I was able to get a goodly bit of code written over this past weekend.  Sorted out a few problems and so forth.

One thing that I have made some progress on but still needs some research and time is session security at the page/function level.  More on this in another post.

Friday, April 6, 2012

more work on entities


A PHP Error was encountered

Severity: Warning
Message: require(applicationFolder/models/Entities/User.php) [function.require]: failed to open stream: No such file or directory
Filename: Common/ClassLoader.php
Line Number: 163

Fatal error: require() [function.require]: Failed opening required 'applicationFolder/models/Entities/User.php' (include_path='.:/usr/local/lib/php:/usr/local/php5/lib/pear') in/../applicationFolder/libraries/Doctrine/Common/ClassLoader.php on line 163


require ($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
               . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
               . $this->fileExtension;

entities


// load the entities
        $entityClassLoader = new \Doctrine\Common\ClassLoader('Entities', APPPATH.'models');
        $entityClassLoader->register();
  $entityClassLoader = new \Doctrine\Common\ClassLoader('Dynasties2', APPPATH.'models');
        $entityClassLoader->register();
$entityClassLoader = new \Doctrine\Common\ClassLoader('Testing', APPPATH.'models');
        $entityClassLoader->register();

Remapping YML files

With doctrine when you make changes to your sql database, you have to do so with code.

I decided to move from a pure test environment to an alpha game environment (what's the diff?, sure sure)

To do this I need a different table setup.  I need the old 'users' table to go away and be replaced by a new one, and I need at least one other table just to get going.  I do still want the old users table and articles table from my test environment, for further testing.

My hope was that I could remove/modify the existing YML files and add more for the tables I needed.  When I started I made a YML table for users and for articles.  The documentation indicates that I can further compartmentalize them, instead of Entities.User.dcm.yml I should be able to use Testing.User.dcm.yml and Livesite.User.dcm.yml as long as the files are set to point to different tables.

However,  its not working.

**


[yangon]$ /usr/local/php53/bin/php doctrine-cli.php orm:generate-entities models
Processing entity "Testing\User"
Processing entity "Testing\Article"
Processing entity "Dynasties2\Users"
Processing entity "Dynasties2\Families"

Entity classes generated to "/home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/models"

**

[yangon]$ /usr/local/php53/bin/php doctrine-cli.php orm:generate-proxies        
Warning: class_parents(): Class Testing\User does not exist and could not be loaded in /home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/libraries/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php on line 40

Warning: array_reverse() expects parameter 1 to be array, boolean given in /home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/libraries/Doctrine/ORM/Mapping/ClassMetadataFactory.php on line 231

Warning: Invalid argument supplied for foreach() in /home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/libraries/Doctrine/ORM/Mapping
**

I've already tried numerous tricks - naming them all Entity.Test.User.dcm.yml and Entity.Dynasties2.User.dcm.yml and such, but no luck..

db table manipulation

Now I need to figure out how to fiddle with the layout of my database.  For testing sake, I'm going to try to add a field to my Users table in my database.

I think that I do this by modifying Entities.User.dcm.yml.  Simple enough, I'll just add some data:

    userName:
      type: string
      length: 255
      nullable: true
      column: user_name

Then I think that I just need to run a few CLI commands:
/usr/local/php53/bin/php doctrine-cli.php orm:generate-entities models 
/usr/local/php53/bin/php doctrine-cli.php orm:generate-proxies
/usr/local/php53/bin/php doctrine-cli.php orm:schema-tool:update



 Now lets see if it works, or if I just massively break it.

First two commands seem to work fine, on the schema update I get:


[yangon]$ /usr/local/php53/bin/php doctrine-cli.php orm:schema-tool:update
ATTENTION: This operation should not be executed in a production environment.
           Use the incremental update to detect changes during development and use
           the SQL DDL provided to manually update your database in production.
The Schema-Tool would execute "1" queries to update the database.
Please run the operation by passing one of the following options:
    orm:schema-tool:update --force to execute the command
    orm:schema-tool:update --dump-sql to dump the SQL statements to the screen

Lets try /usr/local/php53/bin/php doctrine-cli.php orm:schema-tool:update --dump-sql

Alright, that worked.  --dump-sql tells me what SQL statements it will execute, but it only shows me what it will do.  I had to do --force to execute the changes.  And they worked!


Unique Validation

Grr.  I've spent two days trying to figure out how to do unique validation.

I have a form that a user fills out.  If it meets all of the validation rules then its submitted to the DB.  If it does not - if one of the fields is too long or short, not a proper email address, etc - the form is kicked back.  That all works.

I'm trying to get it to check to make sure that the email address is unique.  You cannot register an email address that is already in the system.  Now, I know how to do this old school, you query the db and look for the submitted email address, and if you get a return, you reject it.  However, I don't want to do it that way.

There are apparently functions in CodeIgniter/Doctrine for this very thing.

CodeIgniter has a form_validation function that works great for making sure that the passwords match, that length or complexity requirements are met... and has an is_unique feature, but I cannot seem to get it to work - that could be because I'm also using Doctrine, but I'm not certain.

The CodeIgniter userguide also suggests using a callback, but again - I just cannot seem to get it to work.  In this case, the code example seems incomplete.  Either it is, or I'm new enough that I'm not grasping some fundamental concept.

I've appealed to the internet for help, posting on stackoverflow and a couple PHP forums.  We'll see what I can find out.

Edit:

I discovered that if I add $autoload['libraries'] = array('database'); to autoload.php, it makes the form_validation work.

However, it seems to break the Doctrine part of this thing.
Fatal error: Class 'Entities\User' not found in /home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/controllers/signup_form.php on line 30
After more trial and error, I find that I cannot apparently have both of those autoloaded libraries.  Hm.

Edit:  Solved.

This may not be the best or most elegant solution, but it works.
$this->form_validation->set_rules('email', 'E-mail', 'required|valid_email|callback_email_check');
 
public function email_check($str)
{
$user = $this->doctrine->em->getRepository('Entities\User')->findOneBy(array('email' => $str));
               if (isset($user)) {
                        $this->form_validation->set_message('email_check', 'This email address is already in use');
                        return FALSE;
                } else
{
return TRUE;
}
}
(Note to self,  code looks hideous on here.)

Thursday, April 5, 2012

Doctrine CLI

Got it!

Apparently Dreamhost's PHP CLI uses version 5.2.17.  I needed it to use 5.3, so any commands must be preceeded with /usr/local/php53/bin/php

I was thrown off by the instruction's to change the APPPATH definition.  After a great deal of trial and error, it turned out that define('APPPATH', dirname(__FILE__).DIRECTORY_SEPARATOR); was what I needed.

[yangon]$ /usr/local/php53/bin/php doctrine-cli.php  

Returned the expected results.  Huzzah!

I tried running php doctrine-cli.php orm:generate-entities models

but it gave me an error - 

  [Doctrine\ORM\Mapping\MappingException]                                       
  No mapping file found named 'Entities.Article.dcm.yml' for class 'Entities\Article'.

I setup my own Entities xml file, after a little trial and error I saw that this was the problem, so I replaced that with the yml files from Joel's documentation.  Now that command works.

[yangon]$ /usr/local/php53/bin/php doctrine-cli.php orm:generate-entities models
Processing entity "Entities\Article"
Processing entity "Entities\User"
Entity classes generated to "/home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/models"

Yay!

Now php doctrine-cli.php orm:generate-proxies

Fatal error: Call to undefined function Doctrine\Common\Cache\apc_fetch() in /home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/libraries/Doctrine/Common/Cache/ApcCache.php on line 52
After some digging, it appears that I do not have APC installed (alternate PHP cache). The comments on Joel's page recommends either disabling APC or installing it. Installing it has proved a little tricky.


http://wiki.dreamhost.com/APC

[a little while later...]

APC installed!


[yangon]$ /usr/local/php53/bin/php doctrine-cli.php orm:generate-proxies
Processing entity "Entities\Article"
Processing entity "Entities\User"
Proxy classes generated to "/home/xxxjermxxx/dixieandtheninjas.net/hellounderscoreworld/applicationFolder/models/Proxies"


Progress!


[yangon]$ /usr/local/php53/bin/php doctrine-cli.php orm:schema-tool:create
ATTENTION: This operation should not be executed in a production environment.
Creating database schema...
Database schema created successfully!


Aaaaaaaand apparently its done.  Installed.

Now I'll wrap this post up and next time we'll see what happens when we try to do stuff with it!

Wednesday, April 4, 2012

Setup

Lets get this thing running, shall we?

I'm installing at http://dixieandtheninjas.net/hellounderscoreworld/


I've got CodeIgniter 2.1.0 downloaded and put it into the new site.

  • CodeIgniter recommends changing the names of your application and system folders for increased security, which I've done, and then updated the index.php file accordingly.
  • I modified CI's config file and updated the base URL. $config['base_url'] = 'http://www.dixieandtheninjas.net/hellounderscoreworld/';
  • I've created a mySQL database just for this blog project, and gone into the database.php file and configured it correctly.

Now we're ready to get Doctrine added.

  • Created a Doctrine.php file in /application/libraries and put the text in from Joel's site.
  • Uploaded the Doctrine folder to /application/libraries/
  • Changed CI's autoload config file
  • Add Models to Doctrine
    Note that this bit is rather tricky.  In the example on Joel’s site, he discusses creating two models, User and Article.  These are actually objects in the code.  He notes that these are different than CI Models and do not extend the CI_Model class.  So I created the mappings directory under /application/models/ and then created an Entities.User.dcm.xml  Now, I’ve done this once before, and so I’m cribbing a little.. my Entities file looks very different than Joel’s.  Here is mine.
<doctrine-mapping>
    <entity name="Entity\User" table="Users" change-tracking-policy="DEFERRED_IMPLICIT">
        <id name="id" type="smallint" column="ID">
            <generator strategy="IDENTITY"/>
        </id>
           
        <field name="name" type="string" column="Name" length="40"/>
                                    
    </entity>
</doctrine-mapping>
           

So, here’s the thing:  I’m just going to come right out and admit that I don’t really understand this Entities file, what it does, how it does it or why.  But I’m doing this to learn, so hopefully at some point I can say that this is no longer the case.

And this is where I get stuck for the moment.  Joel’s page discusses further configuration changes, including a CLI for Doctrine, and setting up Proxies and entity classes.  So I’m going to have to stop here for a bit and study it further.  Based on previous experience, this is a functioning install – in that I can get classes to work, and MVC to do its thing, though I have not yet tested database connectivity – which is of course important.  That’ll be next.  Stay tuned!




    My Tools and Resources

    First we need to get this thing setup.

    I have an account with Dreamhost to do hosting, and am using PHP 5.3. I like WinSCP for uploading and manipulating files directly on the server, and I prefer Netbeans for programming.

    I used this great link to get CodeIgniter and Doctrine running, which I'll detail in a subsequent post.

    When I set out to learn PHP I picked up a couple of books on the cheap, but I found that the web was the biggest help. PHP.net has everything you need to get started, and stackoverflow.com was a huge help.

    Tuesday, April 3, 2012

    A Brief Introduction

    Hello World!

    What's this blog for?

    It is 1) for my reference. I go long stretches sometime between coding, and I forget a great deal, and relearning from scratch is a pain. And 2) for new coders interested in some occasional tidbits of information.

    I'm a network administrator by day, and a dad and husband by night, so programming is merely a hobby for me.

    I began teaching myself PHP in 2010, and got to the point that I could put together small web projects. Very small, mind you - and probably very ugly. Since I'm teaching myself, I have little doubt that I'm picking up strange habits, or missing very simple solutions to things sometimes. It's been almost entirely procedural PHP, but recently I've begun getting into OOP: Code Igniter, MVC, a little Doctrine. And I've learned some JQuery and some Ajax.

    OOP and MVC is where I get confused currently, so I'll be steering this blog down that path initially in order to help me better understand and retain it.

    Lets see how it goes!