2/3 урок — связь сущностей между собой.

Наша задача на данном этапе состоит в том, чтобы прописать взаимосвязи между сущностями нашего блога между собой.
Откроем файл /app/Category.php
Класс должен выглядеть подобным образом

class Category extends Model
{
    use Sluggable;
    public function posts ()
    {
        return $this->hasMany(Post::class);
    }

    public function sluggable()
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }
}

У сущности есть связь только с постом, в категории может быть 1 или более постов.


Это описывается функцией posts.
Вы можете заметить тут то, что для категории мы используем пакет, о котором я говорил ранее — Sluggable.
Это строка

use Sluggable;

И функция

    
public function sluggable()
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }

Эти вещи нужно будет скопировать и вставить в нужные модели.

Далее идет сущность — Comment

class Comment extends Model
{
    public function post ()
    {
        return $this->hasOne(Post::class);
    }

    public function author ()
    {
        return $this->hasOne(User::class);
    }
}

Мы описали, что у комментария должен быть 1 post и 1 user.

Главная сущность нашего проекта — Post

class Post extends Model
{
    use Sluggable;
    public function category ()
    {
        return $this->hasOne(Category::class);
    }

    public function author ()
    {
        return $this->hasOne(User::class);
    }

    public function tags ()
    {
        return $this->belongsToMany(
            Tag::class,
            'post_tags',
            'post_id',
            'tag_id'
        );

        public function sluggable()
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }
    }
}

Вот здесь уже больше подробностей.


Идем по порядку.
У поста может быть 1 категория.
У поста может быть 1 автор.
У поста может быть много тегов.
Остановимся тут.
Мы создали метод tags и описываем что эта функция и как должна делать — она может возвращать много тегов ( belongsToMany ), далее мы прописали модель, с которой мы связываемся (Tag::class,), связываемся мы через таблицу — ‘post_tags’, далее указывается id этой модели в таблице ‘post_tags’, и id тэга.
Модель Subscription пока пропустим и переходим к следующей — Tag.

class Tag extends Model
{
    use Sluggable;
    public function posts ()
    {
        return $this->belongsToMany(
            Post::class,
            'post_tags',
            'tag_id',
            'post_id'
        );
    }

    public function sluggable()
    {
        return [
            'slug' => [
                'source' => 'title'
            ]
        ];
    }
}

Похоже на Post? Да, я думаю тут все понятно и по два раза одно и тоже расписывать не стоит.


И последняя на данный момент модель — User.
В ней уже есть какой то стандартный ларавеловский код, в итоге этот класс должен выглядеть так

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function posts ()
    {
        return $this->hasMany(Post::class);
    }

    public function comments ()
    {
        return $this->hasMany(Comment::class);
    }
}

Тут мы используем hasMany — это значит, что 1 пользователь может иметь множество статей и множество комментариев.

На данный момент код является оооочень легким для чтения и главное понимания, человеком, который хотя бы что то то понимает в программировании.

2/2 урок — связь постов с тегами.

Возьмем функцию up из последнего файла миграции.

    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('slug');
            $table->text('content');
            $table->integer('category_id')->nullable();
            $table->integer('user_id')->nullable();
            $table->integer('status')->default(0);
            $table->integer('views')->default(0);
            $table->integer('is_featured')->default(0);
            $table->timestamps();
        });
    }

Мы указали ‘category_id’ и ‘user_id’, которые будут связаны с нашим постом, но как нам связать посты и теги? Для этого необходимо создать таблицу, не модель с таблицей, а просто таблицу.
Введем в терминале команду

php artisan make:migration create_posts_table --create=post_tags

В файле миграции в функции up, нам нужно добавить две строки

$table->integer('post_id');
$table->integer('tag_id);

Все, с помощью это таблицы мы сможем связывать между собой посты с тегами.

2/1 урок — дополнение.

Мы остановились на заполнении миграций, но в прошлом посте я не раскрыл несколько деталей.

Мы указали функции up в миграции Category. Там всего два добавленных нами столбца — title и slug, без модификаторов.
Вот про это я и хотел уточнить. Про модификаторы всегда можно почитать в официальной документации laravel.

Как вы могли заметить, если вы запустили миграцию, то в mysql появятся данные Users, но мы же решили, что у юзера могут быть админские права и он может быть забанен, в базовой миграции этого нет, соответственно нам нужно исправить файл /database/migrations/create_users_table.php.
Функия up в этой миграции будет иметь такой вид

    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email');
            $table->string('password');
            $table->integer('is_admin')->default(0);
            $table->integer('status')->default(0);
            $table->rememberToken();
            $table->timestamps();
        });
    }

