Laravel по-русски

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

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

#1 Веб-разработка » Как найти дублирующиеся подряд записи по признаку? » 28.09.2018 08:58:02

EVOSandru6
Ответов: 1

Добрый день,

Есть такая структура таблицы orders
id
user_id
product_id

Записи:

id       user_id         product_id
1        1               2
2        2               2
3        2               3
4        2               4
5        1               2
6        1               5
7        1               5
8        1               5

Нужно, чтобы заселектились записи только те, в которых предыдущие записи с такими же user_id имеют эквивалентный product_id.

Т.е. в данном случае вытащатся только с id 7 и 8


Есть 2 не совсем рабочих варианта:

1) Возвращает нужные записи с дубликатами, а дубликаты не нужны.

select * from your_table
INNER JOIN   (
      SELECT user_id, product_id
     FROM your_table
     GROUP BY user_id, product_id
    HAVING COUNT(id) > 1
) as m ON m.user_id = your_table.user_id AND m.product_id = your_table.product_id

2) Возвращает все, у которых были раннее эквивалентные записи, но тут не соблюдается, что запись для текущего пользователя по условию должна быть предыдущей.

SELECT 
  id 
FROM 
  orders outerO 
WHERE 
  EXISTS (
    SELECT 
      * 
    FROM 
      orders innerO 
    WHERE 
      innerO.user_id = outerO.user_id 
      AND innerO.product_id = outerO.product_id 
      AND innerO.id < outerO.id
  );

Подскажите - как решить мою проблему?

#3 Laravel 5.x » Насколько допустимо в laravel условие на relation? » 15.08.2018 00:09:16

EVOSandru6
Ответов: 2

Добрый день,

Есть 2 модели - User и Contract( provider_id, customer_id, sign )

class User extends Model {
    public function isProvider()
    {
        return $this->role === 1;
    }

    public function isCustomer()
    {
        return $this->role === 2;
    }

   public function contracts()
    {
        if($this->isProvider())
            return $this->hasMany(Contract::class, 'provider_id');
        if($this->isCustomer())
            return $this->hasMany(Contract::class, 'customer_id');
    }
}

Насколько верна реализация связи contracts?

Имеет ли смысл наследовать Provider и Customer от User и прописывать связи в них?

#4 Laravel 5.x » Как в laravel организовать роуты для элемента с составными ключами? » 12.08.2018 01:04:21

EVOSandru6
Ответов: 0

Добрый день:

Есть миграция:

class CreatePricesTable extends Migration
{
    public function up()
    {
        Schema::create('prices', function (Blueprint $t) {
            $t->primary(['vehicle_id','days']);
            $t->decimal('price');
            $t->integer('vehicle_id')->default(1)->index;
            $t->foreign('vehicle_id')->references('id')->on('vehicles')->onDelete('cascade');
            $t->integer('days');
            $t->timestamps();
            $t->softDeletes();
        });
    }

    public function down()
    {
        Schema::dropIfExists('prices');
    }
}

Первое что приходит в голову - обозначить в RouteServiceProvider:

Route::bind('price', function ($days, $price) {
            return Price::where([
                'days' => $days,
                'price' => $price,
            ]);
        });

routes/web

Route::group([
                'as' => 'prices.',
                'prefix' => 'prices',
            ], function() {

                Route::get('{days}/{price}/edit', 'PricesController@edit')->name('edit');

                Route::get('create', 'PricesController@create')->name('create');
                Route::get('{days}/{price}', 'PricesController@show')->name('show');
                Route::post('', 'PricesController@store')->name('store');
                Route::put('{days}/{price}', 'PricesController@update')->name('update');
                Route::delete('{days}/{price}', 'PricesController@destroy')->name('destroy');
            });
        });

Но если я допустим в контроллере пишу так:

public function edit(Price $price)
    {
        dd($price);
}

