Может войдёшь?
Черновики Написать статью Профиль

Выполняем тестовое задание (Мини блог) — Часть 2

laravel 5 Тестовое задание

Всем привет, кто читает мою статью.
Создадим проект, начальную базу для дальнейшей работы. Используемые программные средства:
• IDE — Sublime Text.
• Laragon Wamp 4.0.
• Git.
• Laravel 5.5.
• Bootstrap 4.

Используемые дополнительные библиотеки:
laravelcollective/html — v 5.4.
intervention/image — v 2.4.
stechstudio/laravel-php-cs-fixer — v 1.0.

Так же при написании проекта в помощь будем использовать:
«Хорошие практики Laravel».

Далее выполняем пункт 1 тестового задания — ничего сложного:
— Модель User без кастомных полей.
Создаются по умолчанию миграции.

— Модель Article с полем text.
Создаем миграцию:

  1. php artisan make:migration CreateArticlesTable --create=articles

В созданной миграции в методе up() опишем создаваемые поля:

PHP
class CreateArticlesTable extends Migration
{
    public function 
up()
    {
        
Schema::create('articles', function (Blueprint $table) {
            
$table->increments('id');
            
$table->string('title')->default('none');
            
$table->string('text');
            
$table->timestamps();
        });
    }
    ...
}

После этого применяем наши миграции:

  1. php artisan migrate

— Относятся как многие ко многим.
Т.к. отношение многие ко многим, то для начала создадим дополнительную таблицу «article_user» в БД :

  1. php artisan make:migration CreateArticleUserTable --create=article_user

В созданной миграции в методе up() опишем создаваемые поля необходимые для отношения многие ко многим:

PHP
class CreateArticleUserTable extends Migration
{
    public function 
up()
    {
        
Schema::create('article_user', function (Blueprint $table) {
            
$table->increments('id');

            
$table->unsignedInteger('user_id')->default(1);
            
$table->foreign('user_id')->references('id')->on('users');

            
$table->unsignedInteger('article_id')->default(1);
            
$table->foreign('article_id')->references('id')->on('articles');

            
$table->timestamps();
        });
    }
    ...
}

Применяем нашу миграцию.

— Написать свойство articles в первой модели, которое вернёт все статьи пользователя.
Добавляем метод articles в нашу модель User:

PHP
class User extends Authenticatable
{
    use 
Notifiable;

    protected 
$fillable = [
        
'name''email''password'
    
];

    protected 
$hidden = [
        
'password''remember_token',
    ];

    public function 
articles()
    {
        return 
$this->belongsToMany('App\Article''article_user')->withTimestamps();
    }
    ...
}

— Написать метод users во второй, который вернёт всех авторов статьи.
Здесь необходимо создать модель Articles.

  1. php artisan make:model Article

Уже после этого добавляем свойство users:

PHP
class Article extends Model
{
    protected 
$fillable = [
        
'id''text''title''created_at'
    
];

    public function 
users()
    {
        return 
$this->belongsToMany('App\User''article_user')->withTimestamps();
    }
    ...
}

А вот наши методы в действии (соответственно):
user_articles.blade.php

PHP
<div class="main-content">
  <
article>
    <
h2 class="page-title">{{ $title }}: {{ $user->name }}</h2>
    <
p>
      <
a href="{{ route('home') }}" class="btn btn-default btn-sm btn-back" type="button">{{ __('site.but_return_main') }}</a>
    </
p>
  </
article>

  @if (
$user->articles)
    @foreach (
$user->articles as $article)
      <
article>
        <
a href="{{ route('articles.show', $article->id) }}"><h2 class="post-title">{{ $article->title }}</h2></a>
        <
div class="post-meta">
          @foreach (
$article->users as $user)
            <
span><a href="{{ route('authors.articles',$user->id) }}"><class="fa fa-user post-meta-icon"></i> {{ $user->nickname }}</a></span>
          @endforeach
          <
