Many-to-many relationships – Phalcon

If you are working with Phalcon, you will probably need to establish a many-to-many relationship between models. While i was searching in the official documentation, this was not very clear for me at that time. I posted this question on the form, and i got the correct answer.

I will explain you here, step by step. As an example, we will think about the following database structure:

Article table:

CREATE TABLE IF NOT EXISTS `article` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
  `content` text CHARACTER SET latin1,
  `slug` varchar(160) CHARACTER SET latin1 NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `title` (`title`,`created_at`),
  KEY `slug` (`slug`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;

Category table:

CREATE TABLE IF NOT EXISTS `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET latin1 NOT NULL,
  `slug` varchar(255) CHARACTER SET latin1 DEFAULT NULL,
  `left_node` int(11) NOT NULL,
  `right_node` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`),
  KEY `idx_slug` (`slug`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;

articles_categories table:

CREATE TABLE IF NOT EXISTS `articles_categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `article_id` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `article_id` (`article_id`),
  KEY `category_id` (`category_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

ALTER TABLE `articles_categories`
  ADD CONSTRAINT `articles_categories_ibfk_1` FOREIGN KEY (`article_id`) REFERENCES `article` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `articles_categories_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

Article model:

hasManyToMany(
      "id",
      "Models\ArticlesCategories",
      "article_id",
      "category_id",
      "Models\Category",
      "id",
      array('alias' => 'categories')
    );
  }
}

Category model:

hasManyToMany(
      "id",
      "Models\ArticlesCategories",
      "category_id",
      "article_id",
      "Models\Article",
      "id",
      array('alias' => 'articles')
    );
  }
}

ArticlesCategories model:

belongsTo('category_id', 'Models\Category', 'id', 
      array('alias' => 'category')
    );
    $this->belongsTo('article_id', 'Models\Article', 'id', 
      array('alias' => 'article')
    );
  }
}

Easy, huh ? See the original post. I hope this was helpful 🙂

PHP Credit Card Validator – Class

If you ever need to validate credit card numbers, here is a simple validator class. Of course you can use it as simple as just defining validation rules in one array and use the php biult-in preg_match function to validate. But for the sake of good OOP practice, we need a class 🙂 . Well, i hope that this will help you. So, first we create the validator class:

setCreditCardRules();
    }

    /**
     * Set the rules for credit card validation
     *
     * @author  [email protected]
     * @since   May 2, 2012
     */
    private  function setCreditCardRules()
    {
        $this->rules['creditCard'] = array(
            'amex'     => '/^3[4|7]\\d{13}$/',
            'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
            'diners'   => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
            'disc'     => '/^(?:6011|650\\d)\\d{12}$/',
            'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
            'enroute'  => '/^2(?:014|149)\\d{11}$/',
            'jcb'      => '/^(3\\d{4}|2100|1800)\\d{11}$/',
            'maestro'  => '/^(?:5020|6\\d{3})\\d{12}$/',
            'mc'       => '/^5[1-5]\\d{14}$/',
            'solo'     => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
            'switch'   => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})' .
                          '\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4]' .
                          '[0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/',
            'visa'     => '/^4\\d{12}(\\d{3})?$/',
            'voyager'  => '/^8699[0-9]{11}$/',
            'fast'     => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3' .
                          '(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/'
            );
    }

    /**
     * Get available rules for credit card validation. In case you need
     * them to pass to another object(s) and you don't want to use
     * the validator
     *
     * @author  [email protected]
     * @since   May 2, 2012
     * @return  array
     */
    public function getCreditCardRules()
    {
        return $this->rules['creditCard'];
    }

    /**
     * The validator
     *
     * @author  [email protected]
     * @since   May 2, 2012
     * @param   string $cardType Card type as defined in setCreditCardRules()
     * @param   numeric $cardNumber Credit card number
     * @throws  \Exception
     */
    public function isValid($cardType, $cardNumber)
    {
        if(!isset($this->rules['creditCard'][$cardType]))
        {
            throw new \Exception('Invalid card type');
        }

        return preg_match($this->rules['creditCard'][$cardType], $cardNumber);
    }

}
?>

Easy, no ? Using it is very, very simple:

isValid($cardType, $cardNumber))
    {
        echo 'Credit card number is valid';
    }
    else
    {
        echo 'Invalid credit card number';
    }
?>

Hope it is useful for you. Cheers !