{"id":11917,"date":"2016-11-15T19:24:38","date_gmt":"2016-11-15T16:24:38","guid":{"rendered":"http:\/\/blog.belvg.com\/?p=11917"},"modified":"2025-02-11T13:12:57","modified_gmt":"2025-02-11T11:12:57","slug":"prestashop-mvc-part-1-creating-a-model","status":"publish","type":"post","link":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html","title":{"rendered":"Prestashop MVC. Part 1: Creating a Model"},"content":{"rendered":"<p>This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of information we decided to divide it into 3 parts. In the following part we are going to consider basic principles of creation and operation with a model. Moreover, you can find some information regarding this subject under the following <a href=\"http:\/\/doc.prestashop.com\/display\/PS16\/Accessing+the+database\">link.<\/a><\/p>\n<p><!--more--><\/p>\n<p>Let&#8217;s consider Category(\/classes\/Category.php) object as a model example. Category class is inherited from ObjectModel:<\/p>\n<pre class=\"lang:php decode:true \">class CategoryCore extends ObjectModel\r\n{\r\n    \tpublic $id;\r\n\r\n   \t \/** @var int category ID *\/\r\n   \t public $id_category;\r\n\r\n    \t\/** @var string Name *\/\r\n    \tpublic $name;\r\n\r\n    \t&#8230;\r\n}\r\n<\/pre>\n<p>Which in turn implements <a href=\"https:\/\/en.wikipedia.org\/wiki\/Entity&#8211;relationship_model\">ERM<\/a> (entity-relationship model) in Prestashop, in other words every row in database table subsumes to entity and object, that very simplifies data management.<\/p>\n<p>Basing on Category class example we are going to create new tables in a database to build up our model:<\/p>\n<pre class=\"lang:php decode:true\">CREATE TABLE IF NOT EXISTS `ps_category` (\r\n  `id_category` int(10) unsigned NOT NULL AUTO_INCREMENT,\r\n  `id_parent` int(10) unsigned NOT NULL,\r\n  `id_shop_default` int(10) unsigned NOT NULL DEFAULT '1',\r\n  ...\r\n  `is_root_category` tinyint(1) NOT NULL DEFAULT '0',\r\n  PRIMARY KEY (`id_category`),\r\n  &#8230;\r\n) ENGINE=InnoDB  DEFAULT CHARSET=utf8;\r\n<\/pre>\n<pre class=\"lang:php decode:true \">CREATE TABLE IF NOT EXISTS `ps_category_lang` (\r\n  `id_category` int(10) unsigned NOT NULL,\r\n  `id_shop` int(11) unsigned NOT NULL DEFAULT '1',\r\n  `id_lang` int(10) unsigned NOT NULL,\r\n  `name` varchar(128) NOT NULL,\r\n  `description` text,\r\n  ...\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n<\/pre>\n<pre class=\"lang:php decode:true \">CREATE TABLE IF NOT EXISTS `ps_category_shop` (\r\n  `id_category` int(11) NOT NULL,\r\n  `id_shop` int(11) NOT NULL,\r\n  `position` int(10) unsigned NOT NULL DEFAULT '0',\r\n  PRIMARY KEY (`id_category`,`id_shop`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n<\/pre>\n<pre class=\"lang:php decode:true \">CREATE TABLE IF NOT EXISTS `ps_category_group` (\r\n  `id_category` int(10) unsigned NOT NULL,\r\n  `id_group` int(10) unsigned NOT NULL,\r\n  PRIMARY KEY (`id_category`,`id_group`),\r\n  KEY `id_category` (`id_category`),\r\n  KEY `id_group` (`id_group`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n<\/pre>\n<p>In order of creating new tables it is necessary to follow some rules:<\/p>\n<p>1. A name of unique table key is built in accordance with the rule:<\/p>\n<pre class=\"lang:php decode:true \">'id_' . $name_table(without prefix, CREATE TABLE IF NOT EXISTS `ps_category` &#8230;  - `id_category` int(11) NOT NULL, ...)<\/pre>\n<p>2. If there are any data in different languages in the entity, then you must create a table name with postfix:<\/p>\n<pre class=\"lang:php decode:true \">$name_table .  '_lang' (CREATE TABLE IF NOT EXISTS `ps_category_lang` &#8230;)<\/pre>\n<ul>\n<li>A table should contain at least 3 columns: &#8216;id_name_table&#8217;, &#8216;id_lang&#8217;, &#8216;id_shop&#8217;<\/li>\n<\/ul>\n<p>3. In case entity has to work with multistore, it is necessary to create a table name with postfix:<\/p>\n<pre class=\"lang:php decode:true \">$name_table . '_shop' ( CREATE TABLE IF NOT EXISTS `ps_category_shop` &#8230;)<\/pre>\n<ul>\n<li>A table should contain at least 2 columns: &#8216;id_name_table&#8217;, &#8216;id_shop&#8217;<\/li>\n<\/ul>\n<p>4. In case you need to limit an access to the entity for different user groups, then you should create a table name with postfix: $name_table . &#8216;_group&#8217; (CREATE TABLE IF NOT EXISTS `ps_category_group` &#8230;). Access restriction implementation is not inherited from ObjectModel class, and it will require to create additional methods in your entity. Let&#8217;s consider it below.<\/p>\n<ul>\n<li>A table should contain at least 2 columns: &#8216;id_name_table&#8217;, &#8216;id_shop&#8217;<\/li>\n<\/ul>\n<p>5. &#8216;id_name_table&#8217; without AUTO_INCREMENT in all tables except of the first, because data could be duplicated and it may lead to exception.<\/p>\n<p>Model Class:<\/p>\n<pre class=\"lang:php decode:true \">class CategoryCore extends ObjectModel\r\n{\r\n    public $id;\r\n\r\n    \/** @var int category ID *\/\r\n    public $id_category;\r\n\r\n    \/** @var string Name *\/\r\n    public $name;\r\n\r\n    \/** @var bool Status for display *\/\r\n    public $active = 1;\r\n\r\n    \/** @var  int category position *\/\r\n    public $position;\r\n\r\n    ...\r\n<\/pre>\n<pre class=\"lang:php decode:true \">    \/**\r\n     * @see ObjectModel::$definition\r\n     *\/\r\n    public static $definition = array(\r\n        'table' =&gt; 'category',\r\n        'primary' =&gt; 'id_category',\r\n        'multilang' =&gt; true,\r\n        'multilang_shop' =&gt; true,\r\n        'fields' =&gt; array(\r\n            'nleft' =&gt;                array('type' =&gt; self::TYPE_INT, 'validate' =&gt; 'isUnsignedInt'),\r\n            'nright' =&gt;            array('type' =&gt; self::TYPE_INT, 'validate' =&gt; 'isUnsignedInt'),\r\n            'level_depth' =&gt;        array('type' =&gt; self::TYPE_INT, 'validate' =&gt; 'isUnsignedInt'),\r\n            'active' =&gt;            array('type' =&gt; self::TYPE_BOOL, 'validate' =&gt; 'isBool', 'required' =&gt; true),\r\n            'id_parent' =&gt;            array('type' =&gt; self::TYPE_INT, 'validate' =&gt; 'isUnsignedInt'),\r\n            'id_shop_default' =&gt;    array('type' =&gt; self::TYPE_INT, 'validate' =&gt; 'isUnsignedId'),\r\n            ...\r\n            \/* Lang fields *\/\r\n            'name' =&gt;                array('type' =&gt; self::TYPE_STRING, 'lang' =&gt; true, 'validate' =&gt; 'isCatalogName', 'required' =&gt; true, 'size' =&gt; 128),\r\n            'link_rewrite' =&gt;        array('type' =&gt; self::TYPE_STRING, 'lang' =&gt; true, 'validate' =&gt; 'isLinkRewrite', 'required' =&gt; true, 'size' =&gt; 128),\r\n            ...\r\n        ),\r\n    );\r\n<\/pre>\n<p>As you can see from the example, each column of the table corresponds to a class property:<\/p>\n<p><em>`name` varchar(128) NOT NULL, &#8211; public $name;<\/em><\/p>\n<p><em>`id_category` int(10) unsigned NOT NULL, &#8211;&#160; public $id_category;<\/em><\/p>\n<p>To create a connection between model and tables it is necessary to specify the name of the table in <em>$definition <\/em>property, as well as the name of the unique key and determine whether our model will work with several languages:<\/p>\n<pre class=\"lang:php decode:true \">public static $definition = array(\r\n        'table' =&gt; 'category',\r\n        'primary' =&gt; 'id_category',\r\n        'multilang' =&gt; true,\r\n        'multilang_shop' =&gt; true,\r\n        &#8230;\r\n<\/pre>\n<p>Those fields that hold data in different languages should have &#8216;lang&#8217; index with &#8216;true&#8217; value:<\/p>\n<pre class=\"lang:php decode:true \">('name'  =&gt;  array('type' =&gt; self::TYPE_STRING, 'lang' =&gt; true, 'validate' =&gt; 'isCatalogName', 'required' =&gt; true, 'size' =&gt; 128)<\/pre>\n<p>And in case of using a multistore: &#8216;shop&#8217; =&gt; true<\/p>\n<pre class=\"lang:php decode:true \">('id_category_default' =&gt;        array('type' =&gt; self::TYPE_INT, 'shop' =&gt; true, 'validate' =&gt; 'isUnsignedId'), property from Product class)<\/pre>\n<p>It is necessary to add <em>Shop::addTableAssociation()<\/em> method in the model constructor, to configure the operation of model with multistore:<\/p>\n<pre class=\"lang:php decode:true \">public function __construct($id_name_table = null, $id_lang = null, $id_shop = null) \r\n{\r\n\tShop::addTableAssociation('name_table', array('type' =&gt; 'shop'));\r\n       \t parent::__construct($id_name_table, $id_lang, $id_shop);\r\n}\r\n<\/pre>\n<p>Let&#8217;s consider an implementation of permissions restriction by using &#8216;ps_category_group&#8217; table:<\/p>\n<pre class=\"lang:php decode:true \">\/\/ \/classes\/Category.php\r\n\/**\r\n* Update customer groups associated to the object\r\n*\r\n* @param array $list groups\r\n*\/\r\npublic function updateGroup($list)\r\n{\r\n\t$this-&gt;cleanGroups();\r\n\tif (empty($list)) {\r\n\t\t$list = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), \t\t\t\t\tConfiguration::get('PS_GUEST_GROUP'), \t\t\t\t\t\tConfiguration::get('PS_CUSTOMER_GROUP'));\r\n\t}\r\n\t$this-&gt;addGroups($list);\r\n}\r\n\r\n\r\n\r\n\r\npublic function cleanGroups()\r\n{\r\n\treturn Db::getInstance()-&gt;delete('category_group', 'id_category = '.(int)$this-&gt;id);\r\n}\r\n\r\npublic function addGroups($groups)\r\n{\r\n\tforeach ($groups as $group) {\r\n\t\tif ($group !== false) {\r\n\t\t\tDb::getInstance()-&gt;insert('category_group', array('id_category' =&gt; (int)$this-&gt;id, \t\t\t'id_group' =&gt; (int)$group));\r\n\t\t}\r\n\t}\r\n}\r\n\r\npublic function getGroups()\r\n{\r\n\t$cache_id = 'Category::getGroups_'.(int)$this-&gt;id;\r\n\tif (!Cache::isStored($cache_id)) {\r\n\t\t$result = Db::getInstance()-&gt;executeS('\r\n\t\t\tSELECT cg.`id_group`\r\n\t\t\tFROM '._DB_PREFIX_.'category_group cg\r\n\t\t\tWHERE cg.`id_category` = '.(int)$this-&gt;id);\r\n\t\t$groups = array();\r\n\t\tforeach ($result as $group) {\r\n\t\t\t$groups[] = $group['id_group'];\r\n\t\t}\r\n\t\tCache::store($cache_id, $groups);\r\n\t\treturn $groups;\r\n\t}\r\n\treturn Cache::retrieve($cache_id);\r\n}\r\n\r\n\/\/ \/controllers\/front\/CategoryController.php\r\n\/**\r\n* checkAccess return true if id_customer is in a group allowed to see this category.\r\n*\r\n* @param mixed $id_customer\r\n* @access public\r\n* @return bool true if access allowed for customer $id_customer\r\n*\/\r\npublic function checkAccess($id_customer)\r\n{\r\n\t$cache_id = 'Category::checkAccess_'.(int)$this-&gt;id.'-'.$id_customer.(!$id_customer ? '-'.\t\t(int)Group::getCurrent()-&gt;id : '');\r\n\tif (!Cache::isStored($cache_id)) {\r\n\t\tif (!$id_customer) {\r\n\t\t\t$result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)-&gt;getValue('\r\n\t\t\t\tSELECT ctg.`id_group`\r\n\t\t\t\tFROM '._DB_PREFIX_.'category_group ctg\r\n\t\t\t\tWHERE ctg.`id_category` = '.(int)$this-&gt;id.' AND ctg.`id_group` = '.\t\t\t\t\t(int)Group::getCurrent()-&gt;id);\r\n\t\t} else {\r\n\t\t\t$result = (bool)Db::getInstance(_PS_USE_SQL_SLAVE_)-&gt;getValue('\r\n\t\t\t\t\tSELECT ctg.`id_group`\r\n\t\t\t\t\tFROM '._DB_PREFIX_.'category_group ctg\r\n\t\t\t\t\tINNER JOIN '._DB_PREFIX_.'customer_group cg on \t\t\t\t\t\t\t(cg.`id_group` = ctg.`id_group` AND cg.`id_customer` = '.(int)\t\t\t\t\t\t$id_customer.')\r\n\t\t\t\t\tWHERE ctg.`id_category` = '.(int)$this-&gt;id);\r\n\t\t}\r\n\t\tCache::store($cache_id, $result);\r\n\t\treturn $result;\r\n\t}\r\n\treturn Cache::retrieve($cache_id);\r\n}\r\n<\/pre>\n<p>Unfortunately, ObjectModel and controller implementation does not support its realization and you will have to add them by yourself.<\/p>\n<p>As the result we are getting model class, in which the following methods are already determined:<\/p>\n<ol>\n<li>add($autodate = true, $nullValues = false) &#8211; Save current object to database (add or update).<\/li>\n<li>Delete() &#8211; Delete current object from database.<\/li>\n<li>save($nullValues = false, $autodate = true) &#8211; Save current object to database (add or update).<\/li>\n<li>update($nullValues = false) &#8211; Update current object to database.<\/li>\n<\/ol>\n<p>A simple example of the model:<\/p>\n<pre class=\"lang:php decode:true \">\t$context = Context::getContext();\r\n\t$id_category = 12;\r\n\t$category = new Category((int)$id_category, $context-&gt;language-&gt;id);\r\n\t$category-&gt;active = $category-&gt;active == 1 ? 0 : 1;\r\n\t$category-&gt;name = &#8216;New name&#8217;;\r\n\t$category-&gt;save();\r\n<\/pre>\n<p>After the execution of a code in &#8216;ps_category&#8217; table, in the string with &#8216;id_category&#8217; = 12, &#8216;active&#8217; field will change its value to opposite or will stay the same. &#8216;Name&#8217; property, which is determined in &#8216;ps_category_lang&#8217; table will be saved at the same place in the current language. But if you want to save it in several languages, do as follows:<\/p>\n<pre class=\"lang:php decode:true \">$id_category = 12;\r\n$category = new Category((int)$id_category);\r\n$category-&gt;active = $category-&gt;active == 1 ? 0 : 1;\r\n\r\nforeach (Language::getLanguages(true) as $lang){\r\n\t$tab-&gt;name[$lang['id_lang']] = &#8216;New name&#8217;;\/\/for all languages\r\n}\r\n$category-&gt;save();\r\n<\/pre>\n<p>Properties that are related to &#8216;ps_category_shop&#8217; table will be saved automatically for the current store, but getting the value list from database will require to use Shop::addSqlAssociation() method. This method adds JOIN into sql request to connect entity fields selection from the current store.<\/p>\n<pre class=\"lang:php decode:true \">\/**\r\n* Return available categories\r\n*\r\n* @param int $id_lang Language ID\r\n* @param bool $active return only active categories\r\n* @return array Categories\r\n*\/\r\npublic static function getCategories($id_lang = false, $active = true, $order = true, $sql_filter = '', \t$sql_sort = '', $sql_limit = '')\r\n\t{\r\n\t\tif (!Validate::isBool($active)) {\r\n\t\t\tdie(Tools::displayError());\r\n\t\t}\r\n\t\t$result = Db::getInstance(_PS_USE_SQL_SLAVE_)-&gt;executeS('SELECT *\r\n\t\t\tFROM `'._DB_PREFIX_.'category` c\r\n\t\t\t'.Shop::addSqlAssociation('category', 'c').'\r\n\t\t\tLEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON c.`id_category` = \t\t\t\t\tcl.`id_category`'.Shop::addSqlRestrictionOnLang('cl').'\r\n\t\t\tWHERE 1 '.$sql_filter.' '.($id_lang ? 'AND `id_lang` = '.(int)$id_lang : '').'\r\n\t\t\t'.($active ? 'AND `active` = 1' : '').'\r\n\t\t\t'.(!$id_lang ? 'GROUP BY c.id_category' : '').'\r\n\t\t\t'.($sql_sort != '' ? $sql_sort : 'ORDER BY c.`level_depth` ASC, \t\t\tcategory_shop.`position` \t\tASC').'\r\n\t\t\t'.($sql_limit != '' ? $sql_limit : '')\r\n\t\t);\r\n\t...\r\n<\/pre>\n<p>And now let&#8217;s take a look how model operates with AdminController. AdminController is intended for data management in backend. Usually it displays lists of categories, products, editing forms. Look how easy it is to connect a module to controller (based on \/controllers\/admin\/AdminCategoriesController.php):<\/p>\n<pre class=\"lang:php decode:true \">public function __construct()\r\n{\r\n\t$this-&gt;bootstrap = true;\r\n\t$this-&gt;table = 'category';\r\n\t$this-&gt;className = 'Category';\r\n\t$this-&gt;lang = true;\r\n\t$this-&gt;deleted = false;\r\n\t$this-&gt;explicitSelect = true;\r\n\t$this-&gt;_defaultOrderBy = 'position';\r\n\t$this-&gt;allow_export = true;\r\n\r\n\t$this-&gt;context = Context::getContext();\r\n\r\n\t$this-&gt;fieldImageSettings = array(\r\n\t\t'name' =&gt; 'image',\r\n\t\t'dir' =&gt; 'c'\r\n\t);\r\n\r\n\t$this-&gt;fields_list = array(\r\n\t\t'id_category' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('ID'),\r\n\t\t\t'align' =&gt; 'center',\r\n\t\t\t'class' =&gt; 'fixed-width-xs'\r\n\t\t),\r\n\t\t'name' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('Name')\r\n\t\t),\r\n\t\t'description' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('Description'),\r\n\t\t\t'callback' =&gt; 'getDescriptionClean',\r\n\t\t\t'orderby' =&gt; false\r\n\t\t),\r\n\t...\r\n<\/pre>\n<p>Here we got 2 most important properties in controller to operate with a model:<\/p>\n<pre class=\"lang:php decode:true \">\t$this-&gt;table = 'category'; \/\/name table of entity\r\n\t$this-&gt;className = 'Category'; \/\/name class model entity\r\n<\/pre>\n<p>And if you need to output entity list (rows of tables in your database) in your controller, then just specify the model properties names in $this-&gt;fields_list property:<\/p>\n<pre class=\"lang:php decode:true \">$this-&gt;fields_list = array(\r\n\t\t'id_category' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('ID'),\r\n\t\t\t'align' =&gt; 'center',\r\n\t\t\t'class' =&gt; 'fixed-width-xs'\r\n\t\t),\r\n\t\t'name' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('Name')\r\n\t\t),\r\n\t\t'description' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('Description'),\r\n\t\t\t'callback' =&gt; 'getDescriptionClean',\r\n\t\t\t'orderby' =&gt; false\r\n\t\t),\r\n\r\n\tclass CategoryCore extends ObjectModel\r\n\t{\r\n   \t\t public $id;\r\n\r\n   \t\t \/** @var int category ID *\/\r\n    \t\tpublic $id_category;\r\n\r\n   \t\t \/** @var string Name *\/\r\n   \t\t public $name;\r\n\r\n    \t\t\/** @var bool Status for display *\/\r\n    \t\tpublic $active = 1;\r\n\r\n   \t\t \/** @var  int category position *\/\r\n    \t\tpublic $position;\r\n<\/pre>\n<p>It&#8217;s much easier to edit the data. Just create a form and make sure that fields names are identical to model properties names.<\/p>\n<pre class=\"lang:php decode:true\">public function renderForm()\r\n{\r\n\t&#8230;\r\n\r\n\t$this-&gt;fields_form = array(\r\n\t\t'tinymce' =&gt; true,\r\n\t\t'legend' =&gt; array(\r\n\t\t\t'title' =&gt; $this-&gt;l('Category'),\r\n\t\t\t'icon' =&gt; 'icon-tags'\r\n\t\t),\r\n\t\t'input' =&gt; array(\r\n\t\t\tarray(\r\n\t\t\t\t'type' =&gt; 'text',\r\n\t\t\t\t'label' =&gt; $this-&gt;l('Name'),\r\n\t\t\t\t'name' =&gt; 'name', \/** @var string Name *\/\r\n   \t\t\t\t \t\t\t\/\/public $name;\r\n\t\t\t\t'lang' =&gt; true,\r\n\t\t\t\t'required' =&gt; true,\r\n\t\t\t\t'class' =&gt; 'copy2friendlyUrl',\r\n\t\t\t\t'hint' =&gt; $this-&gt;l('Invalid characters:').' &lt;&gt;;=#{}',\r\n\t\t\t),\r\n\t\t\tarray(\r\n\t\t\t\t'type' =&gt; 'switch',\r\n\t\t\t\t'label' =&gt; $this-&gt;l('Displayed'),\r\n\t\t\t\t'name' =&gt; 'active', \/** @var bool Status for display *\/\r\n    \t\t\t\t\t\t\t\/\/public $active = 1;\r\n\t\t\t\t'required' =&gt; false,\r\n\t\t\t\t'is_bool' =&gt; true,\r\n\t\t\t\t'values' =&gt; array(\r\n\t\t\t\t\tarray(\r\n\t\t\t\t\t\t'id' =&gt; 'active_on',\r\n\t\t\t\t\t\t'value' =&gt; 1,\r\n\t\t\t\t\t\t'label' =&gt; $this-&gt;l('Enabled')\r\n\t\t\t\t\t),\r\n\t\t\t\t\tarray(\r\n\t\t\t\t\t\t'id' =&gt; 'active_off',\r\n\t\t\t\t\t\t'value' =&gt; 0,\r\n\t\t\t\t\t\t'label' =&gt; $this-&gt;l('Disabled')\r\n\t\t\t\t\t)\r\n\t\t\t\t)\r\n\t\t\t),\r\n<\/pre>\n<p>Creation, updating and filling out the form and list fields are performed by AdminController, and it does not require any development of additional logic of saving, deleting or updating.<\/p>\n<p>Pre-save validation is performed by using the settings specified in &#8216;fields&#8217; array of <em>$definition<\/em> model property&#160; ( &#8216;active&#8217; =&gt; array(&#8216;type&#8217; =&gt; self::TYPE_BOOL, &#8216;validate&#8217; =&gt; &#8216;isBool&#8217;, &#8216;required&#8217; =&gt; true),). It&#8217;s very important to name a unique key in the first table in accordance with the rule <em>&#8216;id_&#8217; . $name_table &#8211; &#8216;id_category&#8217;. <\/em>This will help to avoid problems with data updating and deleting.<\/p>\n<p>As we described above, the creation and using of a model in Prestashop is pretty easy process. Managing the model in admin area is rather simple and it doesn&#8217;t require monotypic implementation of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Create,_read,_update_and_delete\">CRUD<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of &#8230;","protected":false},"author":2,"featured_media":11918,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"image","meta":{"_acf_changed":false,"footnotes":""},"categories":[15,520,461,522],"tags":[],"class_list":["post-11917","post","type-post","status-publish","format-image","has-post-thumbnail","hentry","category-prestashop","category-prestashop-custom-development","category-prestashop-development","category-prestashop-speed-optimization","post_format-image"],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of information we decided to divide it into 3 parts. In the following part we are going to consider basic principles of creation and operation with a model.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Pavel Novitsky\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#article\",\"name\":\"Prestashop MVC. Part 1: Creating a Model | BelVG Blog\",\"headline\":\"Prestashop MVC. Part 1: Creating a Model\",\"author\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/author\\\/luge#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#organization\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/belvg.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/11\\\/Prestashop-MVC1.jpg\",\"width\":737,\"height\":200,\"caption\":\"Prestashop MVC. Part 1: Creating a Model\"},\"datePublished\":\"2016-11-15T19:24:38+02:00\",\"dateModified\":\"2025-02-11T13:12:57+02:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#webpage\"},\"articleSection\":\"Prestashop, PrestaShop Custom Development, Prestashop Development, PrestaShop Speed Optimization, Image\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/belvg.com\\\/blog\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/category\\\/prestashop#listItem\",\"name\":\"Prestashop\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/category\\\/prestashop#listItem\",\"position\":2,\"name\":\"Prestashop\",\"item\":\"https:\\\/\\\/belvg.com\\\/blog\\\/category\\\/prestashop\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#listItem\",\"name\":\"Prestashop MVC. Part 1: Creating a Model\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#listItem\",\"position\":3,\"name\":\"Prestashop MVC. Part 1: Creating a Model\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/category\\\/prestashop#listItem\",\"name\":\"Prestashop\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#organization\",\"name\":\"BelVG Blog\",\"description\":\"Magento and Prestashop articles\",\"url\":\"https:\\\/\\\/belvg.com\\\/blog\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/author\\\/luge#author\",\"url\":\"https:\\\/\\\/belvg.com\\\/blog\\\/author\\\/luge\",\"name\":\"Pavel Novitsky\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2c4388e3468896377123f434a9a2a2d64f479816da1570f85619b074102127b7?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Pavel Novitsky\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#webpage\",\"url\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html\",\"name\":\"Prestashop MVC. Part 1: Creating a Model | BelVG Blog\",\"description\":\"This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of information we decided to divide it into 3 parts. In the following part we are going to consider basic principles of creation and operation with a model.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/author\\\/luge#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/author\\\/luge#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/belvg.com\\\/blog\\\/wp-content\\\/uploads\\\/2016\\\/11\\\/Prestashop-MVC1.jpg\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html\\\/#mainImage\",\"width\":737,\"height\":200,\"caption\":\"Prestashop MVC. Part 1: Creating a Model\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/prestashop-mvc-part-1-creating-a-model.html#mainImage\"},\"datePublished\":\"2016-11-15T19:24:38+02:00\",\"dateModified\":\"2025-02-11T13:12:57+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/belvg.com\\\/blog\\\/\",\"name\":\"BelVG Blog\",\"description\":\"Magento and Prestashop articles\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/belvg.com\\\/blog\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Prestashop MVC. Part 1: Creating a Model | BelVG Blog","description":"This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of information we decided to divide it into 3 parts. In the following part we are going to consider basic principles of creation and operation with a model.","canonical_url":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#article","name":"Prestashop MVC. Part 1: Creating a Model | BelVG Blog","headline":"Prestashop MVC. Part 1: Creating a Model","author":{"@id":"https:\/\/belvg.com\/blog\/author\/luge#author"},"publisher":{"@id":"https:\/\/belvg.com\/blog\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/belvg.com\/blog\/wp-content\/uploads\/2016\/11\/Prestashop-MVC1.jpg","width":737,"height":200,"caption":"Prestashop MVC. Part 1: Creating a Model"},"datePublished":"2016-11-15T19:24:38+02:00","dateModified":"2025-02-11T13:12:57+02:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#webpage"},"isPartOf":{"@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#webpage"},"articleSection":"Prestashop, PrestaShop Custom Development, Prestashop Development, PrestaShop Speed Optimization, Image"},{"@type":"BreadcrumbList","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/#listItem","position":1,"name":"Home","item":"https:\/\/belvg.com\/blog\/","nextItem":{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/category\/prestashop#listItem","name":"Prestashop"}},{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/category\/prestashop#listItem","position":2,"name":"Prestashop","item":"https:\/\/belvg.com\/blog\/category\/prestashop","nextItem":{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#listItem","name":"Prestashop MVC. Part 1: Creating a Model"},"previousItem":{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#listItem","position":3,"name":"Prestashop MVC. Part 1: Creating a Model","previousItem":{"@type":"ListItem","@id":"https:\/\/belvg.com\/blog\/category\/prestashop#listItem","name":"Prestashop"}}]},{"@type":"Organization","@id":"https:\/\/belvg.com\/blog\/#organization","name":"BelVG Blog","description":"Magento and Prestashop articles","url":"https:\/\/belvg.com\/blog\/"},{"@type":"Person","@id":"https:\/\/belvg.com\/blog\/author\/luge#author","url":"https:\/\/belvg.com\/blog\/author\/luge","name":"Pavel Novitsky","image":{"@type":"ImageObject","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/2c4388e3468896377123f434a9a2a2d64f479816da1570f85619b074102127b7?s=96&d=mm&r=g","width":96,"height":96,"caption":"Pavel Novitsky"}},{"@type":"WebPage","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#webpage","url":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html","name":"Prestashop MVC. Part 1: Creating a Model | BelVG Blog","description":"This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of information we decided to divide it into 3 parts. In the following part we are going to consider basic principles of creation and operation with a model.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/belvg.com\/blog\/#website"},"breadcrumb":{"@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#breadcrumblist"},"author":{"@id":"https:\/\/belvg.com\/blog\/author\/luge#author"},"creator":{"@id":"https:\/\/belvg.com\/blog\/author\/luge#author"},"image":{"@type":"ImageObject","url":"https:\/\/belvg.com\/blog\/wp-content\/uploads\/2016\/11\/Prestashop-MVC1.jpg","@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html\/#mainImage","width":737,"height":200,"caption":"Prestashop MVC. Part 1: Creating a Model"},"primaryImageOfPage":{"@id":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html#mainImage"},"datePublished":"2016-11-15T19:24:38+02:00","dateModified":"2025-02-11T13:12:57+02:00"},{"@type":"WebSite","@id":"https:\/\/belvg.com\/blog\/#website","url":"https:\/\/belvg.com\/blog\/","name":"BelVG Blog","description":"Magento and Prestashop articles","inLanguage":"en-US","publisher":{"@id":"https:\/\/belvg.com\/blog\/#organization"}}]}},"aioseo_meta_data":{"post_id":"11917","title":"Prestashop MVC. Part 1: Creating a Model | #site_title","description":"This article is dedicated to the Model-view-controller in Prestashop CMS. Due to the amount of information we decided to divide it into 3 parts. In the following part we are going to consider basic principles of creation and operation with a model.","keywords":null,"keyphrases":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_image_url":null,"twitter_title":null,"twitter_description":null,"schema_type":"default","schema_type_options":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"limit_modified_date":false,"ai":null,"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"created":"2026-11-03 18:37:25","updated":"2026-11-03 18:37:25"},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/belvg.com\/blog\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/belvg.com\/blog\/category\/prestashop\" title=\"Prestashop\">Prestashop<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">\u00bb<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tPrestashop MVC. Part 1: Creating a Model\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/belvg.com\/blog\/"},{"label":"Prestashop","link":"https:\/\/belvg.com\/blog\/category\/prestashop"},{"label":"Prestashop MVC. Part 1: Creating a Model","link":"https:\/\/belvg.com\/blog\/prestashop-mvc-part-1-creating-a-model.html"}],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/posts\/11917","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/comments?post=11917"}],"version-history":[{"count":-3,"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/posts\/11917\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/media\/11918"}],"wp:attachment":[{"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/media?parent=11917"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/categories?post=11917"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/belvg.com\/blog\/wp-json\/wp\/v2\/tags?post=11917"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}