Laravel по-русски

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

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

#26 Laravel 5.x » Потеря в производительности при обращении к многомерным массивам » 02.02.2018 02:43:31

Gleb2708
Ответов: 2

Думаю, это будет вопрос скорее по PHP, но всё же структура Laravel тоже имеет влияние. Может быть, Вы в ответе предложите один из инструментов Laravel.

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

PHP
class References {

    const 
DB_TABLES = array(

        
'pages' => array(
            
'tableName' => 'pages',
            
'fieldNames' => array(
                
'id' => 'id',
                
'pagename' => 'name',
                
'title' => 'title',
                
'metadesc' => 'metadesc',
                
'keywords' => 'keywords'
           
)
       );
}

Обращение к этому массиву длиннее, чем прямое указание строкового значения, зато легко переименовать поле без внедрения в логику:

PHP
use App\Extenders\References as REF;

private function 
getTopPageHtmlHeadData(){

   return 
DB::table(REF::DB_TABLES['pages']['tableName'])
     -> 
where(REF::DB_TABLES['pages']['fieldNames']['pagename'], REF::OPEN_PAGE_NAMES_IN_DB['top'])
     -> 
first();
}

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

#27 Re: Laravel 5.x » SQL-запрос в конструкторе класса-контроллера » 01.02.2018 12:06:00

Благодарю Вас за ответ!
А Вы можете сказать, в какой момент создаётся экземпляр контроллера?

#28 Laravel 5.x » SQL-запрос в конструкторе класса-контроллера » 01.02.2018 11:18:07

Gleb2708
Ответов: 6

Всерьёз занявшись улучшением поддерживаемости кода, создал поля класса контроллера и добавл конструктор. Попробовал осуществить запрос к базе данных в конструкторе (вернее, вызвать соответствующий метод из конструктора), а не как обычно (то есть в методе, вызываемого из маршрутов web.php, в примере ниже — renderTopPage). Работает.

PHP
class TopPageController extends Controller {

    private 
$pageHtmlHeadData;

    public function 
__construct() {
        
$this -> pageHtmlHeadData =  $this -> getTopPageHtmlHeadData();
    }


    public function 
renderTopPage(){
        
// код этого метода не нужен в данном примере, но именно этот метод вызывается из web.php
    
}