$price Не проглатывается(

Object of class Illuminate\Database\Eloquent\Builder could not be converted to string


Получается в любом случае придется писать аргументы такого вида:

public function edit($days, $price) {
        $price = Price::where([
            'days' => $days,
            'price' => $price
        ])->first();
...
}

И RouteServiceProvider тут никак не поможет?

#6 Re: Laravel 5.x » Как правильно сконфигурировать Mailer для отправки почты на VPS? » 11.08.2018 10:53:22

Благодарю,

"Эксим настраивал или просто "ничего не трогал""

если правильно понял - exim - это почтовый сервер. Его не ставил.

Если это важно - то в /etc/nginx/nginx.conf секуия mail закоменчена.

#mail {
#       # See sample authentication script at:
#       # http://wiki.nginx.org/ImapAuthenticateW … ePhpScript
#
#       # auth_http localhost/auth.php;
#       # pop3_capabilities "TOP" "USER";
#       # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#       server {
#               listen     localhost:110;
#               protocol   pop3;
#               proxy      on;
#       }
#
#       server {
#               listen     localhost:143;
#               protocol   imap;
#               proxy      on;
#       }
#}

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

По поводу агента - не совсем понял, попробовал так сдеать:

apt-file -x search 'bin/mail$'

получил:

phabricator: /usr/share/phabricator/bin/mail

Если это то, что Вы имеете ввиду.

Еще заметил, что config('mail.driver') вместо smtp  возвращает array...

config/mail.php:
...
    'driver' => env('MAIL_DRIVER', 'smtp'),
...

-----------

.env

MAIL_DRIVER=smtp

#7 Laravel 5.x » Как правильно сконфигурировать Mailer для отправки почты на VPS? » 10.08.2018 14:47:16

EVOSandru6
Ответов: 3

Добрый день,

Перечисленный ниже ход действий тестировал на локальной машине и на VPS хостинге с настроенный DNS. И там и там без ssl сертификата (only http://)

Во первых - конфигурация Laravel, варианты, которые почередно пробовал:

1) Mail.ru
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mail.ru
MAIL_PORT=465
MAIL_USERNAME=secret_login@mail.ru
MAIL_PASSWORD=secret_pass
MAIL_ENCRYPTION=tls

2) Gmail
#MAIL_DRIVER=smtp
#MAIL_HOST=smtp.gmail.com
#MAIL_PORT=587
#MAIL_USERNAME=secret_login@gmail.com
#MAIL_PASSWORD=secret_pass
#MAIL_ENCRYPTION=ssl

3) Mailtrap
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=secret_login
MAIL_PASSWORD=secret_pass
MAIL_ENCRYPTION=null

Тестировал так - поочередно раскоменчивал каждую секцию и запускал тесты. Например:

class MailRuTest extends TestCase
{
    protected $mailer;

    protected $mail_host = 'smtp.mail.ru';
    protected $mail_port = 465;
    protected $mail_username = '{secret_login}@mail.ru';
    protected $mail_password = '{secret_pass}';
    protected $mail_encryption = 'tls';

    protected $msg_from = 'secret_login@mail.ru';
    protected $msg_author = 'author_name';
    protected $msg_subject = 'Message From  to car sharing system - system_name';

    protected $msg_to = 'customer_name@mail.ru';

    public function setUp()
    {
        parent::setUp();
        $this->mailer = $this->app->make(MailerInterface::class);
    }

    public function testSend()
    {
        $this->assertTrue(true);

        $this->mailer->raw('Hi, welcome user! ' . date('Y-m-d H:s') . ' - mail_service_name', function ($message) {
            $message->to($this->msg_to)
                ->from($this->msg_from, $this->msg_author)
                ->subject($this->msg_subject);
        });
    }

    public function testAuth()
    {
        try{
            $transport = new Swift_SmtpTransport($this->mail_host, $this->mail_port, $this->mail_encryption);
            $transport->setUsername($this->mail_username);
            $transport->setPassword($this->mail_password);
            $mailer = new Swift_Mailer($transport);
            $mailer->getTransport()->start();
            // $this->expectOutputString('Good mailtrap auth');
            $this->assertTrue(true);

        } catch (Swift_TransportException $e) {
            fwrite(STDERR, print_r($this->mail_host. ': '.$e->getMessage() . ' - ' . $this->mail_host, TRUE));
            return $e->getMessage();

        } catch (\Exception $e) {

            fwrite(STDERR, print_r($this->mail_host. ': '.$e->getMessage() . ' - ' . $this->mail_host, TRUE));
            return $e->getMessage();
        }
        $this->assertTrue(true);
    }
}

Во всех трех тестах в protected свойства просто продублировал параметры из .env

Т.е. в файлах GmailTest.php, MailRuTest.php, MailtrapTest.php
производится попытка стукнуться на smtp сервер и отправить сообщение.

