Category Archives: Yii 2 Tutorial

Yii 2 Create Method on Controller

Greetings to everyone from around the world who follows this blog. Programming knowledge does not recognize borders, which really points to how superficial borders are. I know I’ve said that before, but everytime I get a supportive email from someone on the other side of the planet, it really hits home.

I also appreciate all the positive comments, reviews, and word-of-mouth referrals on my book, Yii 2 For Beginners. Readers of the book have been very helpful in elevating the quality of the book by pointing out typos and bugs. I’m happy to say as of the last update, the code in the book is 100% working. Updates are free for the life of the book and I plan on adding material to the book several times a year.

So for those who are unfamiliar with Yii 2 or have never worked with a PHP framework before, I want to demonstrate just how powerful a single method on the Yii 2 Framework can be. This insight came to me as I was working on an idea for a 2nd book, a book on beginning PHP, for people who have never programmed before.

Anyway, I wanted to simulate a framework to teach PHP fundamentals. I didn’t build an actual framework for the following reasons:

1. That’s too intense for beginning PHP.

2. It would take me a 100 years to write the book.

3. It would be a 100 years of wasted time.

The reason why I say it would be wasted time is because of how great the Yii 2 framework is. It makes the idea of building a framework from scratch a bit silly, unless you have very good reason to do so. Why reinvent the wheel, especially when we have such an amazing wheel to work with in the first place?

Anyway, this was made abundantly clear to me as I was staring at the code I made for my simulated controller code. I used a switch statement to simulate individual actions, and this is what the create action looks like. I’ll explain each section, but to start, here it is in one ugly, proceedural block:


case('/mysong/src/controllers/songcontroller.php/create' == $uri):
                      
            if (isset($_POST)){
                
                $post = Security::sanitizeInput($_POST['form_token']);
                $session = Security::sanitizeInput($_SESSION['form_token']);
            }
            
            if (isset($_POST) && Security::matchTokens($post, $session)){
                       
            $song_name = Security::sanitizeInput($_POST['song_name']);
            $visibility = Security::sanitizeInput($_POST['visibility']);
            $video_source = Security::sanitizeInput($_POST['video_source']);
            $video_is_featured = Security::sanitizeInput(isset($_POST['video_is_featured']));
            $video_is_active_item = Security::sanitizeInput(isset($_POST['video_is_active_item']));

            if ($video_is_active_item == true){
                
                $video_is_active_item = 1;
                
            } else {
                
                $video_is_active_item = 0;
            }
            
            if ($video_is_featured == true){
                
                $video_is_featured = 1;
                
            } else {
                
                $video_is_featured = 0;
                
            }
            
            if (!Validators::validateDropDownOption($visibility)){
                
                $visibility = 'Private';
                
            }                      
          
       $cmd = new Query;
       
       $sql = 'INSERT INTO song (song_name, visibility, video_source, 
               video_is_featured, video_is_active_item) VALUES (:song_name, 
               :visibility, :video_source, :video_is_featured, 
               :video_is_active_item);';
       
       $cmd->query($sql); 
       
       $cmd->bind(':song_name', $song_name);
       $cmd->bind(':visibility', $visibility); 
       $cmd->bind(':video_source', $video_source);
       $cmd->bind(':video_is_featured', $video_is_featured);
       $cmd->bind(':video_is_active_item', $video_is_active_item); 

       $cmd->execute();
       
       $cmd->closeDb();
       
            $url = Url::toSong($song_name);
            return header('Location: ' . $url);
           
            break;
            
        } else {
        
             $url = Url::toSongCreate();
             return header('Location: ' . $url);   
             break;
        }

Anyway, we can step through this quickly. If we have post data, make sure the tokens match to prevent CSRF:


 if (isset($_POST)){
                
     $post = Security::sanitizeInput($_POST['form_token']);
     $session = Security::sanitizeInput($_SESSION['form_token']);
 }

 if (isset($_POST) && Security::matchTokens($post, $session)){

If we pass that test, then we set the variables from the form data:


 $song_name = Security::sanitizeInput($_POST['song_name']);
 $visibility = Security::sanitizeInput($_POST['visibility']);
 $video_source = Security::sanitizeInput($_POST['video_source']);
 $video_is_featured = Security::sanitizeInput(isset($_POST['video_is_featured']));
 $video_is_active_item = Security::sanitizeInput(isset($_POST['video_is_active_item']));

We’re using my homegrown Security class to scrub the input. Then we do a little formatting for the check boxes:


if ($video_is_active_item == true){
                
    $video_is_active_item = 1;
                
} else {
                
    $video_is_active_item = 0;
}
            
if ($video_is_featured == true){
                
    $video_is_featured = 1;
                
} else {
                
    $video_is_featured = 0;
                
}
            
if (!Validators::validateDropDownOption($visibility)){
                
    $visibility = 'Private';
                
}
           

I probably would have used ternary syntax if not for the word wrap issues in creating a book.

Anyway, then I use my custom-built Query class to insert the new record:


 $cmd = new Query;
       
       $sql = 'INSERT INTO song (song_name, visibility, video_source, 
               video_is_featured, video_is_active_item) VALUES (:song_name, 
               :visibility, :video_source, :video_is_featured, 
               :video_is_active_item);';
       
       $cmd->query($sql); 
       
       $cmd->bind(':song_name', $song_name);
       $cmd->bind(':visibility', $visibility); 
       $cmd->bind(':video_source', $video_source);
       $cmd->bind(':video_is_featured', $video_is_featured);
       $cmd->bind(':video_is_active_item', $video_is_active_item); 

       $cmd->execute();
       
       $cmd->closeDb();

My bind method autmatically detects string, int, etc. I had a lot of fun creating that. Then we save via execute and close the DB connection. Then we go to the newly created record or show the form if no post data was sent:


$url = Url::toSong($song_name);
return header('Location: ' . $url);
           
break;
            
} else {
        
$url = Url::toSongCreate();
return header('Location: ' . $url);   
break;
}

This is very simple and clear code, easy for a beginner to digest, but it sure did get procedural in a hurry. So I thought about extracting out the methods to further simulate what a framework like Yii 2 would do, but then I thought, hey, why don’t I just show the reader what the framework actually does instead? How would Yii 2 handle this method?

In Yii 2, we would get a single method on the controller. So I grabbed a controller method for the FAQ model we make in the Yii 2 book:


public function actionCreate()
{
    $model = new Faq();

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['view', 'id' => $model->id]);
    } else {
        return $this->render('create', [
            'model' => $model,
        ]);
    }
}

9 lines, not counting the white space. Now that’s power. It’s starts by creating a new Faq model, which gives us access to all the model attributes and methods. Then comes:


if ($model->load(Yii::$app->request->post()) && $model->save()) {

So what this is doing is loading the $_POST array, which gets all the fields from the form, validating it, and saving it. All that in one line of code. Wow!

If it successfully saves, it returns the view page of the newly created record:


return $this->redirect(['view', 'id' => $model->id]);

In the above, view is the name of the page we want. Yii 2 knows which model the view belongs to and $model->id is the specific instance. No other routing necessary.

If we can’t successfully save, we get the form:


} else {
     return $this->render('create', [
        'model' => $model,
    ]);
}

And that is essentially one line as well. You could style it like so:


return $this->render('create', ['model' => $model,]);

And that’s pretty much it. 9 lines and all the security, validation and formatting is already handled. It’s so simple!

Hopefully I’ve demonstrated at least one reason why I’m such a Yii 2 enthusiast. I will continue to do my best to make the framework as easy to understand for beginners as possible.

Thanks again to everyone who wrote in with encouragement and corrections, especially to those who took the time to do a review on GoodReads.com. As always, any comments, reviews, word-of-mouth referrals, are greatly appreciated.

Yii 2 FAQ

As part of our ongoing series to build a reusable template in Yii 2, we are going to do a tutorial on our FAQ model. We will focus mostly on our frontend implementation, but we will also be talking about the data structure, differences in the frontend and backend, and we will make use of Yii 2’s ArrayDataProvider, a very handy iterator for use in sending data to the views.

Ok, so if you are just joining the blog, and have not yet gotten started on the basics, I recommend my book, Yii 2 For Beginners, which is a step by step guide to get you installed, up and running, and into development. The book is oriented toward beginning programmers who are just making the transition into frameowrk development and in addition to explaining how things work, we take care to explain why things are done they way they are done.

