Tagged: MVC RSS Toggle Comment Threads | Keyboard Shortcuts

  • webscriptz 22:37 on 23/06/2011 Permalink | Reply
    Tags: , data, , MVC, , , , , ,   

    Using Our Models To Do Basic Queries On The DB 

    The application has an auto-generated model, Gii kindly provides the model once the database is created.

    01
    <?php
    02
    class Product extends CActiveRecord
    03
    {
    04
        /**
    05
         * The followings are the available columns in table 'Product':
    06
         * @var integer $id
    07
         * @var integer $brandId
    08
         * @var string $name
    09
         * @var string $price
    10
         */
    11
     
    12
        /**
    13
         * Returns the static model of the specified AR class.
    14
         * @return CActiveRecord the static model class
    15
         */
    16
        public static function model($className=__CLASS__)
    17
        {
    18
            return parent::model($className);
    19
        }
    20
     
    21
        /**
    22
         * @return string the associated database table name
    23
         */
    24
        public function tableName()
    25
        {
    26
            return 'Product';
    27
        }
    28
     
    29
        /**
    30
         * @return array validation rules for model attributes.
    31
         */
    32
        public function rules()
    33
        {
    34
            return array(
    35
                array('name','length','max'=>255),
    36
                array('price','length','max'=>8),
    37
                array('name, price', 'required'),
    38
            );
    39
        }
    40
     
    41
        /**
    42
         * @return array relational rules.
    43
         */
    44
        public function relations()
    45
        {
    46
            // NOTE: you may need to adjust the relation name and the related
    47
            // class name for the relations automatically generated below.
    48
            return array(
    49
                'brand' => array(self::BELONGS_TO, 'Brand', 'brandId'),
    50
                'categories' => array(self::MANY_MANY, 'Category', 'ProductCategory(productId, categoryId)'),
    51
            );
    52
        }
    53
     
    54
        /**
    55
         * @return array customized attribute labels (name=>label)
    56
         */
    57
        public function attributeLabels()
    58
        {
    59
            return array(
    60
                'id'=>'Id',
    61
                'brandId'=>'Brand',
    62
                'name'=>'Name',
    63
                'price'=>'Price',
    64
            );
    65
        }
    66
    }

    Enable your weblogger: this you will find in: /yourProject/protected/config/main.php

    By default your log array looks something like this: (Tip: IF you haven’t done this, and you find it hard to find you way in the file, comment everything you deem meaningful, use spaces and limit blocks of codes with comment of your choice)

    1
            'log'=>array(
    2
                'class'=>'CLogRouter',
    3
                'routes'=>array(
    4
                    array(
    5
                        'class'=>'CFileLogRoute',
    6
                        'levels'=>'error, warning',
    7
                    ),
    8
                ),
    9
            ),

    Let’s add in the CWebLogRoute so it looks like this.

    01
      'log'=>array(
    02
                'class'=>'CLogRouter',
    03
                'routes'=>array(
    04
                    array(
    05
                        'class'=>'CFileLogRoute',
    06
                        'levels'=>'error, warning',
    07
                    ),
    08
                    array(
    09
                        'class'=>'CWebLogRoute',
    10
                        'levels'=>'trace,info, error, warning',
    11
                    ),
    12
                ),
    13
            ),

    Visit the application and notice that at the bottom of the screen a table is shown displaying everything Yii does to make it possible for the website to be shown correctly. This is especially useful when you’re new to the Yii DB stuff.

    Let’s start by getting all of our products. If you are trying this tutorial, then please create a simple new installation, config the database settings in /protected/config/main.php and create your database with the proposed columns from the model seen earlier.

    You can test this in any controller, because the system already has a default SiteController in: /protected/controllers/siteController.php, this tutorial will use siteController.php with the view-file in: /protected/views/site/index.php

    So we’ll first modify our SiteController::actionIndex method.

    1
        public function actionIndex()
    2
        {
    3
            $this->render('index', array(
    4
                'Products' => Product::model()->findAll(),
    5
            ));
    6
        }

    Open the view-file related to the actionIndex() The system has an array that will be passed to our index view. This array contains ‘Products’ which will be usable as ‘$Products’ in our view: /protected/views/site/index.php

    01
    <?php $this->pageTitle=Yii::app()->name; ?>
    02
     
    03
    <h1>
    04
        Welcome, <?php echo Yii::app()->user->name; ?>!
    05
    </h1>
    06
    <table>
    07
    <?php foreach($Products AS $Product):?>
    08
        <tr>
    09
            <td><?php echo $Product->name;?></td>
    10
            <td><?php echo $Product->price;?></td>
    11
        </tr>
    12
    <?php endforeach;?>
    13
    </table>

    The system (Yii) writes the SQL statements for us thanks to the AR and everything behind that, but we got back an array of product objects.

    Now let’s use the ‘brand’ relation that is set in our Product model.

    Without changing the controller, we can simply change the view and add the line to output the brand name.

    1
    <td><?php echo $Product->brand->name;?></td>

    Now how did Yii do that? Look at the screen logger. You will see that it used the ‘lazy-loading’ technique to query the Brand table at that point.

    1
    Querying SQL: SELECT * FROM `Product`
    2
     
    3
    Querying SQL: SELECT `Product`.`id` AS `t0_c0`, t1.`id` AS `t1_c0`,
    4
    t1.`name` AS `t1_c1`, t1.`website` AS `t1_c2` FROM `Product` LEFT OUTER
    5
    JOIN `Brand` t1 ON (`Product`.`brandId`=t1.`id`) WHERE (`Product`.`id`=3)
    6
     
    7
    Querying SQL: SELECT `Product`.`id` AS `t0_c0`, t1.`id` AS `t1_c0`,
    8
    t1.`name` AS `t1_c1`, t1.`website` AS `t1_c2` FROM `Product` LEFT OUTER
    9
    JOIN `Brand` t1 ON (`Product`.`brandId`=t1.`id`) WHERE (`Product`.`id`=4)

    This is not the best way to go so let’s change the actionIndex in siteController.php

    1
        public function actionIndex()
    2
        {
    3
            // renders the view file 'protected/views/site/index.php'
    4
            // using the default layout 'protected/views/layouts/main.php'
    5
            $this->render('index', array(
    6
                'Products' => Product::model()->with(array('brand'))->findAll(),
    7
            ));
    8
        }

    One query is all that is needed for all the data to be collected.

    1
    Querying SQL: SELECT `Product`.`id` AS `t0_c0`, `Product`.`brandId` AS
    2
    `t0_c1`, `Product`.`name` AS `t0_c2`, `Product`.`price` AS `t0_c3`, t1.`id`
    3
    AS `t1_c0`, t1.`name` AS `t1_c1`, t1.`website` AS `t1_c2` FROM `Product` 
    4
    LEFT OUTER JOIN `Brand` t1 ON (`Product`.`brandId`=t1.`id`)

    The view file does not have to change for this. This technique is called eager-loading and has advantages over lazyloading sometimes.

    This tutorial is a modified tutorial from another website/blog that unfortunantly isn’t online anymore, domain is being sold by godaddy.com, so I search my archives to retrieve this on, and post him here, hence a few additions, deletes and rewrites from me.

     
  • webscriptz 22:16 on 23/06/2011 Permalink | Reply
    Tags: , , , , MVC, , , , , , ,   

    YiiFramework adding functions to your models 

    MVC has some principals to it, like the fat model principal that I’ll show in this tutorial and which is used in a lot of frameworks. I’m going to show how to add and use functions that can be added to a model.

    There are a few ways to add to a models that increase code re-usability. One way is to just add methods to the models, methods which can execute complex queries and make your controller thinner.

    The first example, a query that will get all products within a price range, it will need a limit and an offset for pagination, so in the Products model, the following function can be added:

    1
    public function findAllByPrice($min=0, $max=1000000, $offset = 0, $limit = 30) {
    2
        $Criteria = new CDbCriteria();
    3
        $Criteria->condition = "price >= :min AND price <=:max";
    4
        $Criteria->limit = $limit;
    5
        $Criteria->offset = $offset;
    6
        $Criteria->params = array ( ':min' => $min, ':max' => $max );
    7
        return $this->with(array('brand'))->findAll($Criteria);
    8
    }

    Now in any of the controlller files this method can be easily accessed and returns all of the ‘Product’ objects with a single line command:

    1
    $Products = Product::model()->findAllByPrice(100, 700, 0, 30);

    Another way to do the same is to:

    1
    public function getProducts($category){
    2
        return $this->findAll('categoryIdFk=:category', array(':category'=>$category));
    3
    }

    Let’s implement the first query using two named scope methods that I’ll create.

    1
    // Price Between - Named Scope ---------------------------------//
    2
    public function scopePriceBetween($min, $max) {
    3
        $Criteria = new CDbCriteria();
    4
        $Criteria->condition = "$this->tableName().price BETWEEN :min AND :max";
    5
        $Criteria->params = array(':min' => $min,   ':max' => $max);
    6
        $this->getDbCriteria()->mergeWith($Criteria);
    7
        return $this;
    8
    }

    Now an additional named scope for the limit element

    1
    //  Limit - Named Scope --------------------------------------//
    2
    public function scopeLimit($limit = 30, $offset = 0) {
    3
        $Criteria = new CDbCriteria();
    4
        $Criteria->limit = $limit;
    5
        $Criteria->offset = $offset;
    6
        $this->getDbCriteria()->mergeWith($Criteria);
    7
        return $this;
    8
    }

    Now we can simply use our named scopes to get our data back, and then we could continue to pile on named scopes to return our data.

    1
    $Products = Product::model()->scopePriceBetween(0, 5000) ->scopeLimit(30, 1)->findAll();

    The query that actually gets executed is simple and looks like this:

    1
    SELECT * FROM `Product` WHERE Product.price BETWEEN :MIN AND :MAX LIMIT 30 OFFSET 1

    This tutorial is a modified tutorial from another website/blog that unfortunantly isn’t online anymore, domain is being sold by godaddy.com, so I search my archives to retrieve this on, and post him here, hence a few additions, deletes and rewrites from me.

     
  • webscriptz 23:47 on 20/12/2009 Permalink | Reply
    Tags: , , MVC, , , , , ,   

    YII framework configuration 

    I’m toying with the Yii Framework for some time now and even if i cost me a lot of anger and frustration in the beginning I’m starting to like it more and more, alas I do have to say that the documentation isn’t always that clear and for someone who begins or who’ll write some large applications the configuration file can be a hassle so here’s my solution:

    Brake down the configuration file in multiple files, this will give you some speed disadvantage and some will  saying that I’m raping Yii framework purpose for speed but at least to me it seems more clear

    This is the protected.config/main.php

    dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
    'name'=>'WEBSITENAME',
    'modules'=>array(
    'users'=>array(
    //sub modules in the module users
    'modules'=>array(
    'messaging',
    'profile',
    'dashboard',
    )
    ),
    'about',
    'forums',
    ),
    // preloading 'log' component active loading
    'preload'=>array('log'),
    
    // autoloading model and component classes lazy loading
    // I make the difference between CformModel and CActiveRecord
    'import'=>array(
    'application.models.*',
    'application.models.forms.*',
    'application.models.database.*',
    ),
    
    // application components
    'components'=>array(
    // enable cookie-based authentication
    'user'=>array('allowAutoLogin'=>true),
    
    // data relinquished to database.php
    // for easy access and usability as also for the future
    // installation procedure, it's less to write to a file
    'db'=>include(dirname(__FILE__).'/database.php'),
    
    // for a better overview we exculded url routes to a seperate file
    'urlManager'=>include(dirname(__FILE__).'/routes.php'),
    
    //authentication component needs data from db for CdbConnection
    'authManager'=>array(
    'class'=>'CDbAuthManager',
    'connectionID'=>'db',
    'defaultRoles'=>array('authenticated', 'guest'),
    ),
    
    //security measures
    'request'=>array(
    'enableCsrfValidation'=>true,
    'enableCookieValidation'=>true,
    ),
    ),
    
    // application-level parameters that can be accessed
    // using Yii::app()->params['paramName']
    // uncomment the following if you want static params in the application
    //'params'=>array(include(dirname(__FILE__).'/params.php'))
    );

    database.php

    'CDbConnection',
    'connectionString'=>'mysql:host=localhost;dbname=mysql',
    //'connectionString'=>'pgsql:host=localhost;port=5432;dbname=mysql',
    'username' => 'root',
    'password' => '',
    );
    ?>
    

    routes.php

    'path', // path or get
    'urlSuffix' => '', //.html .whateverextentionyouwant
    'showScriptName' => true,
    'rules'=>array(
    'users/recovery/perimeterSecurity/'=>'users/recovery/perimeterSecurity',
    ),
    );
    ?>
    

    param.php

    //nothing in it at the moment

     
    • Cherry 10:58 on 30/12/2009 Permalink | Reply

      Hi,I’m trying Yii now.Almost everything could be done with Yii.But all the components,those how I configure ,will run.Something ,like,DB session…
      well,my english is so poor!

    • webscriptz 03:32 on 01/01/2010 Permalink | Reply

      I’m a bit torn between speed and programming luxury and because sometimes Yii is poorly documented, nice example code but not all the options are given actually sometimes very few.

      I’m currently doing models and testing them in Yii and i can’t get my head really around it, Codeigniter was really easy to use in the model logic but now what’s the logic, Model driven or controller driven because of the AR layer and the model sql query which seems implemented in the controllers. I thought controllers were just a gateway between view and model because it’s the model that usually contains all the logic not the controller.

  • webscriptz 21:23 on 14/03/2009 Permalink | Reply
    Tags: .htaccess, , , MVC, , , , views   

    CodeIgniter the views and .htaccess 

    I must admit that I not a huge fan of Frameworks and Patterns because:

    A) They make things complicated

    B) Subject you to some nasty code stuff and rules

    C) Because templating and Frameworks can be water and fire.

    Codeigniter on the opposite has some advantage on it side for the templating stuff. This is really a short explanation for a common problem in other framework.

    What to do if you want a nice folder structure or have different template styles, remember this is just a basic thing which happen to work in CI 1.7.


    function index(){
    $this->load->view('Themename/news/index);
    }

    Just add some slashes an it works so normally it should work if you would make an adaptation for themes too with a variable in it.

    The next thing was kind of hard to find on the web so let me share it. It’s for when you develop with CI and your not working in the root directory of your server.


    DirectoryIndex index.php
    RewriteEngine on
    RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|favicon\.ico)
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ ./index.php/$1 [L,QSA]

     
  • webscriptz 22:49 on 09/03/2009 Permalink | Reply
    Tags: , exp, mod_rewrite, MVC, ,   

    MVC again 

    I’ve grew bored of having to deal with some irritating PHP issues so I’ve turned my back to those and began testing codeIgniter. It seems strait forward but templating already has me intrigued with problems and mod_rewrite needs a look too I think :p .

     
    • webscriptz 15:25 on 11/03/2009 Permalink | Reply

      I must admit once you’ve read some tutorials it seems strait forward but well it seems i’ll have to toy with it to really know.

  • webscriptz 00:40 on 01/11/2008 Permalink | Reply
    Tags: , , , MVC,   

    Cakephp 

    Begin this week I began to experiment with cakephp but there’s a downside, Cake is something like rails but unfortunately the framework has less good tutorials.

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel