Wednesday, 10 April 2019

logotext

This module offers 2 options:


  • A logo with text to the right.
  • A logo with text underneath

The module was created to make logo based header elements more SEO friendly. The logo is itself a background and the text resides in a H1 tag.

The SCSS uses the BEM approach and resides at https://github.com/guitarbeerchocolate/logotext

Forked from https://github.com/guitarbeerchocolate/vanilla-js-component

Friday, 29 March 2019

Yii use and namespace

use

Standard Yii

This is a keyword which is used to make functionality available to the current class.
E.g. If you add line below
use yii\db\ActiveRecord;
You will be able to create a new ActiveRecord such as
$ar = new ActiveRecord();
Or to create a class which is an extension of an ActiveRecord such as
class Customer extends ActiveRecord
{
}

Your Yii custom components

E.g. If you add line below
use app\models\Customer;
You will be able to add functionality which has been created for this application. In this case a model was created called 'Customer'. From here you can such functionality to your current class as
$query = Customer::find();

namespace

The namespace allows you to create a structured naming convention to retrieve the class you are currently working on.
E.g. If you add lines below
namespace app\models;
use yii\db\ActiveRecord;
class Customer extends ActiveRecord
{
}
This will allow you at a later date to 'use' this class thus
use app\models\Customer;

Thursday, 28 March 2019

Yii database model

This is partly based on the documentation found at https://www.yiiframework.com/doc/guide/2.0/en/start-databases

ActiveRecord

If you're going to work with records using Yii, it's helpful to make use of the ActiveRecord class. In this example, we're working with a database of country data.  Thankfully, this is a simple scenario which requires the creation of a simple class. Just add this as models/Country.php
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Country extends ActiveRecord
{
}

Controller

Next we need to create a controller which we can use to pass data from the Country ActiveRecord model to a view. In this case, we're also going to add some pagination functionality, which we'll also pass to the view.

  1. First we create a $query object which will be used to retrieve the data.
  2. Next we create a $pagination object which will be used to control the display of that data.
  3. Next we get all the data we want.
  4. Finally we pass the data and pagination objects to the view.

We save this class as controllers/CountryController.php

<?php
namespace app\controllers;
use yii\web\Controller;
use yii\data\Pagination;
use app\models\Country;
class CountryController extends Controller
{
    public function actionIndex()
    {
        $query = Country::find();
        $pagination = new Pagination([
            'defaultPageSize' => 5,
            'totalCount' => $query->count(),
        ]);

        $countries = $query->orderBy('name')
            ->offset($pagination->offset)
            ->limit($pagination->limit)
            ->all();

        return $this->render('index', [
            'countries' => $countries,
            'pagination' => $pagination,
        ]);
    }
}

View

The view performs 3 tasks in this process:
Loops through the data, adding it to the page.
Adding the pagination object to that the data can be paged through.
Adding the LinkPager widget object to the pagination object to automatically create all those links, saving us a bunch of coding.
We'll put the view in the directory views/country/index.php

<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
?>
<h1>Countries</h1>
<ul>
<?php foreach ($countries as $country): ?>
    <li>
        <?php echo Html::encode("{$country->code} ({$country->name})"); ?>:
        <?php echo $country->population; ?>
    </li>
<?php endforeach; ?>
</ul>
<?php echo LinkPager::widget(['pagination' => $pagination]); ?>

Yii first models and forms

This is partly based on the documentation found at https://www.yiiframework.com/doc/guide/2.0/en/start-forms

Model

In building a form interaction it's often best to begin with a model; a place where the data will be sent for checking, and or converting and putting into a source. A model is therefore also required far all CRUD operations.

rules and validate

The model below handles an entry form post. It doesn't do much with the data, but it does contain a method with a reserved word, rules(). This method will be called later from the controller using the term validate()

The rules method return to the validate call within the controller validation of 2 expectations:

  1. That the name and emailAddress fields are required.
  2. That the emailAddress is a valid email field.

<?php
namespace app\models;
use Yii;
use yii\base\Model;
class EntryForm extends Model
{
    public $name;
    public $emailAddress;
    public function rules()
    {
        return [
            [
              ['name', 'emailAddress'], 'required'
            ],
            [
              'emailAddress', 'email'
            ]
        ];
    }
}

Controller

The controller makes our newly created model available to us through the line
use app\models\EntryForm;
A method is created called actionEntry() is created which will be called from the form (contained in a view) using the view file name of entry.php
and a new instance of the model is created through the line
$model = new EntryForm();
The POSTed data is sent to the model using the
Yii::$app->request->post() method. A list of other request options can be found at
https://www.yiiframework.com/doc/api/2.0/yii-web-request
At the same time, the model validates the data using
$model->validate() which as mentioned previously makes use of the rules() method.
Once these tests have been passed and you've done something useful with the data, you can render the confirmation view, entry-confirm.php.
If something went wrong you can take the user back to the form view entry.php.
In both cases, though it may seem a little confusing, $model is passed as 'model' to the views. This means that 'model' becomes $model within the views.
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\Request;
use app\models\EntryForm;
class SiteController extends Controller
{
    // actionIndex(), actionSay() etc.
    public function actionEntry()
    {
        $model = new EntryForm();
        $request = new Request();
        if ($model->load($request->post()) && $model->validate()) {
            // valid data received in $model do something meaningful here
            return $this->render('entry-confirm', ['model' => $model]);
        } else {
            // either the page is initially displayed or there is some validation error
            return $this->render('entry', ['model' => $model]);
        }
    }
}

Views

As mentioned in the controller section above, there are 2 views; entry.php and entry-confirm.php.

entry-confirm.php

Residing at views/site/entry-confirm.php is fairly easy to understand.
<?php
use yii\helpers\Html;
?>
<p>You have entered the following information:</p>
<ul>
    <li><label>Name</label>: <?php echo Html::encode($model->name); ?></li>
    <li><label>Email</label>: <?php echo Html::encode($model->emailAddress); ?></li>
</ul>

entry.php

Residing at views/site/entry.php requires a little more explanation.
The ActiveForm::begin() method creates form tag. This tag has an action field into which the ActiveForm::begin() method the filename of the form. This action field is used to make a request to the actionEntry() method in the controller.
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(); ?>
    <?php echo $form->field($model, 'name'); ?>
    <?php echo $form->field($model, 'emailAddress'); ?>
    <div class="form-group">
        <?php echo Html::submitButton('Submit', ['class' => 'btn btn-primary']); ?>
    </div>
<?php ActiveForm::end(); ?>

Tuesday, 26 March 2019

Yii first controller and URLs

This is partly based on the documentation found at https://www.yiiframework.com/doc/guide/2.0/en/start-hello
Within the controllers directory I have a file called SiteController.php. I'll explain a few things about it.

site is the default route for Yii applications and therefore SiteController.php would be (by default) the first controller a user interaction would access. So if I access my application through the URL http://localhost/test/yii-apps/basic/web/ then (by default) the SiteController would be called, and (by deafult) the actionIndex method would be called within that controller.

actionIndex renders the view views/site/index.php within the default layout views/layouts/main.php

In order to create a controller we need to make use of the controller classes declared at the top.

The method actionSay can be called from the URL http://localhost/test/yii-apps/basic/web/index.php
?r=site%2Fsay and within this URL, the r stands for route. route's format is ControllerID/ActionID. This would render the view views/site/say.php within the default layout views/layouts/main.php showing the content 'Hello' since this is the default value of the variable message.

The %2F is the URL encoded version of /

views/site/say.php looks like this:

<?php
use yii\helpers\Html;
echo Html::encode($message);
?>

To extend this approach the URL http://localhost/test/yii-apps/basic/web/index.php?r=site%2Fsay&message=Hello+Mick would pass a string Hello+Mick to the value of the variable message and the resulting page would display the string 'Hello Mick'.

Thus SiteController.php looks like this.

<?php
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
    public function actionIndex()
    {
        return $this->render('index');
    }

    public function actionSay($message = 'Hello')
    {
        return $this->render('say', ['message' => $message]);
    }
}
?>

Thursday, 21 March 2019

Yii views and layouts

Within Yii we have the concept of views and layouts. This can get a little confusing for 2 reasons:

  1. They both reside within the views directory
  2. The higher level is the layout, which lies within a sub directory if views i.e views/layouts

That aside once you strip the garbage found in most tutorial the concept is straight forward.
Let's take a layout as our starting position. In this case views/layouts/main.php
This contains 3 elements which are particular to Yii.

  1. The declaration of a variable from config/web.php to set the language
  2. The declaration of a variable which resides in the view for the title tag
  3. The all important echo of the $content variable which displays the contents of the view

<!DOCTYPE html>
<html lang="<?php echo Yii::$app->language ?>">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title><?php echo $this->title ?></title>
</head>
<body>
<?php echo $content; ?>
</body>
</html>

Now let's look at the views/site/index.php
This view passes the title variable which is used in the <title> tag. of the layout above. "Hello world!" is displayed where $content is echo'd from the layout above.
<?php
$this->title = 'My Yii Application';
?>
Hello world!

Introduction to Yii

Yii is a PHP, MVC framework which has been built with performance in mind.

Creating a new project

Let's imagine I've created a yii-apps directory to put all my Yii tests in.
cd yii-apps
If I run the following :
composer create-project --prefer-dist yiisoft/yii2-app-basic basic
I'm doing a number of things:

  • Using composer with the create-project command.
  • Adding the --prefer-dist option to the create-project command which will install packages from dist directory when available.
  • Adding the --stability=dev option, so that the app will be created as a piece of development rather than production. That can come later.
  • Creating the app using the 'Yii 2.0 Basic Application Template'. There are many application templates you can use. Some of them are written by 'yiisoft', the organisation which develops Yii itself.

Once installed, you can use the following command to see you application.
php yii serve
This would give you a URL such as http://localhost:8080/
Alternatively, if you already have a LAMP server running, you can use a URL like this in your browser:
http://localhost/test/yii-apps/basic/web/

How is it structured?

Yii applications are loaded using the following hierarchy:
Entry script -> Controller -> Actions

Yii Views are HTML with PHP. You can use helpers such as yii\helpers\Html and widgets such as yii\widgets\ActiveForm to create views

Yii models use the "active record pattern (methods)" to pull and push data, so in most cases you won't need to write queries.

You can use composer to perform tasks on your application such as create it, or add components.

composer.json handles all the components

config/web.php handles all the routing. Here, you can uncomment the urlManager section to handle pretty URLs.

controllers/SiteController.php is the default controller and contains a method call actionIndex(). This takes users to the index view residing at views/site/index.php. This is where the naming convention becomes obvious. Our controller is called SiteController.php and it corresponds to views/site.

web is the directory containing all the CSS and images etc.

vendor is the directory containing all the libraries.

A full description of the directory structure can be found at https://www.yiiframework.com/doc/guide/2.0/en/start-workflow

One final tip

Since PHP 7 came out you can require multiple namespace items as below:
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};