И вот тут как раз таки мы видим применения модификатора ->default($value).
Мы указали, что столбец is_admin по умолчанию имеет значение — 0.
Соответственно новый зарегестрированный пользователь не будет иметь админские права, то же самое с столбцом ‘status’, который отвечает за бан аккаунта.
Рассмотрим миграцию — Posts.
Функция up будет иметь такой вид

    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('slug');
            $table->text('content');
            $table->integer('category_id')->nullable();
            $table->integer('user_id')->nullable();
            $table->integer('status')->default(0);
            $table->integer('views')->default(0);
            $table->integer('is_featured')->default(0);
            $table->timestamps();
        });
    }

Как мы видим, тут появляется новый модификатор ->nullable();
Этот модификатор позволяет вставлять значение NULL в столбец.
То есть у нас может быть пост без привязки к конкретной категории и пользователю. С остальными модификаторами в этой миграции я думаю все понятно, если нет — вернитесь к этапу планирования и посмотрите, что это за атрибуты ‘status’, ‘views’, ‘is_featured’ и все станет ясно.

Вернемся к Users таблица в мускле уже есть, но ведь мы ее исправили, чтобы «перемигрировать» наши таблицы введите команду

php artisan migrate:refresh

 

2 урок «фундамент».

В прошлом уроке, мы разобрались, какие сущности будут в ядре нашего блога.
Что будем делать дальше?
Дальше мы поставим два пакета — Eloquent-Sluggable и Forms & HTML
На страницах подробно расписано как устанавливать эти компоненты, так что двигаемся дальше.

Как вы наверняка знаете фреймворк laravel работает по концепции MVC.

Итак, очень вкратце, что это. Это означает что у нашего приложения есть модели, контроллеры и представления.

Про представления пока говорить не будем, так как мы проектируем ядро нашего проекта, о фронтенде будем говорить потом.

Контроллер получает http запрос от клиента (браузера) и на основании полученных данных обращается к определенной модели для получения нужных данных. Это совсем вкратце, если кому то интересно почитать — гуглите.

Приступим, для начала нам необходимо создать модели. Мы можем создавать их в ручную, но это дичь полная, у нас есть замечательный инструмент — artisan, который в «два клика» нам позволить сделать все что нам надо.
Вернемся к прошлому посту и увидим, какие модели нам нужны.

Открываем консоль опенсервера, переходим в папку проекта и пишем команду —

php artisan make:model Category

в консоли мы должны увидеть ответ —

Model created successfully.

Проверим наверняка, в папке /project/app должен появится файл Category.php с содержимым


namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
//
}

Да, можно создать все в ручную, но согласитесь, что артизан сэкономить оооочень много времени.

Далее, нам необходимо создать файл миграции.
Делается это командой php artisan make:migration.
Нам необходимо будет ввести

 php artisan make:migration create_categories_table --create=categories

В консоле вы должны будете увидеть

Created Migration: 2018_04_17_100343_create_categories_table