В итоге:
Ошибок не получаю (если езменять пароли например, то в Exception честно попадаю), но и письма не отправляются.

Единственное, почему то кабинете у mailtrap.io видно, что исходящие были, но на почте получателя почта неприходит даже в спам. Да и для тестов больше этот mailtrap, как я понял.

Для gmail пробовал след проделать:
1) gmail->Настройки->Пересылка и POP/IMAP->IMAP == on
2) Активировал: Небезопасные приложения разрешены по адресу:
https://myaccount.google.com/lesssecureapps

Для mail.ru - там почта для бизнеса
Настроили MX записи и получил письма:
Настроена подпись DKIM на домене {domen}.{com}
Почта для домена подключена!

Результат одинаков на лоокальной и на VPS. SSl сертификат нигде не установлен, если это важно. Посоветуйте пожалуйста что я делаю не так.

#8 Re: Laravel 5.x » Как получить env пременные через env('VAR_NAME')? » 10.08.2018 02:23:38

Благодарю,

исправил так:
php artisan config:clear

теперь норм. через env цепляется.

Но в unit тестах ни env ни getenv не работают((

Пусто


        fwrite(STDERR, print_r('YYYYYYYYYYYYYy', TRUE)); // YYYYYYYYYYYYYy
        fwrite(STDERR, print_r(getenv('APP_NAME'), TRUE)); // '' || null
        fwrite(STDERR, print_r(env('APP_NAME'), TRUE)); // '' || null

#9 Laravel 5.x » Как получить env пременные через env('VAR_NAME')? » 09.08.2018 23:12:33

EVOSandru6
Ответов: 2

Добрый день,

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

Фрагмент файла:

COMPOSE_PROJECT_NAME=app

APP_NAME=string
APP_ENV=local
APP_KEY=base64:string/string/string=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost

DEBUGBAR_ENABLED=false

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=string
DB_USERNAME=postgres
DB_PASSWORD=postgres

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=string
MAIL_PASSWORD=string
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=

SMSC_DRIVER=string.com
SMSC_KZ_LOGIN=string@string.com
SMSC_KZ_PASSWORD=string
SMSC_KZ_URL=https://string.string/string/string.php

Сам сайт работает, и данные например подключения базы должны тянутся отсюда.

Ибо в файле /var/www/sitename/config/database.php pgsql я не трогал:

...
'pgsql' => [
            'driver' => 'pgsql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '5432'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'schema' => 'public',
            'sslmode' => 'prefer',
        ],
...

На любую попытку получить значение переменной, ловлю null:

Route::get('/test-mail',function (MailerInterface $mailer) {
    dump(env('MAIL_HOST'));
    dump(env('APP_NAME'));
    dump(config('APP_NAME'));
});

Почему не могу получить доступ к данным переменным и почему база при этом мне подвластна?

#10 Re: Laravel 5.x » Как вытащить модели с критерием по связи, а также не имеющим связи? » 07.08.2018 01:56:18

Подскажите пожалуйста - будет ли верным по аналогии вместо:

->orWhereDoesntHave('leases');

Указать:

->orWhereNotExists(function ($query) {
                $query->select(DB::raw(1))
                      ->from('leases')
                      ->whereRaw('leases.place_id = places.id');
            })

Или же результаты выбора будут разниться?

И еще не подскажете - в каком файле фреймворка можно почитать метод orWhereDoesntHave?

#11 Laravel 5.x » Почему в laravel простой метод Eloquent модели вызывается как связь? » 05.08.2018 20:55:03

EVOSandru6
Ответов: 1

Добрый день,

Есть непонятка при вызове метода модели Edition.

namespace App\Entity\Vehicle;

use Illuminate\Database\Eloquent\Model;

class Edition extends Model
{
    public function brand()
    {
        return $this->belongsTo(Brand::class);
    }

    public function joke() :string
    {
        return 'hello';
    }
}

При вызове методов в обоих случаях:

$edition = Edition::findOrFail(1);
dd($edition->joke());
dd($edition->brand());

Вываливаются следующие ошибки:

Method Illuminate\Database\Query\Builder::brand does not exist.

и

Method Illuminate\Database\Query\Builder::joke does not exist.

Связь brand он не определяет, а метод joke принимает за несуществующую связь.

Laravel - 5.6
Postgres - 9.6.9

В чем может быть причина?

#12 Laravel 5.x » Почему в laravel может не работать hasMany связь? » 04.08.2018 00:39:20

EVOSandru6
Ответов: 0

Добрый день,

Есть 2 модели - Марки и Выпуски марок:

class Mark extends Model
{
    protected $table = 'marks';

    public function editions()
    {
        return $this->hasMany(Edition::class, 'mark_id');
    }
}

class Edition extends Model
{
    protected $table = 'editions';

    public function mark()
    {
        return $this->belongsTo(Mark::class);
    }
}

Проблема в вызове связи на живую модель данных (сами связочные данные в таблицах присутствуют),

class MarksController extends Controller
{
    public function show(Mark $mark)
    {
         dump($mark->name);
         dd($mark->editions());
    }
}

Хватаю:

Method Illuminate\Database\Query\Builder::editions does not exist.

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

Пробовал переименовывать метод связи - не помогло.

Например такая конструкция у меня работает:

Article::find(1)->comments()->create(['body'=>'haha','user_id'=>1])

Ааналогично:

Mark::find(1)->editions()->create(['name'=>AhAhAhA]);

Падает с аналогичной ошиибкой:
Method Illuminate\Database\Query\Builder::editions does not exist.

пробовал:

dd($mark->editions)

Ловлю null

Мне в итоге надо получить:

$editions = $mark->editions()->orderBy('sort')->get();

На что я ловлю вышеуказанную ошибку.

Склоняюсь - что проблема в модели:

namespace App\Entity\Vehicle;

use App\Entity\Behaviors\ImagePublicBehavior;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;

class Mark extends Model
{
....

Т.к. добавил сущность комментов для Марок, та же ошибка для:

$mark->comments()->create(['body' => 'xxx', 'user_id' => 1]);
         dd($mark->comments());
Illuminate\Database\Query\Builder::comments does not exist.

В чем может быть проблема? Подскажите пожалуйста.

#15 Laravel 5.x » Как в Laravel Mix объединить mix.scripts([]) c mix.js() и mix.styles([ » 09.06.2018 22:33:30

EVOSandru6
Ответов: 2

Добрый день,

Есть необходимость собрать секции:

mix.scripts([
    'resources/assets/front/js/file_1.js',
    'resources/assets/front/js/file_2.js',
    'resources/assets/front/js/file_3.js',
])

и

mix.js('resources/assets/js/app.js',  path + '/js')  // named app.js default

В один full.js файл?

Также интересует - как собрать секции:

mix.styles([
    'resources/assets/front/css/file_1.css',
    'resources/assets/front/css/file_2.css,
    'resources/assets/front/css/file_3.css,
])

и

mix.sass('resources/assets/sass/app.scss',  path + '/css');  // named app.css default

В один full.css файл?

Если да, то что виляет на порядок склейки?

#16 Laravel 5.x » Как вытащить модели с критерием по связи, а также не имеющим связи? » 06.06.2018 22:46:48

EVOSandru6
Ответов: 3

Добрый день,

Есть 2 модели:

Place (место для возможной аренды)
--id

и

Lease (аренда)
--id
--place_id
--started_at
--finished_at

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

Хочу запросом вытащить все Place, которые:

1. В указанный период не находятся в стадии аренды.
2. Вообще ни разу не взятые в аренду.

Набросок:

public function search(Request $request)
    {

        $started_at = $request->query('started_at');
        $finished_at = $request->query('finished_at');

              $places = Places::latest();

         if(isset($started_at) && isset($finished_at)) {

            $places->whereHas('leases', function($q) use ($started_at, $finished_at) {
                $q
                    ->where('status', '<>', StatusesLeaseHelper::STATUS_WAIT)
                    ->where(function ($qq) use ($started_at, $finished_at) {

                        $qq->where(function ($qqq) use ($started_at, $finished_at) {
                            $qqq
                                ->where('started_at', '>', $started_at)
                                ->where('started_at', '>', $finished_at);

                        })->orWhere(function ($qqq) use ($started_at, $finished_at) {
                            $qqq
                                ->where('finished_at', '<', $started_at)
                                ->where('finished_at', '<', $finished_at);
                        });
                    });
            });
}

return $places->get();

}


Насколько я понимаю, данный фрагмент отвечает условию 1. т.к. затрагивается период к связи leases (модель Lease), но не учитываются places (пункт 2.), для которых не было ни одной аренды. Подскажите пожалуйста - как можно решить сей момент?

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