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

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

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

Всем привет, кто читает мою статью.
Продолжаем выполнение тестового задания. Выполним пункт 3-5.

3) Добавить возможность удалять статьи в мягком режиме
. При этом сделать возможность обновить систему со старой версии (из первого задания) на новую без полного сброса БД.
Для возможности удаление статей в мягком режиме из таблицы «articles» создадим миграцию :

  1. php artisan make:migration ChangeArticleSoftTable --table=articles

В созданной миграции в методе up() опишем softDeletes.

PHP
class ChangeArticleSoftTable extends Migration
{
    public function 
up()
    {
        
Schema::table('articles', function (Blueprint $table) {
            
$table->softDeletes();
        });
    }
    ...
}

Применяем нашу миграцию. Внесем изменения в модель Article: добавим Trait SoftDeletes и добавим использование текущей метки времени для удаления.

PHP
class Article extends Model
{
    ...
    use 
SoftDeletes;
    protected 
$dates=['deleted_at'];
    ...
}

Теперь при удалении статья не будет удаляться из БД. Статья остается в базе данных, но в БД устанавливается ее атрибут deleted_at. Если у статьи ненулевое значение deleted_at, значит статья мягко удалена.

PHP
class ArticleController extends SiteController
{
    ...
    public function 
destroy(Article $article)
    {
        if (!
Auth::user() || !$article->isAuthor(Auth::user())) {
            return 
abort('404');
        }

        if (
$article->delete()) {
            return 
redirect()->route('home')->with('status'__('articles.delete_success'));
        }

        return 
back()->withInput()->with([
            
'status' => __('articles.warning')
        ]);
    }
    ...
}

Доработаем наш проект: реализуем окончательное удаление и восстановление статьи — соответственно.

PHP
class ArticleController extends SiteController
{
    ...
    public function 
erase(Request $request$article_id)
    {
        if (!
Auth::user()) {
            return 
abort('404');
        }

        
$article_for_delete Article::withTrashed()->find($article_id);
        
$article_for_delete->users()->detach();

        if (
$article_for_delete->forceDelete()) {
            return 
redirect()->route('home')->with('status'__('articles.delete_end_success'));
        }

        return 
back()->withInput()->with('status'__('articles.warning'));
    }

    public function 
restore(Request $request$article_id)
    {
        if (!
Auth::user()) {
            return 
abort('404');
        }

        
$article_for_restore Article::withTrashed()->find($article_id);

        if (
$article_for_restore->restore()) {
            return 
redirect()->route('home')->with('status'__('articles.restore_success'));
        }

        return 
back()->withInput()->with('status'__('articles.warning'));
    }
}

Для получения списка статей в корзине:

PHP
class IndexController extends SiteController
{
    ...
    public function 
trash()
    {
        
$this->title __('articles.title_trash');

        
$title $this->title;
        
$articles =  Auth::user()->getArticlesTrash();
        
$auth_user Auth::user();

        
$this->content view('trash'compact('title''articles''auth_user'))->render();

        return 
$this->renderOutput();
    }
    ...
}

4) Теперь надо создать функцию в классе статей, которая: принимает пользователя и только пользователя – выдаёт mismatch в противном случае, возвращает 
истину, если указанный человек автор статьи, 
ложь – если это не так – null если статья удалена. Если функция пытается вернуть что – то иное – mismatch.
Создадим функцию isAuthor:

PHP
class Article extends Model
{
    ...
    public function 
isAuthor($user)
    {
        if (!
$user) {
            return 
Config::get('constants.mismatch');
        }

        if (
$this->trashed()) {
            return 
null;
        }

        if (
$this->users()->find($user->id)) {
            return 
true;
        } else {
            return 
false;
        }
    }
    ...
}

5) ORM: Добавим новое поле пользователю user – experience 
Нужно создать функцию, в которой будет извлекаться пользователь и сохраняться в переменную $user = User::find(1). Дальше функция выводит experience. Параллельно с работой функции асинхронный метод меняет опыт на случайное число каждые несколько секунд. 
В первой функции ещё раз выводится спустя промежуток времени опыт пользователя. 
Каким будет этот вывод?
«С этим пунктом справился не до конца».
Для начала создадим миграцию для добавления поля experience.

  1. php artisan make:migration ChangeUserAddExperienceTable --table=users

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

