Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 Re: Laravel 5.x » В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом » 31.03.2018 16:16:59

привет, сори за длительный ответ

что фейлится при таком сетапе?

из документации все шаги выполнил? провайдер зарегистрировал?

в composer.json имеется

"autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },

#4 Re: Laravel 5.x » Как увеличить функциональность объектов моделей БД » 15.03.2018 23:28:42

Ты получаешь ошибку call to undefined method stdClass - ключевое для тебя здесь то, что ты работаешь с stdClass. Твоя же задача получать инстанс класса Model который наследуют все твои модели приложения. получить его можно очень просто, используя Eloquent для построения запросов.

// это даст тебе коллекцию из объектов Bestiary (кстати, а что такое Bestiary?)
$bestiary = Bestiary::whereNull('inherited_id')->get();

// соответсвенно в цикле ты будешь работать с моделью
@foreach ($animals as $animal)
  $animal->getUrls(); // будет доступен
@enforeach

и старайся как можно реже прибегать к чистым activeRecord, используй Eloquent

"немного покопавшись, я понял, что модель данных и экземпляр данных имеют общее только связку, но не класс." - это как?

#5 Re: Laravel 5.x » Как увеличить функциональность объектов моделей БД » 15.03.2018 21:51:40

такой метод нужно писать в модели Galereya.

У тебя же есть такая модель? или ты просто накатил таблицу, не создав модель?

#6 Re: Laravel 5.x » В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом » 15.03.2018 21:48:28

твои даск тесты должны наследовать базовый DuskTestCase, который в свою очередь наследует PHPUnitTestCase. и все ассерты от туда доступны в твоем даск тесте. у тебя так? создавал тест командой artisan dusk:make?

#7 Re: Laravel 5.x » В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом » 15.03.2018 12:16:57

После того, как ты так настроил в database.php, в phpunit.xml пропиши <env name="DB_CONNECTION" value="testing"/> и тогда в тестах будет использоваться тестовая база. для сетапа ничего делать не нужно, твой трейт RefreshDatabase будет это делать сам - а именно, накатывать миграции перед каждым тестом.

AssertEquals это базовый ассерт предоставляемый phpunit, по ссылке что у тебя это конкретно даск ассерты, надстроенные уже над phpunit и расширяющие его возможности. ты легко можешь использовать все ассерты из phpunit в своих даск тесах, что очень круто. /vendor/phpunit/phpunit/src/Framework/Assert.php - здесь можно посмотреть все ассерты phpunit,  ну или в их документации

Данное условие истинно - есть ассерт $this->assertTrue($value). или $this->assertNotNull($value). соответственно есть и обратные, $this->assertFalse and $this->assertNull()

#8 Re: Laravel 5.x » выборка из связанной таблицы » 14.03.2018 21:35:31

привет!

репозитории нужно использовать тогда, когда очень хорошо понимаешь зачем ты их используешь. этот паттерн в частности используются в высоконагруженных проектах, и позволяет свапнуть реализацию. например если ты хочешь иметь возможность легко переключаться между Eloquent и, не знаю, файловой системой для выборки данных. тогда ты абстрагируешь логики, необходимые для реализации того и того подхода в свои репозитории, и через интерфейс резолвишь ту, что тебе нужна в данных момент.
Я могу предположить что ничего этого в твоем проекте не намечается => выпиливай нахрен все репозитории и не усложняй себе жизнь. используй Eloquent, тем более что уж он так прекрасен.

// даст тебе выборку юзеров по условию в связной таблице
User::whereHas('userInformation', function ($query) {
    $query->where('field', 'value');
})->get();


// даст тебе всех юзеров с подгрузкой только той информации, где она удовлятворяет вложенным условиям.
User::with(['userInformation' => function ($query) {
    $query->where('field', 'value');
}])->get();

напиши конкретно что хочешь сделать и составим точный запрос

#9 Re: Laravel 5.x » В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом » 14.03.2018 21:08:42

roll

кроном тесты на продакшене? но... зачем? нет, так не делают) зависимости для тестирования даже установлены в require-dev в композере - они по умолчанию на продакш не ставятся. Флоу: ты разрабатываешь фичу, используя тесты. когда твои тесты зеленые, ты можешь быть уверен, что твоя фича работает так как нужно. ты деплоишь код в продакшн. код в продакшене лежит протестированный и работает. и новый код туда не попадает, покуда твои тесты вновь зеленые - и так по кругу. так это работает. По вопросу конкретно, я не в курсе как можно получить отчет о результатах тестирования. Но блин! даже сама идея противоречивая))) то есть, с таким подходом получается, что ты допускаешь, что в продакшене будут фейлиться тесты! но так нельзя, код не может попасть в продакшн, если тесты фейлятся.

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

2) - но это три разных действия, должно обрабатываться трямя разными эндпоинтами, должны иметь три (как минимум своих теста)

3) тестирование на http уровне дает тебе намного более детальное представление о том что происходит, где что фейлится, где рушится логика, ты видишь как легко продвигаешься по стеку исключений от ошибки к ошибке. даск просто дает финальный фейл (как в твоем примере) и не понятно на каком этапе что сломалось. погляди мои видео https://www.youtube.com/watch?v=pUV_tVQlsBE - я сейчас пишу бэкенд для апи для своего приложения, делюсь тем что есть. круто что ты пытаешься внедрить тесты в свое воркфлоу, это правильный путь)
Вьюхи тоже можно нужно тестировать http уровне. допустим ты тестируешь листинг товаров. в фазе сетапа теста ты создаешь несколько товаров, (при этом создаешь их с такими параметрами, как нужно тебе, что опять же невозможно работая с нечистой базой). в фазе экшена делаешь гет запрос на эндпоинт. проверяешь что получил ответ такой то, урл у тебя такой то, проверяешь что вьюха получила необходимый набор из созданных тобою товаров. $this->assertViewHas. и все. а тестировать местоположение элементов на страницы - ну это такое. это значит что если ты решил изменить слегка дизайн, или например изменить формат даты во вьюхе, или используешь другой css фреймвор и классы твоих элементов поменялись - твои даск тесты упадут. будет ли это означать что твое приложение перестало работать? нет. ты просто поменял дизайн. для чего тогда тесты, если они не тестируют поведение, а ломаются от смены дизайна.
Бомбануло чот)) tongue

#10 Re: Хорошие практики (FAQ) » Хорошие практики - фильтры для товаров » 14.03.2018 20:45:33

Дружище, привет.

по вопросу валидации - ты можешь легко вынести ее в FormRequest, так как все Get параметры точно так же доступны в Request как и Post параметры. То есть ты можешь делать $request->shop, $request->category. ну или $this->category, $this->shop если уже в FormRequest классе.

Это раз.

По поводу рефакторинга. очень хороший вопрос и проблема весьма и весьма распространенная. когда контроллер превращается в вермишель изза большого кол-ва проверок на входящие параметры. я не смогу тебе щас тут это расписать, ибо займет много времени и места. лучше погляди мои видео, где я пишу бэкенд для апи для своего стартапа (ссылка в подписи), я там уделяю большое внимание рефакторингу и best practices. и я сделаю видео на эту тему, где хорошо ее смогу осветить (спасибо за идею кстати).

А пока можешь зарефачить валидацию, это уже будет что-то. так же валидация в FormRequeste будет возвращать и список ошибок, что тоже существенный плюс.
ну и кстати, если уж и не использовать форм реквест, то используй метод validate() который зашит в сам Request. $request->validate(['shop'=> 'integer'...]); он также позволит тебе не заботиться о Response и об возвращаемых ошибках

#11 Re: Laravel 5.x » В Laravel 5.5/vue.js2.5 приложении делаю проверку CRUD Dusk-ом » 14.03.2018 00:27:40

Дружище, привет. замечаний будет много

Первое - в тестах нужно использовать чистую отдельную БД и использовать трейт RefreshDatabase. это для того, чтобы А) - не засунуть/удалить по ошибке лишних данных в основную БД, Б) сделать жизнь проще. ларавел позволяет это сделать очень просто. в phpunit.xml, в тэге php добавь следующие записи

<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>

то есть будешь использовать sqlite базу подгружаемую в память. можно конечно и настроить отдельное MySql соединение в database.php для тестирования. но такой метод проще и в 95% случае именно то, что нужно

Второе, как уже сказал, заюзай трейт RefreshDatabase и убери все DB::beginTransaction rollback и коммит.

Третье - Теперь, когда у тебя чистая база, ты легко можешь сделать утверждения на счет того, что ты ожидаешь по результатам своего теста. Например, я так понимаю, что при сабмите формы кнопкой .editor_button_submit должна создаться новая запись в... DocumentCategory? ок, если так, наверно это у тебя модель? тогда ты можешь сделать следующее:

$this->assertEquals(1, DocumentCategory::count());

все - ты протестировал что у тебя создалась новая запись в DocumentCategory. Ты можешь быть в этом уверен, потому что ты начинал с чистой базы, и у тебя не было ни одной записи ни в DocumentCategory, ни в какой либо другой модели. Так же, ты можешь добавить утверждений