Так же проверим, зайдем в папку /project/database/migration и увидим там новый файл, с содержимым

 use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateCategoriesTable extends Migration {     /**      * Run the migrations.      *      * @return void      */     public function up()     {         Schema::create('categories', function (Blueprint $table) {             $table->increments('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

В этом файле нам необходимо описать нашу таблицу, на этапе планирования мы решили, что у сущности Category у нас будут атрибуты — title и slug. Добавим два эти атрибута в функцию up.

    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->string('slug');
            $table->timestamps();
        });
    }

Для запуска миграций, нам нужно в консоли набрать команду — php artisan migrate.
Лично у меня на данном этапе возникли проблемы, команда возвращала ошибку и ни в какую не хотела создавать все таблицы.

111

Если у вас будет похожая проблема, то вам нужно будет открыть файл app/Providers/AppServiceProvider.php, добавить в блок use строку —

use Illuminate\Support\Facades\Schema;

, а метод boot должен выглядеть подобным образом

public function boot()
{
    Schema::defaultStringLength(191);
}

После этого, всего пройдет как надо.

Чтобы убедится в этом, зайдете в phpmyadmin и проверьте какие таблице есть в бд, у вас должно быть как на скрине ниже.

phpmyadmin

Аналогичным образом, создаем модели и миграции для всех сущностей, заполняем миграции и потом запускаем миграцию. Чтобы еще сильнее ускорить процесс используйте команду php artisan make:model someThing -m, флажок -m, сразу же создаст файл миграции для нужной модели.

1 «урок».

Итак, описывать процесс установки openserver и laravel я не буду, благо все это гуглится за 2 минуты.
Начнем.
Нам нужно реализовать с помощью laravel простенький блог.

Какие сущности у нас будут?

  • Пользователь
  • Комментарий
  • Пост
  • Категория
  • Тег
  • Подписка

Какие атрибуты нужны сущности Post?

  • id
  • title
  • slug (seo ссылка)
  • content
  • data
  • description
  • category_id
  • image
  • user_id (автор)
  • status (опубликовано или черновик)
  • views
  • is_featured (рекомендованные посты)
  • created_at
  • updated_at

У постов будут следующие методы:

    • add()
    • edit()
    • remove()
    • uploadImage()
    • removeImage()
    • getImage()
    • setCategory()
    • setTags()
    • toggleStatus()
    • toggleFeaterd()

 

Следующая сущность — Category.

Ее атрибуты:

  • id
  • title
  • slug

И один метод — posts().

Сущность тега — Tag аналогична сущности Category.

Сущность — пользователь User имеет атрибуты:

  • id
  • name
  • password
  • is_admin (имеет ли пользователь права администратора или нет)
  • status (заблокирован ли пользователь или нет)
  • avatar
  • created_at
  • updated_at

Методы пользователя:

  • add()
  • edit()
  • remove()
  • uploadAvatar()
  • removeAvatar()
  • toggleAdmin()
  • toggleStatus()

Сущность комментариев — Comment.

Атрибуты:

  • id
  • text
  • user_id
  • post_id
  • status
  • created_at
  • updated_at

Здесь, я думаю все понятно.

У сущности один метод — toggleStatus(), который определяет одобрен ли комментарий администратором или нет.

Последняя сущность подписка — Subcribe имеет атрибуты:

  • id
  • email
  • token
  • creadet_at
  • updated_at

У сущности два метода — add() и remove().

Какие таблицы в базе данных нам нужны?

  • posts
  • categories
  • tags
  • post_tags
  • users
  • comments
  • subscriptions

Планирование ядра в принципе законченно. Я так думаю, по крайней мере.

 

 

Учим php/js вместе.

Итак, я уже почти 10 лет работаю в it сфере, но за все это время так и не смог освоить ни один ЯП.
В свое время я пытался освоить pascal/delphi, еще в школьные годы, но не хватало мотивации и людей, которые бы отвечали на тупые вопросы.

Сейчас у меня есть знакомые, которые могут ответить на вопросы по любым языкам и темам, от php/python/js до c++/haskell/kotlin/clojure, от ооп до фп, короче — у меня есть кому задавать тупые вопросы.

На данный момент, мне 28 лет, в любом яп я ноль, я знаю парадигму ооп, какие она дает преимущества и пожалуй все, знаю основной синтаксис того же php и js, и пожалуй на этом все.

Начну с осваивания laravel и жса, посмотрим что из этого выйдет.

Знакомый питонист посоветовал начать писать просто свой блог, в плане, не посты в этот блог, а реализовать блог, без использования каких либо cms. Сказал, что главное не парится, если даже на самую тупую херню будет уходить по 5 часов, что с использованием cms и вообще чужих решений очень тяжело освоить программирование.

Работать будем с openserver: Php-7.1×64, Apache-Php-7-x64 и Mysql-5.6.

 

 

 

В России нет олигархов.

Тут подвезли новых санкций, «против России», на самом деле, конечно против ахуевших воров, ну да ладно, Песков пару дней назад, выдал отличный перл, не точная цитата, но что то в духе «В России нет олигархов, есть только бизнесмены».

Наблюдаем, как санкции идут нам на пользу прямо в режиме реального времени — бакс превысил 60 руб впервые с 16 ноября 2017 года.

usd_rub

http://www.forexpf.ru/currency_usd.asp

Димон уже поручил проработать меры поддержки подпавших под санкции США компаний, так что дальше будет еще веселее.

Разочарование в блокчейне, как технологии.

Итак, прошел почти год, после начала «хайпа» криптовалют.

Страсти, что называются поутихли и сейчас можно объективно взглянуть на технологию и оценить ее потенциал.

Как мы видим, сервисов с использованием блокчейна, практически не появилось, зато были бесполезные «криптокошки», стоматология на блокчейне, такси для проституток на блокчейне и еще тысячи и тысячи бесполезных и откровенно «скамовых» проектов, которые в итоге, собрав миллионы долларов не сделали абсолютно ничего.

Сама технология видится как чрезмерно ресурсозатратная реализация обычной базы данных.

Все эти «купить дом за 3 минуты» от Бутерина, возможны только при внедрении технологии государством, но чем тогда государственный блокчейн будет отличаться от обычной базы данных?

На данный момент, криптовалюты максимум на что гОдны и годнЫ это на использование на черном рынке, за счет их псевдонимности, при минимальном понимании технологий и соблюдений правил «цифровой гигиены» отследить, что покупателя, что продавца запрещенных товаров практически нереально.

 

Разбираем код первого контракта.

Здесь я разберу код, который мы деплоили в блокчейн из прошлого поста «Как начать работать с geth и mist. Деплой первого контракта в сеть.»

Продублирую полный код контракта:

pragma solidity ^0.4.18;
 
contract HelloWorld {
string wellcomeString = "Hello, world!";
function getData() public constant returns (string) {
 return wellcomeString;
 }
function setData(string newData) public {
 wellcomeString = newData;
 }
}

Далее разберемся построчно что же делает контракт.

pragma solidity ^0.4.18

pragma (прагма) — препроцессорная директива, которая указывает компилятору на какой версии solidity написан контракт.

contract HelloWorld {

Создаем контракт с названием HelloWorld, контракты можно сравнить с классами в ООП.

string wellcomeString = "Hello, world!";

Создаем переменную с именем welcomeString типа String и значением «Hello, world!»

function getData() public constant returns (string) {

Создаем публичную функцию с именем getData, которая возвращает значение типа String.

return wellcomeString;

Внутри функции мы описываем, что она должна делать, в данном конкретном случае — возвращает переменную wellcomeString, с заданным ранее значением «Hello, World!».
В этом контракте мы пошли немного дальше стандартного «Hello, World!» и создали еще одну публичную функцию с именем setData.

function setData(string newData) public {

Данная функция принимает значение переменной newData типа String.

wellcomeString = newData;

Функция присваивает значение переменной newData переменной wellcomeString. Тем самым мы можем менять начальное «Hello, World!» на что угодно.

Загрузив контракт в сеть, если вы все сделали правильно из прошлого поста, вы можете это проверить.

Для этого в браузере Mist перейдите на вкладку Contracts и выберите созданный контракт.

В поле Select Function, выберите функцию Set Data и в поле ниже введите свое значение, например «Wellcome» и нажмите кнопку Execute.

Если вы все сделали правильно, то вы увидите, что значение переменной getData поменялось на «Wellcome».

 

Как начать работать с geth и mist? Деплой первого контракта в сеть.

Для взаимодействия с блокчейном Ethereum необходимо установить программное обеспечение.
Geth — интерфейс командной строки, написанный на языке GO.
Скачиваем geth со страницы — https://geth.ethereum.org/downloads/.

В моем случае я работаю в ос Windows. Устанавливаем и запускаем через интерпретатор командной строки cmd.
Используем сочетание клавиш Win+R -> cmd и запускаем geth с подключением к тестовой сети Rinkeby, командой geth -rinkeby.

В конечном итоге вы должны увидеть аналогичную картину:

Далее скачиваем браузер Misthttps://github.com/ethereum/mist/releases выбираем подходящий вам клиент и устанавливаем. После скачивания блокчейна и запуска приложения вы увидите следующее:

Единственное отличие должно быть в том, что у вас будет нулевой баланс.

Получить бесплатный тестовый эфир в сети rinkeby вы можете на этой странице https://www.rinkeby.io/#faucet.

На данный момент у вас установлено все программное обеспечение для загрузки вашего первого контракта в сеть.

Переходим в пункт — Contracts и нажимаем кнопку Deploy New Contract.
В поле кода копируйте данный код:

pragma solidity ^0.4.18;
 
contract HelloWorld {
string wellcomeString = "Hello, world!";
function getData() public constant returns (string) {
 return wellcomeString;
 }
function setData(string newData) public {
 wellcomeString = newData;
 }
}

Справа от кода в выпадающем меню Select Contract To Deploy выбирайте Hello World, выставляйте максимальную комиссию ползунком Select Fee и нажимайте кнопку Deploy.

После всех манипуляций ваш контракт будет загружен в блокчейн.

В следующем посте я подробно разберу код контракта.