PHP
class ChangeUserAddExperienceTable extends Migration
{
    public function 
up()
    {
        
Schema::table('users', function (Blueprint $table) {
            
$table->integer('experience')->unsigned()->default(1);
        });
    }
    ...
}

Добавим методы для получения и изменения поля experience соответственно:

PHP
class UserController extends SiteController
{
    ...
    public function 
getExperience(Request $request)
    {
        
$getExprnc $this->userService->getExperienceUser($request);

        if (
$getExprnc) {
            return 
response()->json([
                
'success'=>__('site.get_experience'),
                
'user_experience' => $getExprnc
            
]);
        }

        return 
response()->json([
            
'status' => __('site.warning')
        ]);
    }
    ...
}

class 
UserService
{
    ...
    public function 
getExperienceUser($request)
    {
        if (empty(
$request)) {
            return 
false;
        }
        return 
User::find($request->user_id)->experience;
    }
    ...
}

class 
UserController extends SiteController
{
    ...
    public function 
setExperience(Request $request)
    {
        if (
$this->userService->setExperienceUser($request)) {
            return 
response()->json([
                
'success'=>__('site.set_experience')
            ]);
        }

        return 
response()->json([
            
'status' => __('site.warning')
        ]);
    }
    ...
}

class 
UserService
{
    ...
    public function 
setExperienceUser($request)
    {
        if (empty(
$request)) {
            return 
false;
        }

        
$user User::find($request->user_id);
        
$user->experience random_int(150);

        if (
$user->update()) {
            return 
true;
        }

        return 
false;
    }
    ...
}

Определим routes, которые понадобятся для выполнения методов:

PHP
Route::group(['middleware' => ['web']], function () {
    ...
    
Route::group(['middleware' => ['auth']], function() {
        ...
        
Route::post('/get_experience','UserController@getExperience');
        
Route::post('/set_experience','UserController@setExperience');
    });
    ...
});

Для реализации задания написал скрипт, который использует ajax:

PHP
var startInterval;
var 
count 1;

function 
get_experience() {
    $.
ajaxSetup({
        
headers: {
            
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
    });

    $.
ajax({
        
url"/get_experience",
        
type"post",
        
data: { user_id: $("#user_id").val() },
            
success: function(result){
                
//console.log(result);
                
$("#experience").text(result['user_experience']);
            }
        });
};

function 
set_experience() {
    $.
ajaxSetup({
        
headers: {
            
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
    });

    $.
ajax({
        
url"/set_experience",
        
type"post",
        
data: { user_id: $("#user_id").val() },
        
success: function(result){
            
//console.log(result);
        
}
    });
};

function 
timerFired () {
    if((
count 2)==0){
        
get_experience();
    }
    else {
        
set_experience();
    }
    
count count 1;
}

$(
document).ready(function() {

    $(
'#start_experience').click(function(e)
    {
        
clearInterval(startInterval);
        
startInterval setInterval(timerFired,1000);
    });

    $(
'#stop_experience').click(function(e)
    {
        
clearInterval(startInterval);
    });

});

Скрин
Ссылка на Git.

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

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

Eskono

$data = [];
$data ['title'] = $this->title;
$data ['articles'] = $articles_trash_user;
$data ['auth_user'] = Auth::user();

почему не так?
$data = [
'title' ⇒ $this->title,
......
];

Eskono

public function isAuthor($user) {
if ($user) {
if($this->trashed()) {
return null;
}

if ($this->users()->find($user->id)) {
return true;
} else {
return false;
}
}
return'mismatch';
}

чем меньше вложенность ифов, тем удобнее читать код, лучше так:

if (!user) {
return 'mismatch';
}
...тут остальное без вложенности

и еще — лучше все тексты по типу «mismatch» выносить куда-нибудь в константы

raketa

Отдельное спасибо, за такие комментарии) Возьму себе в заметки

raketa

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

A1ex7

Никогда не понимал смысл такой конструкции

        if ($article_for_delete->forceDelete()) {
            return true;
        }
        return false;

Звучит как Если true - вернуть true иначе вернуть false. Сразу напрашивается более короткий вариант

return $article_for_delete->forceDelete();
raketa

Спасибо за советы)

raketa

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

seqond
PHP
public function isAuthor(User $user)
{
        return 
$this->users->contains($user);
}

Так еще проще.

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

Разметка: ? ?

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