span><class="fa fa-calendar-check-o post-meta-icon"></i> {{ $article->created_at->format('F d, Y') }} </span>
        </
div>
        <
div class="post-content">
          <
p>{{{ str_limit($article->text$limit 250$end '...') }}}</p>
          @if (
$auth_user && $article->isAuthor($auth_user))
            <
ul class="list-inline">
              <
li>
                <
a href="{{ route('articles.edit',$article->id) }}" class="btn btn-default btn-sm btn-category">{{ __('site.but_edit') }}</a>
              </
li>
              <
li>
                {{ 
Form::open(['method' => 'DELETE','route' => ['articles.destroy'$article->id],'style'=>'form-inline']) }}
                  {{ 
csrf_field() }}
                  {{ 
Form::submit(__('site.but_delete'), ['class' => 'btn btn-default btn-sm btn-back']) }}
                {{ 
Form::close() }}
              </
li>
            </
ul>
          @endif
        </
div>
      </
article>
    @endforeach
  @else
    <
article>
      <
div class="post-content">
        <
p>{{ __('site.no_articles') }}</p>
      </
div>
    </
article>
  @endif
</
div><!-- main-content -->

../articles/index.blade.php

PHP
<div class="main-content">
  @if (
$articles)
    @foreach (
$articles as $article)
      <
article>
        <
a href="{{ route('articles.show', $article->id) }}"><h2 class="post-title">{{ $article->title }}</h2></a>
        <
div class="post-meta">
          @foreach (
$article->users as $user)
            <
span><a href="{{ route('authors.articles',$user->id) }}"><class="fa fa-user post-meta-icon"></i> {{ $user->nickname }}</a></span>
          @endforeach
          <
span><class="fa fa-calendar-check-o post-meta-icon"></i> {{ $article->created_at->format('F d, Y') }} </span>
        </
div>
        <
div class="post-content">
          <
p>{{{ str_limit($article->text$limit 250$end '...') }}}</p>
          @if (
$auth_user && $article->isAuthor($auth_user))
            <
ul class="list-inline">
              <
li>
                <
a href="{{ route('articles.edit',$article->id) }}" class="btn btn-default btn-sm btn-category">{{ __('site.but_edit') }}</a>
              </
li>
              <
li>
                {{ 
Form::open(['method' => 'DELETE','route' => ['articles.destroy'$article->id],'style'=>'form-inline']) }}
                  {{ 
csrf_field() }}
                  {{ 
Form::submit(__('site.but_delete'), ['class' => 'btn btn-default btn-sm btn-back']) }}
                {{ 
Form::close() }}
              </
li>
            </
ul>
          @endif
        </
div>
      </
article>
    @endforeach
  @else
    <
article>
      <
div class="post-content">
        <
p>{{ __('site.no_articles') }}</p>
      </
div>
    </
article>
  @endif
</
div><!-- main-content -->

Ссылка на Git.
Далее Часть 3

Как вы считаете, полезен ли этот материал? Да Нет

Комментарии (5)

vuwave

composer create-project laravel/laravel --prefer-dist
В результате в каталоге larablog.test будет файл composer.phar и каталог larravel. Из каталога laravel все перемещаем в larablog.test – файл composer.phar и пустой каталог laravel удаляем.

вместо этого лучше composer create-project laravel/laravel ./ --prefer-dist
тогда проект закачается в папку в которой вы находитесь и не нужно будет копировать файлы из папки laravel и потом ее удалять

raketa

Принял)

A1ex7

Почему связанная таблица Articles Users создается двумя файлами миграции? Можно ведь одним

Добавляем свойство articles в нашу модель User:

articles() - это метод, а не свойство

Если же уже использовать best practises, тогда:

не $table->integer('user_id')->unsigned()->default(1);

а $table->unsignedInteger('user_id')->default(1);

не {{ csrf_field() }}

а @csrf

raketa

Спасибо, поправил.

yiimar

Зачастую в качестве primary key для связующей таблицы для связи many-many лучше использовать составной ключ (user_id, article_id), без id.

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.