Всем привет, кто читает мою статью.
Продолжаем выполнение тестового задания. Выполним пункт 3-5.
3) Добавить возможность удалять статьи в мягком режиме
. При этом сделать возможность обновить систему со старой версии (из первого задания) на новую без полного сброса БД.
Для возможности удаление статей в мягком режиме из таблицы «articles» создадим миграцию :
- php artisan make:migration ChangeArticleSoftTable --table=articles
В созданной миграции в методе up() опишем softDeletes.
class ChangeArticleSoftTable extends Migration
{
    public function up()
    {
        Schema::table('articles', function (Blueprint $table) {
            $table->softDeletes();
        });
    }
    ...
}
Применяем нашу миграцию. Внесем изменения в модель Article: добавим Trait SoftDeletes и добавим использование текущей метки времени для удаления.
class Article extends Model
{
    ...
    use SoftDeletes;
    protected $dates=['deleted_at'];
    ...
}
Теперь при удалении статья не будет удаляться из БД. Статья остается в базе данных, но в БД устанавливается ее атрибут deleted_at. Если у статьи ненулевое значение deleted_at, значит статья мягко удалена.
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')
        ]);
    }
    ...
}
Доработаем наш проект: реализуем окончательное удаление и восстановление статьи — соответственно.
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'));
    }
}
Для получения списка статей в корзине:
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:
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.
- php artisan make:migration ChangeUserAddExperienceTable --table=users
В созданной миграции в методе up() опишем создаваемое поле.
class ChangeUserAddExperienceTable extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->integer('experience')->unsigned()->default(1);
        });
    }
    ...
}
Добавим методы для получения и изменения поля experience соответственно:
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(1, 50);
        if ($user->update()) {
            return true;
        }
        return false;
    }
    ...
}
Определим routes, которые понадобятся для выполнения методов:
Route::group(['middleware' => ['web']], function () {
    ...
    Route::group(['middleware' => ['auth']], function() {
        ...
        Route::post('/get_experience','UserController@getExperience');
        Route::post('/set_experience','UserController@setExperience');
    });
    ...
});
Для реализации задания написал скрипт, который использует ajax:
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);
    });
});
 Laravel по-русски
Laravel по-русски 
      
      
     
          
Комментарии (8)
$data = [];
$data ['title'] = $this->title;
$data ['articles'] = $articles_trash_user;
$data ['auth_user'] = Auth::user();
почему не так?
$data = [
'title' ⇒ $this->title,
......
];
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» выносить куда-нибудь в константы
Отдельное спасибо, за такие комментарии) Возьму себе в заметки
Спасибо, исправил
Никогда не понимал смысл такой конструкции
Звучит как
Если true - вернуть true иначе вернуть false. Сразу напрашивается более короткий вариантСпасибо за советы)
Спасибо, исправил
public function isAuthor(User $user){
return $this->users->contains($user);
}
Так еще проще.