This blog is meant to be an extension of the book, great for tips and tutorials, which will be included in the quarterly updates of the book. Anyone who purchases the book is entitled to the free quarterly updates for the entire life of the book, so hopefully you can take advantage of that.

One of the other big themes I like to explore is the idea of working for a client and keeping the client satisfied. I’m just going to assume that you will be building applications for a client who is difficult to please.

When we think of FAQs, we think of simplicity, just questions and answers, and simplicity typically serves us well. But if we think about our demanding client and things that are important to them, the order of the questions, for example, might be very important. And obviously, the order they want will most likely not match the ascending or descending timestamp for creation or alphabetical order.

In most cases, the client won’t even know what order they want the questions in until long after the project has been developed. So what we need is a way for them to determine the order via backend UI. Now this is really simple to do of course. We just add a faq_value field, with a data type of int, that we can sort either ascending or desceding depending on our preference.

For example, in an ascending sort, an FAQ with a value of 10 will be higher on the list than an FAQ with a value of 20. And as long as we give the client a method for changing the value of an FAQ from backend UI, the problem is anticipated and solved before it ever becomes an issue.

Yii 2 Test Controller

Welcome back to our beginner’s journey in Yii 2. I’ve made it my mission to help programmers at the beginning stages of framework development to learn about Yii 2, one of the most intuitive and powerful PHP frameworks available.

For those just getting started, I recommend my book, Yii 2 For Beginners, which will take you step by step through setup and onto coding. The book focuses on learning Yii 2 and building a reusable template that can serve as a starting point for your projects. It shows you how to do things, but also explains why we do things the way we do.

This blog serves as an extension of the book, where I share development tips and tutorials that will help you learn more about Yii 2. I also roll out new pieces of the template, which will be incorporated into the book on a quarterly basis. Anyone who purchases the book, gets free updates for the life of the book, so please take advantage of that, if you can.

Today’s tutorial is about implementing a simple test controller to help you with development. This tutorial is for beginning level programmers.

Sometimes in development, you want to isolate a block of code and play with it, without cluttering up your other code. Now version control should always be there if you made a huge mistake, but you really don’t want to be relying on that to step backwards unless you absolutely have to.

So what we’ll do is create a controller named test. We start by navigating to Gii, and clicking on Controller Generator. We don’t have to worry about creating a model first, since we don’t have one, our test controller will be used to play around with different bits of many models, and we will pull in the models via use statements as we need them.

If you don’t know how to use Gii or haven’t started using the framework yet, I would recommend learning that first before moving on to this tutorial. We’re assuming here that you know how to use Gii, which is Yii 2’s built-in code generator.

Ok, so back to the create Controller form on Gii. Pop in test into the first input field to name the controller. We will create just one action for now, Index. Then check to see if the namespace is set to where you want it to go.

In the advanced template, which is what I use because they provide a working user model, I’ve created a test controller for both frontend and backend, though that’s not really necessary. It just helps me when I’m thinking of things to intuitively associate a backend test controller with things I want to try in the backend. Also, sometimes, I leave code in place in the test controller while I’m thinking about whether or not I want to use it.

Ok, so when you hit preview on Gii, it will show two files, the controller and the view file. Once we click generate, it will also create the directory to hold the view file. So let’s do that now.

If all went well, you should have a TestController.php file in frontend\controllers and a frontend\views\test\index.php file.

Yii 2 Mailer and Auto-Responder

Yii 2 Mailer Tutorial

This Yii 2 mailer tutorial implements a method to send response messages via email to users of the application. This is sometimes called an auto-responder.

This tutorial is not included in my book, Yii 2 For Beginners, but I thought it would make a great addition to the template that the book builds.

This is not a short tutorial, even though in reality, there isn’t much code. The reason is that we are not only going to talk about how we are approaching our methods, but also why. The why is very important.

A couple of years ago, I discovered a youtube video that talks about how important “why” is, and ever since then, I’ve made it part of my lesson plans.

Also, my blog is geared toward beginners, so I take great pains to explain in great detail what we are doing, what decisions we made, and why we made them. We want to not only advance your understanding of Yii 2, but we also want to learn a little about design principles and their application.

The goal, as always, is to make the final code as pretty, thin, and usable as possible. Ultimately, the email trigger method will be in a controller, so we always want to keep that code as clean as possible.