$documentCategory = DocumentCategory::first(); // взяли вновь созданную модель, тк она одна в базе
$this->assertEquals("D", $documentCategory->type); // проверяем, что то, что юзер ввел в форме, то и сохранилось в модель
$this->assertEquals("content lorem...", $documentCategory->content); // чтобы это проверить, избавься от time() - он не нужен тебе
$this->assertRedirect('uri');

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


$user = factory(User::class)->create();

$this->actingAs($user)->post('url куда уходить пост запрос',[
'type' => 'D',
'content' => 'Lorem ipsum...'
]);

#12 Re: Laravel 5.x » Произвольное условие в отношениях модели » 14.03.2018 00:05:50

Привет! расскажи немного о логике приложения - что пытаешься сделать? звучит как Visit - это счетчик кол-ва посещений Ticket для каждого пользователя (Person)? это так?

#13 Re: Laravel 5.x » Как получать данные для юзера? » 10.03.2018 15:17:47

привет!

чтобы получать данные из стороннего АПИ хорошим тоном считается созданием, так называемого Gateway, то есть некого шлюза который будет связывать логику твоего приложения и логику стороннего. на простом языке это обычный класс. например

<?php

class SomeServiceGateway
{
    public function getItems()
    {
        // здесь мы общаемся со сторонним апи

        // если этот сервис предоставляет либу для работы
        // со своим апи используем его здесь.
        $result = \SomeOtherSerivce\Items::get();

        // если нет - просто делаем запросы руками по их документации
        $response = \GuzzleHttp\Client::get('url', 'params');

        return $this->format($resposne);
    }

    protected function format($response)
    {
        // каким то образом приводим ответ от стороннего сервиса в тот вид,
        // который будет удобен для нашего приложения и подходит под его нужды
        // в этом и весь смысл Gateways.

        return json_decode($response->getBody()->getContents());
    }
}

теперь чтобы поделиться этим всем во своими вьюхами можно использовать view composer https://laravel.com/docs/5.6/views#view-composers

Или можно использовать View::share,

class AppServiceProvider extends ServiceProvider
{
    
    public function boot()
    {
        View::share('items', (new SomeServiceGateway)->getItems());
    }

#14 Re: Веб-разработка » VueJS, Laravel » 10.03.2018 15:06:54

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

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

protected function authenticated(Request $request, $user)
    {
        // вместо редиректа по дефолту вернем какой-то json response
        return response()->json(['status' => 'OK']);
    }

#15 Re: Веб-разработка » VueJS, Laravel » 10.03.2018 14:55:45

Далее, по поводу именования роутов

тут многое зависит от того, что за приложение ты строишь. если это будет апи например для мобильного приложения, то имеет огромный смысл все роуты писать в routes/api.php. по причинам описанным тобою выше — токен авторизация из коробки.

Если это просто веб приложение, на которое ты хочешь натянуть vue на фронтенде, можно обойтись вообще без routes/api и писать все в web.php. и просто отдавать ответы в виде json ответов. в этом случае не подразумевается аутентификация по токенам, и соответственно паспорт не нужен, аутентификация будет происходить по сессии, и слой усложнений в виде паспорта и поддержки аутентификации по токенам здесь излишний

если ты хочешь префиксовать роуты на которые vue будет делать запросы как /api но у тебя не чистый API для стороннего приложения, никаких проблем, объявим роут группу в web.php с префиксом api, и пиши их там.

#16 Re: Веб-разработка » VueJS, Laravel » 10.03.2018 14:51:20

Дружище, привет. по вопросу 401

если ты используешь пасспорт, то убедись что добавил middleware который будет генерить токен при запросах из vue к бэкенду

'web' => [
    // Other middleware...
    \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],

таким образом, тебе не нужно получать токен руками, когда ты используешь свой же API из своего же фронтенда. Ларавел будет это делать за тебя, а токен потребуется только для сторонних приложение (мобильное приложение, которое будет использовать тот же api)

#17 Re: Laravel 5.x » Удаление материала и безопасность. » 10.03.2018 13:50:22

Дружище, удалять ресурс GET запросом не самая хорошая идея. ознакомся с REST архитектурой

Если вкратце, для твоего случая тебе нужен запрос типа DELETE



<form method="post" action="/articles/{{ $article->id }}">
{{ csrf_field() }} // это предотвратит несанкционированный доступ к твоему эндпоинту со сторонних приложений, чего ты лишаешься при GEt запросе
{{ method_field('DELETE') }}
</form>

//в routes/web
Route::delete('articles/{article}', 'ArticlesController@destroy')->name('articles.destroy');

// В контроллере

public function destroy(Article $article, Request $reqeust)
{
   // авторизация на удаление в Reqeust

   ...


   $article->delete();
}

#18 Re: Laravel 5.x » Имеет ли смысл обновление Laravel с 5.3? » 10.03.2018 13:37:36

C 5.3 обновляться конечно уже нужно. с версии 5.3 прошло уже больше года, а может и полутора. добавлено огромное кол-во новых фич, особенно в части написания тестов, если используешь тесты то обновиться нужно обязательно. Да и вообще, не вижу никаких проблем обновляться через недельку другую после релиза новой версии. laravel это продукт того качества, когда можно не переживать за то, что [I]вдруг что-то сломается[/I]. Плюс, чем быстрее ты это делаешь, тем безболезненнее процесс.

#19 Re: Laravel 5.x » Как писать javascript без постоянной сборки webpack-ом? » 09.03.2018 19:15:36

Привет!

если просто ответить на твой вопрос — то наверно создать в public/js/app.js и туда писать js код)