    private function 
getTopPageHtmlHeadData(){
       
retrun // SQL запрос к БД ...
    
}
}

Вопрос такой: а будет ли выигрыш в скорости генерации страницы засчёт того, что SQL-запрос был выполнен до метода, где создаётся вид? Я бы смог ответить на этот вопрос, если бы знал, когда создаётся экзепляр контроллера (а он где-то создаётся, хотя у родительских классов конструкторов нет).

#29 Re: Laravel 5.x » Swift_TransportException - Не могу понять причину ошибки » 29.01.2018 11:44:40

На OpenServer smtp-то нет!
Теперь при тестировании только через log походу.

#30 Re: Laravel 5.x » Swift_TransportException - Не могу понять причину ошибки » 29.01.2018 11:33:11

Самый последний. Понял насчёт smtp. А есть какие-то ещё какие-то особенности в настройках кроме MAIL_DRIVER=smtp по сравнению с mail?

У меня теперь ошибка %Connection could not be established with host%, что следует в MAIL_HOST указать для Open Server?

#31 Laravel 5.x » Swift_TransportException - Не могу понять причину ошибки » 29.01.2018 11:28:28

Gleb2708
Ответов: 5

Никак не могу найти причину ошибки Swift_TransportException Process could not be started. На одном проекте работает — на другом — ни вкакую. И ещё в скобках показаны крокозябры:

Swift_TransportException Process could not be started [w肳ꂽpX‚܂B ]

При попытке локализовать ошибку я убрал всё лишее из функции отправки email, приведённый ниже код так же не работает, как и исходный:

PHP
    private function submitRequestEmailToAdmin(){

        
Mail::send('open.email.consultRequestNotification', [],
                function(
$message){

                });
    }

Настройки среды такие (в другом проекте с ними всё работает):

MAIL_DRIVER=mail
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=

Конфигурация — по умолчанию:

'driver' => env('MAIL_DRIVER', 'smtp'),

#32 Re: Laravel 5.x » Сессия каждый раз создаётся заново при перезагрузке страницы? » 27.01.2018 05:01:13

Без понятия, чем это объяснить, но когда я стал глубже копаться, внезапно всё заработало как надо.
Одна только версия есть: у меня хранилось 2 файла сессии и я удалил оба. Потом, соответственно, создался только один и дальше уже стало работать всё, как надо.

#33 Laravel 5.x » Сессия каждый раз создаётся заново при перезагрузке страницы? » 25.01.2018 05:54:22

Gleb2708
Ответов: 3

В следующем эксперименте я получаю false в первой строке при каждой перезагрузке страницы.

PHP
dump($request->session()->has('someSessionVariable')); // false
$request->session()->put('someSessionVariable''value');
dump($request->session()->has('someSessionVariable')); // true

Маршрут обрабатывается последником web (впрочем, без него то же самое), драйвер сессий — по умолчанию, т. е. file. SESSOON_LIFETIME тоже не менял — по умолчанию 120, expire_on_close — false.

#34 Re: Laravel 5.x » Импорт собственного класса в класс миграции » 25.11.2017 17:05:21

Вообще-то нет…
На этом проблема решена, но для понимания: зачем в классе указывать пространство имён? Почему оно не определяется автоматически на основе пути к файлу?

#35 Laravel 5.x » Импорт собственного класса в класс миграции » 25.11.2017 16:47:05

Gleb2708
Ответов: 4

Хочу добавить собственный класс в проект. На одном из формумов было сказано, что лучше свои классы помещать в app/, тогда я добавил свой класс в директорию app/Extenders/ (назначение этого класса не важно в данном вопросе).

Теперь пытаюсь импортировать свой класс в миграцию:

PHP
use App\Extenders\References as REF;

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

PHP
[Symfony\Component\Debug\Exception\FatalThrowableError]
Class 
'App\Extenders\References' not found

Я просмотрел много ответов, но рабочего решения нигде не нашёл. %% composer dump-autoload не помогло %%. Видел :[QUOTE][https://stackoverflow.com], решение[/QUOTE]:

PHP
"autoload": {
    
"classmap": [
        
"app/database/migrations"
    
],
    
"psr-4": {
        
"Acme\\controllers\\""app/controllers"
    
}
}

Но этого кода не достаточно, чтобы понять, что делать. Во-первых, этих autoload в composer.lock уйма, и непонятно, какой из них менять или новый добавлять… Да и что за psr-4, тоже непонятно.

#36 Re: Laravel 5.x » Ручная проверка пользовательской аутентификации » 21.11.2017 18:06:51

Используй стандартные файлы шаблонов или переопредели методы.

Используй стандартные файлы шаблонов

Нет, мне нужны именно свои собственные, со своим дизайном и организованные в файловой системе так, как мне комфортно.

Зачем?

Потому что в этих таблицах разные данные для аутентификации. Всё, что нужно администраторам для аутентификации — это имя, email и пароль; в данном случае аутентификация осуществляется по email. Другое дело с таблицей аутентификационных данных для заказчиков. Там будет помимо имени заказчика и пароля также название сайта, алиас и номер заказа; аутентификация в данном случае осуществляется по номеру заказа, а не по имени заказчика.

Это не повод лепить свой велик.

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

#37 Re: Laravel 5.x » Ручная проверка пользовательской аутентификации » 21.11.2017 17:22:00

Хорошо, но как? Как решается эта задача, если:
— Макеты с формой входа пользовательские и они лежат во views, но там, где мне надо (не в стандартном пути, генерируемом php artisan make:auth). На данный момент страница входа в закрытую зону сайтов в разработке — такая же открытая страница, как и многие другие потому маршрут к ней определяется так:

PHP
    Route::get('/login_to_sites_in_development_zone',

        [   
'as' =>      'loginToSitesInDevelopmentZonePage',
            
'uses' =>   'MainController@renderLoginToSiteInDevelopmentZonePage']

    );

— Разные таблицы с разными данными для админов и заказчиков. На данный момент аутентификацию для админов я ещё не проработал, но уже организовал последовательную проверку номера заказа и соответствующего пароля с выводом пользовательских ошибок. То есть у меня выводит что-то поинтереснее, чем стандартное Laravel-сообщение об ошибке:

PHP
if (is_null($orderIdInDB)) {
   return 
Redirect::route('loginToSitesInDevelopmentZonePage')->withErrors(['wrongOrderId' => true])->withInput();
}
xml    @if ((bool) $errors->first('wrongOrderId'))
        <div class="signInForm-errorMessagebox" id="invalidID-errorMessage">
            <div class="signInForm-errorMessagebox-heading">Неверный ID заказа</div>
            <div class="signInForm-errorMessagebox-contains">
            Вы ввели неверный или несуществующий ID заказа.</div>
        </div>
    @endif

— Регистрация и сброс паролей не требуются, меня сейчас интересует только аутентификация. Соответственно большинство того, что создаётся php artisan make:auth — лишнее.

#38 Laravel 5.x » Ручная проверка пользовательской аутентификации » 21.11.2017 16:06:57

Gleb2708
Ответов: 4

Если я правильно понял, то в приведённом ниже примере из документации по ручной аутентификации метод attept сверяет данные с данными в таблице users:

PHP
public function authenticate(){
    if (
Auth::attempt(['email' => $email'password' => $password])) {
     
// Аутентификация успешна
     
return redirect()->intended('dashboard');
   }
 }

Если так, то встаёт вопрос — а как же сверять данные с какой-либо другой таблицей? Я уже посмотрел имеющиеся ответы на этот вопрос, и везде показывали, как эту таблицу менять глобально. Я хочу оставить таблицу users и в одних случаях сверять данные с этой таблицы, но в других — с другой таблицей.

Предвижу ответ: «Локально указаться таблицу при конструировании запроса невозможно». Если так, то хорошо, не критично: сравнить данные можно и без Auth::attempt, и я уже это реализовал. А вопрос такой: как теперь вручную проверять, авторизован ли пользователь, если до этого фасад Auth вообще не использовался?

У Вас наверняка возникнет вопрос, что я такое вытворяю, для чего всё это. Задача специфическая; не готов утверждать, что выбрал лучший путь. У меня две аутентификации: одна для админов, которая даёт доступ к админ-панели, другая — для заказчиков, которая даёт доступ к его сайту, находящемуся в процессе разработки и временно являющегося частью моего сайта. Может, это можно реализовать и через авторизацию, но эти две аутентификации совершенно для разных целей и для каждой аутентификации необходимы разные наборы данных (отсюда — две таблицы под каждую идентификацию). Например, у каждого заказчика есть поле в БД «номер заказа» — администратору такое поле незачем.

#39 Re: Laravel 5.x » Laravel-проект в Laravel-проекте » 19.11.2017 15:05:02

Даже если и можно, то едва ли это будет менее трудозатратно, чем добавить дополнительный сайт в виде группы новых маршрутов. Кстати говоря, только задумался: для вложенного сайта-то динамическая часть не нужна! В случае сайта-портфолио достаточно показать вёрстку. Так что на добавлении новой группы запросов разработка серверной части портфолио-сайта практически закончится.

#40 Laravel 5.x » Laravel-проект в Laravel-проекте » 19.11.2017 06:30:20

Gleb2708
Ответов: 2

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

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

Можно загрузить портфолио-сайты на другие домены, но тогда надо покупать новый домент под каждый сайт и ещё каждый продлевать. Не подходит.

Что же можно сделать, чтобы был Laravel-сайт в Laravel-сайте с минимумом перенастроек? К маршрутизацией, в целом, всё понятно:

gleb-webmaster.ru - корень
gleb-webmaster.ru/portfolio - список портфолио-сайтов
gleb-webmaster.ru/portfolio/website1 - пример главной страницы портфолио-сайта
gleb-webmaster.ru/portfolio/website1/about - пример внутренней страницы портфолио-сайта

Теперь вопрос в том, как организовать файловую структуру. Можно, конечно прописать группу маршрутов gleb-webmaster.ru/portfolio/website1/, но тогда придётся переписывать контроллер с оригинального проекта website1. Если ли более быстрый способ заставить заработать Laravel-проект, вложенный в другой Laravel-проект?

#42 Laravel 5.x » Предел возможностей Laravel Mix » 12.10.2017 08:04:01

Gleb2708
Ответов: 2

В своих вопросах я уже неоднократно высказывал недовольство в адрес Laravel Elixir и Lavarel Mix, но эксперты Laravel настойчиво рекомендуют использовать именно эти инструменты. В первую очередь я критикую указаные выше инструменты за отсутствия гибкости и сложности в пользовательских настройках. Я думаю, этим инструментам не по зубам то, что я делаю спомощью gulp и webpack, но это лишь мои предположения и я могу ошибаться. В этом вопросе, я бы хотел сравнить Laravel Mix с возможностями нативных gulp и webpack и узнать предел возможностей Laravel Mix.

Далее я приведу настройки, которые использую в своих Laravel-проектах на данный момент (я добавляю в корень проекта собственные package.json и webpack.config.js и далее устанавливаю нативные gulp и webpack). Пожалуйста, перепишите эти настройки в инструкции для Laravel Mix, чтобы эффект от этих инструкций был такой же, как и от моих инструкций; либо открыто заявите, что это невозможно (только уточните, что именно и почему невозможно). Отсутствие ответа на данный вопрос длительное время тоже можно будет расценить как ответ «Laravel Mix это не по зубам…».

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

Итак, по делу:

Файл gulpfile.js

var  gulp = require('gulp'),
        pug = require('gulp-pug'),
        sass = require('gulp-sass'),
        browserSync  = require('browser-sync'),
        cssnano     = require('gulp-cssnano'),
        autoprefixer = require('gulp-autoprefixer'),
        rename      = require('gulp-rename'),
        del         = require('del'),
        imagemin    = require('gulp-imagemin'),
        pngquant    = require('imagemin-pngquant'),
        cache       = require('gulp-cache'),
        runSequence = require('run-sequence'),
        shorthand = require('gulp-shorthand');

gulp.task('default', ['watch']);

gulp.task('pug', function() {
    return gulp.src('resources/assets/pug/*.pug')
        .pipe(pug({
            pretty: true,
            basedir: 'resources/assets/pug'
        }))
        .pipe(gulp.dest('resources/assets'))
        .pipe(browserSync.reload({stream: true}));
});

gulp.task('sass', function(){
    return gulp.src('resources/assets/sass/*.+(sass|scss)')
        .pipe(sass())
        .pipe(autoprefixer(['last 15 versions', '> 1%', 'ie 8', 'ie 7'], { cascade: true }))
        .pipe(gulp.dest('resources/assets/css'))
        .pipe(browserSync.reload({stream: true}));
});

gulp.task('browser-sync', function() {
    browserSync({
        server: {
            baseDir: 'resources/assets'
        },
        notify: false
    });
});

gulp.task('watch', ['browser-sync', 'pug', 'sass'], function() {
    gulp.watch('resources/assets/pug/**/*.pug', ['pug']);
    gulp.watch('resources/assets/sass/*.+(sass|scss)', ['sass']);
    gulp.watch('resources/assets/es6/*.js', browserSync.reload);
});

// Продакшен

gulp.task('Build production', function(){
    runSequence(    'Clean previous production build',
                              'sass', 'Prepare CSS for production',
                              'Copy Fonts Folder To Production',
                              'Prepare images for production'
    );
});

gulp.task('Clean previous production build', function() {
    return del.sync(['public/css/*.css', 'public/img/**/*']);
});

gulp.task('Prepare CSS for production', function(){
    return gulp.src('resources/assets/css/*.css')
            .pipe(shorthand())
            .pipe(cssnano())
            .pipe(rename({suffix: '.min'}))
            .pipe(gulp.dest('public/css'));
});

gulp.task('Copy Fonts Folder To Production', function(){
    return gulp.src('resources/assets/fonts/**/*')
                    .pipe(gulp.dest('public/fonts'));
});

gulp.task('Prepare images for production', function() {
    return gulp.src('resources/assets/img/**/*')
        .pipe(cache(imagemin({
            interlaced: true,
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngquant()]
        })))
        .pipe(gulp.dest('public/img'));
});

gulp.task('Clear cash', function () {
    return cache.clearAll();
});

В папке resources/assets/pug находятся файлы препроцессора pug, которые компилируются в .html и помещаются в resources/assets.

gulp.task('pug', function() {
    return gulp.src('resources/assets/pug/*.pug')
        .pipe(pug({
            pretty: true,
            basedir: 'resources/assets/pug'
        }))
        .pipe(gulp.dest('resources/assets'))
        .pipe(browserSync.reload({stream: true}));
});

gulp-таск по умолчанию после выполнения других тасков (в т. ч. pug и sass) открывает файл index.html. Это лишь вёрстка; превращение её в шаблоны blade — это уже следующий этап. Как сказал мастер constb в вопросе [https://laravel.ru], Настройка средств front-end разработки без использоваия elixir,

Вполне можно разрабатывать на одной кодовой базе сразу и бэкенд и фронт

с тех пор я увлёкся организацией разработки фронтэнда и бэкэнда на одной базе.

* В папке resources/assets/sass находятся файлы расширения .scss, которые при development-сборке компилируются в resources/assets/css с добавлением вендорных префиксов, а при production-сборке — компилируются, минифицируются, оптимизируются (gulp-shorthand) и выкладываются в public/css:

gulp.task('sass', function(){
    return gulp.src('resources/assets/sass/*.+(sass|scss)')
        .pipe(sass())
        .pipe(autoprefixer(['last 15 versions', '> 1%', 'ie 8', 'ie 7'], { cascade: true }))
        .pipe(gulp.dest('resources/assets/css'))
        .pipe(browserSync.reload({stream: true}));
});

gulp.task('Prepare CSS for production', function(){
    return gulp.src('resources/assets/css/*.css')
            .pipe(shorthand())
            .pipe(cssnano())
            .pipe(rename({suffix: '.min'}))
            .pipe(gulp.dest('public/css'));
});

* Таск Prepare images for production сжимает изображения и выкладывает их в public/img, а Copy Fonts Folder To Production просто копирует шрифты в public/fonts.

* Функция runSequence, которая используется в таске Build production, требует новейшие версии gulp.

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

За всё, что связино с JavaScript, отвечает webpack. Исходники находится в папке es6.

webpack.config.js

const NODE_ENV = process.env.NODE_ENV || 'development';
const webpack = require('webpack');

const output_path = NODE_ENV === 'production' ?
    (__dirname + '/public/js'):
    (__dirname + '/resources/assets/js');

module.exports = {

    context: __dirname + '/resources/assets/es6',

    entry: {
        top: './top.js',
        about: './about.js'
    },

    output: {
        path: output_path,
        filename: '[name].js'
    },

    watch: NODE_ENV === 'development',

    watchOptions: {
        aggregateTimeout: 100
    },

    devtool: NODE_ENV === 'development' ? 'cheap-inline-module-source-map' : false,

    resolve : {
        alias: {
          "jquery-ui": "jquery-ui-dist/jquery-ui.js"
        },
        extensions: ['.js', '.jsx', '.json', '*']
    },

    module: {
        rules: [
            {
                test: [
                    /\.jsx?$/
                ],
                exclude: /node_modules/,
                use: [
                    'babel-loader'
                ]
            }
        ]
    },

    plugins: [

        new webpack.ProvidePlugin({
            jQuery: "jquery",
            $: "jquery"
        })

    ]

};

if (NODE_ENV === 'production') {
    module.exports.plugins.push(
            new webpack.optimize.UglifyJsPlugin({
            beautify: NODE_ENV === 'development' ? true : false,
            mangle: {
                screw_ie8: true,
                keep_fnames: true
            },
            compress: {
                screw_ie8: true
            },
            comments: false
        })
    );
}

* При development сборке es6 (но расширение тоже .js) конвертируется в JavaScript стандарта es5, происходит сборка модулей в файлы точек входа и они помещаются в /resources/assets/js
* При production-сборке происходит также минификация js-файлов, а затем они они отправляются в public/js.

На данный момент я пока запускаю gulp и webpack отдельно, потому что ещё не решил задачу интеграции gulp и свежей версии webpack, но работаю над этим. Если всё получится, то отдельный запуск webpack и файл webpack.config.js станут ненужными.

#43 Re: Laravel 5.x » Каково назначение папки resources/assets? » 08.10.2017 04:35:14

Оффтоп, но я хочу знать, почему это плохая идея и почему в коммерческих сайтах надо использовать встроенные средства.

Я одно время хотел использовать Laravel Mix, но тут же оказалось, что он совершенно лишён гибкости и крайне плохо кастомизируем. Я приведу ниже свои настройки для gulp и webpack, которые на данный момент использую в Laravel-проектах, но по своей методике, то есть с самостоятельной настройкой нативных gulp и webpack . Вот скажите: с помощью Laravel Mix я могу так же гибко всё настроить?

gulpfule.js

var  gulp = require('gulp'), 
        pug = require('gulp-pug'),
        sass = require('gulp-sass'),
        browserSync  = require('browser-sync'),
        cssnano     = require('gulp-cssnano'), 
        autoprefixer = require('gulp-autoprefixer'),
        rename      = require('gulp-rename'),
        del         = require('del'),
        imagemin    = require('gulp-imagemin'), 
        pngquant    = require('imagemin-pngquant'),
        cache       = require('gulp-cache'),
        runSequence = require('run-sequence'),
        shorthand = require('gulp-shorthand'); 

gulp.task('default', ['watch']);

gulp.task('pug', function() { 
    
    return gulp.src('resources/assets/01_pug/*.pug')
        .pipe(pug({
            pretty: true,
            basedir: 'resources/assets/01_pug'
        }))
        .pipe(gulp.dest('resources/assets'))
        .pipe(browserSync.reload({stream: true}));

});

gulp.task('sass', function(){ 
    
    return gulp.src('resources/assets/02_sass/*.+(sass|scss)') 
        .pipe(sass()) 
        .pipe(autoprefixer(['last 15 versions', '> 1%', 'ie 8', 'ie 7'], { cascade: true })) 
        .pipe(gulp.dest('resources/assets/css'))
        .pipe(browserSync.reload({stream: true})); 

});

gulp.task('browser-sync', function() { 
    
    browserSync({ 
        server: { 
            baseDir: 'resources/assets' 
        },
        notify: false 
    });
    
});

gulp.task('watch', ['browser-sync', 'pug', 'sass'], function() {
    gulp.watch('resources/assets/01_pug/**/*.pug', ['pug']); 
    gulp.watch('resources/assets/02_sass/*.+(sass|scss)', ['sass']);
    gulp.watch('resources/assets/03_es6/*.js', browserSync.reload);
});

// === Production Build

gulp.task('Build production', function(){
    
    runSequence(    'Clean previous production build',
                              'sass', 'Prepare CSS for production',
                              'Copy Fonts Folder To Production',
                              'Prepare images for production'
    );
       
});

gulp.task('Clean previous production build', function() {
    
    return del.sync(['public/css/*.css', 'public/img/**/*']);
    
});

gulp.task('Prepare CSS for production', function(){
    
    return gulp.src('resources/assets/css/*.css')
            .pipe(shorthand())
            .pipe(cssnano())
            .pipe(rename({suffix: '.min'}))
            .pipe(gulp.dest('public/css'));
});

gulp.task('Copy Fonts Folder To Production', function(){
    
    return gulp.src('resources/assets/fonts/**/*')
                    .pipe(gulp.dest('public/fonts'));
            
});

gulp.task('Prepare images for production', function() {
    
    return gulp.src('resources/assets/img/**/*') 
        .pipe(cache(imagemin({ 
            interlaced: true,
            progressive: true,
            svgoPlugins: [{removeViewBox: false}],
            use: [pngquant()]
        })))
        .pipe(gulp.dest('public/img')); 

});

gulp.task('Clear cash', function () {
    return cache.clearAll();
});

webpack.config.js

'use strict';

const NODE_ENV = process.env.NODE_ENV || 'development';
const webpack = require('webpack');

const output_path = NODE_ENV === 'production' ?
    (__dirname + '/public/js'):
    (__dirname + '/resources/assets/js');

module.exports = {
    
    context: __dirname + '/resources/assets/03_es6',
    
    entry: {
        index: './01indexEP.js',
        about: './02aboutEP.js',
        business: './03businessEP.js',
        feedback: './05feedbackEP.js'
    },
    
    output: {
        path: output_path,
        filename: '[name].js'
    },
    
    watch: NODE_ENV === 'development',
    
    watchOptions: {
        aggregateTimeout: 100
    },
    
    devtool: NODE_ENV === 'development' ? 'cheap-inline-module-source-map' : false,
        
    resolve : {
        alias: {
          "jquery-ui": "jquery-ui-dist/jquery-ui.js"
        },
        extensions: ['.js', '.jsx', '.json', '*']
    },
        
    module: {
        rules: [
            {
                test: [
                    /\.jsx?$/
                ],
                exclude: /node_modules/,
                use: [
                    'babel-loader'
                ]
            }            
        ]
    },
    
    plugins: [
        
        new webpack.ProvidePlugin({
            jQuery: "jquery",
            $: "jquery"
        })
         
    ]
 
};

if (NODE_ENV === 'production') {
    module.exports.plugins.push(
            new webpack.optimize.UglifyJsPlugin({
            beautify: NODE_ENV === 'development' ? true : false,
            mangle: {
                screw_ie8: true,
                keep_fnames: true
            },
            compress: {
                screw_ie8: true
            },
            comments: false
        })
    );
}

#44 Laravel 5.x » Что делает функция-хелпер asset()? » 07.10.2017 11:44:55

Gleb2708
Ответов: 1

Правильно ли я понял, что функция-хелпер asset(), использующаяся в шаблонизаторе Blade, просто заменяет относительный путь на абсолютный, при этом никакого отношения к папке assets не имеет?

#45 Laravel 5.x » Каково назначение папки resources/assets? » 07.10.2017 11:40:36

Gleb2708
Ответов: 2

Каково назначение папки assets (resources/assets)?

Я знаю, что в только что собранном проекте там находятся стили и JS-код по умолчанию, который Laravel Mix компилирует в выдаёт в папку public.

Теперь предположим, что я по какой-то причине не хочу использовать Laravel Mix и не хочу держать стили и js в assests - долго до них добираться + интуитивно непонятное назначение папки по её названию. Я подумываю вообще удалить папку assets, а все исходники (HTML-вёрстку, SASS, JS и прочее) хранить в папке frontend, которая находится в корневом каталоге проекта (такое имя папки лучше соответствует её содержимому). Development и prodution-сборку стилей и JS в public с помощью gulp и webpack я могу настроить самостоятельно без использования Laravel-mix.

Будут ли в этом случае какие-либо отрицательные последствия, если я удалю папку assets?

#46 Re: Laravel 5.x » Автоматическое определение локали на мультиязычном сайте » 21.09.2017 14:57:55

Благодарю Вас за ответ!
А так нормально будет с точки зрения SEO?

[url]http://example.com/ru/somepage[/url]
[url]http://example.com/en/somepage[/url]
[url]http://example.com/zh/somepage[/url]

#47 Laravel 5.x » В каких случаях следует добавлять в head meta name="csrf-token"? » 19.09.2017 05:21:10

Gleb2708
Ответов: 1

В шаблоны каких страниц следует добавлять в <head> нижеследующий код?

<meta name="csrf-token" content="{{ csrf_token() }}">

Я видел, что такой код есть в шаблонах аутентификации пользователей вдобавок к csrf-полю.

#48 Laravel 5.x » Автоматическое определение локали на мультиязычном сайте » 18.09.2017 15:38:38

Gleb2708
Ответов: 3

Достаточно ли для автоматического определения локали добавить тэгу html атрибут lang="{{ app()->getLocale() }}? Или же нужно ещё какие-то настройки прописать, чтобы локаль автоматически определялась?

И ещё: как протестировать с локального сервера корректное определение для каждой локали? Естественно, что будет отображаться тот язык, который соответствует главной локали, указанной в config/app.php, но как проверить корректность отображения страниц с другими локалями?

Предполагается, что на сайте доступно более двух языков (то есть помимо основной и fallback локалей есть и другие).

#49 Laravel 5.x » Локализация длинных фрагментов текста и html-кода » 18.09.2017 08:37:07

Gleb2708
Ответов: 1

Только что прочитал про основы работы с локализацией в Laravel. С короткими сообщениями всё понятно: создаём соловарь, в нём создаём ассоциативный массив, и переводим на нужный язык (ну или берём готовые словари). А что же делать с длинными фрагментами текста, которые, возможно, будут содержать большое количество HTML-тегов? Куда лучше поместить их переводы и как с ними работать? Полагаю, что хранить мы их будет не в ассоциативныом массиве...

#50 Laravel 5.x » Ручная регистрация пользователей » 14.09.2017 10:57:45

Gleb2708
Ответов: 1

Допустим, я не хочу использовать стандартный механизм регистрации пользователей, поскольку не предполагается, что среди пользователей (администраторов) будет больше двух человек. Таким образом, мне не нужен view для регистрации и RegisterController, а добавление пользователей в базу данных нужно будет сделать вручную. Ничего сложного, только непонятно, как правильно захэшировать пароль, то есть сделать это такими же способом, как Laravel. Какой тип хэширования использует метод bcrypt()? md5?

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