в шаблоне сделать <script src="/js/app.js"></script>

Но если тебе хочется обойти сборку webpackом стороной, то скорее всего ты что-то упускаешь из виду. такие инструменты сделаны наоборот для того, чтобы сделать твою жизнь лучше)

#20 Re: Laravel 5.x » Delayed Jobs » 09.03.2018 10:31:29

Butirator рад что смог помочь

я пишу  API для своего мобильного приложения, делюсь с миром через видео уроки https://www.youtube.com/watch?v=pUV_tVQlsBE&t=1s

Заходи, смотри, поддержи проект)

#21 Re: Laravel 5.x » Delayed Jobs » 08.03.2018 20:31:37

дружище, тебе надо обернуть эту операцию в Job.

php artisan make:job RewardUser

// RewardUser
public function handle()
{
$this->user->money = ( $this->site->double_rewards ) ? ( $this->site->reward_amount * 2 ) : $this->site->reward_amount + $this->user->money;
$this->user->save();
}

// в контроллере

...

$job = (new RewardUser($user, $site))->delay(60*5);
dispatch($job);

из дополнений не по теме, но по best practices: оберни операцию награждения юзера в читаемый метод в модели юзера

// App\User

public function reward($site)
{
$this->money = $site->double_rewards 
         ? ( $site->reward_amount * 2 ) 
         : $site->reward_amount + $this->money;
$this->save();

// тогда в Джобе в handle вызовешь
$user->reward($this->site); // красиво и понятно
}

а еще мне кажется у тебя в логике ошибка

когда $this->site->double_rewards возвращает true, ты тупо перезаписываешь поле money для юзера каждый раз, не прибавляя к нему текущее значение этого поля. но может так и нужно

А еще)

имей ввиду, что когда ты выполнишь этот код, он все равно будет выполняться без задержки, потому что у тебя queue_driver = sync. сконфигурируй какой-нить другой, самое простое - database

#22 Re: Laravel 5.x » добавление данных в связанные таблицы » 07.03.2018 11:55:56

Company::create($request->all())
    ->companyInformation()
    ->create($request->all());

Не знаю, что означает лучше. Если запись в одну строчку улучшает, то можно так.

#23 Re: Laravel 5.x » Помогите настроить связи между таблицами » 06.03.2018 19:24:02

Тебе нужно еще таблица converstion_user

User::belongsToMany(Conversation)
User::hasMany(Message)

Conversation::belongsToMany(User)
Conversation::hasMany(Message)

Message::belongsTo(User) // в сообщение обязательно должно быть user_id иначе как мы узнаем кто его отправил. у тебя его нет. так же сюда можно засунуть read_at чтобы отображать прочитано оно или нет
Message::belongsTo(Conversation)

связку user->conversation можно еще объявить как

// User
public function conversations()
     {
         return $this->belongsToMany(Conversation::class)
            ->withPivot('name') // сюда можно положить название которое будет отображаться для каждого участника диалога. например если общаются Василий с Петром то для Василия диалог будет отображатьс как "Петр", а для Петра как "Василий"
            ->withTimestamps();
     }

#25 Re: Laravel 5.x » Добавление-удаление работ в заказе » 06.03.2018 18:55:00

А разве Работа != OrderService? Если нет, то в чем различие?

из того что видно, поля в ней такие же как в order_service? Под нее есть модель сейчас, Work? что она делает?

Эти строки на скриншоте - это order_services или уже works?

Может отличие в том, что order_service это список доступных сервисов, а работа - непосредственно выполненная работа по этим сервисам? тогда можно проставить order_services.is_complete и вытаскивать потом те, которые is_complete чтоб получить Работы

Подвал раздела