• Как оптимально реализовать фронт на Vue и бэк на Yii (желательно без CORS)?

    Sanasol
    @Sanasol
    нельзя просто так взять и загуглить ошибку
    OPTIONS не содержит практически никакой логики на бекенде, разве что авторизацию проверить, чего у вас так от него бомбит? Итого выполняется <50ms, ну дальше уже от интернета зависит.
    "Чинится" двумя заголовками и больше не беспокоит.
    Весь бекенд уже давно понимает OPTIONS.

    Сейчас хочется сделать "как положено", разделить мух (Yii) и котлеты (Vue).

    И бомбить от корса, а всего лишь нужно было узнать что это работает только между разными доменами, так почему бы просто не поднять бекенд и фронт на одном домене?
    Ответ написан
    3 комментария
  • Как сравнить строки в PHP?

    @Flying
    PHP поддерживает сравнение объектов DateTimeInterface напрямую, в данном случае стоит пользоваться именно этим:
    $format = 'd.m.Y H:i';
    $tz = new DateTimeZone('UTC');
    
    $d1 = DateTimeImmutable::createFromFormat($format, '01.01.2019 15:24', $tz);
    $d2 = DateTimeImmutable::createFromFormat($format, '02.01.2019 13:56', $tz);
    
    $newer = $d1 >= $d2 ? $d1 : $d2;
    echo $newer->format(DATE_ATOM);
    Ответ написан
    Комментировать
  • В чем разница между 'фабричным методом' и 'простой фабрикой'?

    @rundle
    Привет.

    Пример с сайта неудачный. Он не показывает выразительность фабричного метода в отличие от фабрики. Я изменил пример ниже.

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

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

    Например, мы открыли в Москве и Питере магазин по продаже телефонов и в классе BeelineStore есть общие методы для всех телефонов (код на java схематичный). Samsung стал поддерживать 5G интернет, поэтому сделаем тариф для этих телефонов дороже.

    spoiler
    abstract class IMobile {
    	void prepare() {
    		System.out.println("Подготовим документы по продаже от ООО Билайн");
    	}
    	void setInternetTariff() {
    		System.out.println("Установим стандартный тариф Билайна для интернета");
    	}
    	void box() {
    		System.out.println("Упакуем в желтый пакетик");
    	}
    }
    
    class BeelineSamsung extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Установим отдельный тариф для 5G интернета");
    	}
    }
    
    class BeelineIPhone extends IMobile {}
    
    class BeelineStore {
    	public IMobile orderPhone(String type) {
    		IMobile phone = null;
    
    		if (type.equals("samsung")) {
    			phone = new BeelineSamsung();
    		} else if (type.equals("iphone")) {
    			phone = new BeelineIPhone();
    		}
    
    		phone.prepare();
    		phone.setInternetTariff(); 
    		phone.box();
    
    		return phone;
    	}
    }
    
    // использование
    // var mobileStore = new BeelineStore();
    // mobileStore.orderPhone("samsung"); <- клиентский код

    Однако при изменении, удалении или добавлении новых видов телефонов мы бы открывали наш класс BeelineStore и расширяли новыми конкретными типами. А если мы добавим модели телефонов, то дерево условий станет сложнее. Если одни аспекты системы изменяются, а другие остаются неизменными — пора заняться инкапсуляцией.

    spoiler
    class MobileFactory {
    	public IMobile getMobile(String type) {
    		if (type.equals("samsung")) {
    			return new BeelineSamsung();
    		} else if (type.equals("iphone")) {
    			return new BeelineIPhone();
    		}
    
    		return null;
    	}
    }
    
    class BeelineStore {
    	MobileFactory factory;
    
    	public BeelineStore(MobileFactory factory) {
    		this.factory = factory;
    	}
    
    	public IMobile orderPhone(String type) {
    		IMobile phone;
    
    		phone = factory.getMobile(type);
    
    		phone.prepare(); 
    		phone.setInternetTariff();
    		phone.box();
    
    		return phone;
    	}
    }
    // использование 
    // var mobileFactory = new MobileFactory();
    // mobileStore = new BeelineStore(mobileFactory);
    // mobileStore.orderPhone("samsung"); <- замечу, клиентский код не изменился

    Окей - мы вынесли процесс создания телефонов - это и есть фабрика. И тут мы расширяемся, дела в нашей компании пошли хорошо и мы открываем филиалы на Урале. Тарифы на Урале будут дешевле, как стандартные, так и для 5G интернета. А также в Москве и Питере запускается программа по обмену старых телефонов на новые. И тут нам помогает фабричный метод.

    spoiler
    abstract class BeelineStore { // класс становится абстрактным
    	protected abstract IMobile getMobile(String type); // возвращается метод getMobile
    
    	public IMobile orderPhone(String type) {
    		IMobile phone = getMobile(type);
    
    		phone.prepare(); 
    		phone.setInternetTariff();
    		phone.box(); 
    
    		return phone;
    	}
    }
    
    class CenterBeelineSamsung extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Отдельный тариф для 5G интернета в центре России");
    	}
    }
    
    class CenterBeelineIPhone extends IMobile {}
    
    class СenterBeelineStore extends BeelineStore {
    	public IMobile getMobile(String type) {
    		if (type.equals("samsung")) {
    			return new CenterBeelineSamsung();
    		} else if (type.equals("iphone")) {
    			return new CenterBeelineIPhone();
    		}
    
    		return null;
    	}
    	
    	public void tradeIn(String phone) {
    		System.out.println("Вы обменяли старый телефон на новый с доплатой");
    	}
    }
    
    class UralBeelineSamsung extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Отдельный тариф для 5G интернета на Урале");
    	}
    }
    
    class UralBeelineIPhone extends IMobile {
    	void setInternetTariff() {
    		System.out.println("Отдельный тариф для стандартного интернета на Урале");
    	}
    }
    
    class UralBeelineStore extends BeelineStore {
    	public IMobile getMobile(String type) {
    		if (type.equals("samsung")) {
    			return new UralBeelineSamsung();
    		} else if (type.equals("iphone")) {
    			return new UralBeelineIPhone();
    		}
    
    		return null;
    	}
    }
    // использование
    // var centerBeelineStore = new СenterBeelineStore();
    // centerBeelineStore.orderPhone("samsung");
    // var uralBeelineStore = new UralBeelineStore();
    // uralBeelineStore.orderPhone("samsung");

    Мы смогли сохранить единые для всех магазинов стандарты оформления заказа, а также добавили региональные отличия.
    То есть фабричный метод гораздо гибче. Простая Фабрика обладает узкой специализацией, а фабричный метод ведет к созданию инфраструктуры, в которой реализация выбирается субклассами.
    Простая Фабрика инкапсулирует создание объектов, но она лишена гибкости фабричного метода в изменении создаваемых продуктов.
    Ответ написан
    Комментировать
  • В PHP канонично сначала проверить, потом сделать или попробовать и обработать ошибку?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Очень хороший вопрос и тема, в которой самое чудовищное количество самых дремучих северий на единицу кода.

    В общем случае, по умолчанию, никаких проверок и траев с кетчами быть не должно.

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

    Пример: В обоих приведенных выше случаях мы имеем масло масляное: попытка подменить пхп в выборосе ошибки. Вопрос - зачем? Если файл не найден, то РНР сам прекрасно сообщит нам об ошибке, причем в подробностях, и скажет в чем конкретно заключается проблема. А по строчке "file not found" иди гадай - путь ли кривой или в имени файла опечатка, или вообще пустоту передали.

    Любые проверки надо делать только тогда, когда есть осмысленный сценарий их обработки.

    И обсуждать выше приведенные примеры имеет смысл только если автор вопроса предоставит такой сценарий. тупое error: file not found таким сценарием не является. Так что в общем случае оставляем код в покое и не устраиваем никакого карго культа из перехвата ошибок.

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

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

    Но повторюсь, если нет никакого осмысленного сценария обработки ошибки, то ловить её не надо.
    Ответ написан
    6 комментариев
  • Как сделать дату на 5 дней вперед от определенной даты?

    irishmann
    @irishmann
    Научись пользоваться дебаггером
    <?php
        $date = new DateTime('18.07.2019 15:17:34');
        echo "Исходная:     ", $date->format('d.m.Y H:i:s'), PHP_EOL;
        $date->modify('+ 5 day');
        echo "Через 5 дней: ", $date->format('d.m.Y H:i:s'), PHP_EOL;

    Результат:
    Исходная:     18.07.2019 15:17:34
    Через 5 дней: 23.07.2019 15:17:34
    Ответ написан
    Комментировать
  • Почему в конструкторе не могу написать так?

    e-vyushin
    @e-vyushin
    Frontend engineer
    Думаю основная причина почему кажется что это должно работать — это непонимание разницы между функцией в JS и методом объекта. Это не одно и то же, несмотря на то что оба варианта можно вызвать подписав скобочки () в конце :) Да, вызывать можно и функцию и метод объекта, а вот создавать экземпляры методов нельзя.

    В указанном Вами примере внутри функции Man вызывается new this.Man. Это означает, что создаётся экземпляр Man, а значит сам Man должен иметь конструктор (грубо говоря быть классом).

    Функции в JS имеют конструктор, а методы объектов не имеют. Функции и методы объектов это не одно и то же. Рассмотрим такой пример:

    const obj = {
       Man() {}
    }

    в данном случае Man() это просто метод объекта. У него нет своего конструктора. Т. е. нельзя создать его экземпляры через new. Но можно его вызвать:

    const obj = {
       Man() {}
    }
    obj.Man();

    это корректный вариант.

    Но создавать экземпляры нельзя. Например:

    const obj = {
       Man() {}
    }
    new obj.Man(); // Будет ошибка. TypeError: obj.Man is not a constructor

    А вот экземпляры функции можно создавать. Например:

    const obj = {
       Man: function() {}
    }
    new obj.Man(); // Всё ок

    для того чтобы создать экземпляр функции не обязательно конечно чтобы она была внутри объекта. Можно и так:

    const Man = function() {}
    new Man(); // Всё ок

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

    Вывод: методы объекта и функции это не одно и то же.
    Ответ написан
    1 комментарий
  • Шуточная шпаргалка по срокам выполнения проектов

    sefus
    @sefus
    Ответ написан
    Комментировать
  • Шуточная шпаргалка по срокам выполнения проектов

    Juggler
    @Juggler
    «Сегодня» — завтра.
    «Завтра» — напомнить завтра, что уже сегодня (см. «сегодня»).
    «В течение недели» — в следующую среду.
    «В течение недели, но до выходных, пожалуйста» — в понедельник.
    «Через две недели» — месяц.*
    «Месяц» — неопределенная, очень большая величина времени.
    «Три месяца» — три неопределенные, очень большие величины времени.
    «К осени» — когда выпадет снег. Снег выпадает каждый год, поэтому «к осени» является наиболее благоприятным сроком, пропустить который практически невозможно.
    «Через год» — не используется, т.к. есть «к осени».
    ____________

    * Популярно заблуждение, что две недели — это 14 дней. Это не так. Две недели — это 14 дней + «в течение недели» (ибо вторая неделя еще не кончилась) + завтра («один день погоды не сделает»). В особых случаях отсчет «двух недель» начинается со следующего понедельника, так выигрывается еще несколько дней.
    Если повезет, то в результате выходит месяц срока и опоздание всего на один день («завтра»).
    Ответ написан
    1 комментарий
  • Правда ли что рынок веб разработки "перегрет"?

    politon
    @politon
    HTML5,CSS3,JS,PHP,SQL,API,canvas,animation...
    Перегрет... говнокодерами, тыжпрограммистами.
    И все благодаря говногугру исповедующих говнокурсы "Выучить ЯП за десять минут".
    Толковых мало
    Ответ написан
    1 комментарий
  • Зачем нужен контейнер если php умирает?

    Maksclub
    @Maksclub Куратор тега PHP
    maksfedorov.ru
    Пишем код, кода становится много, его нужно обслуживать и бороться со сложностью, также нужно тщательно тестировать, тк деньги и надежность пользователей

    Чтобы тестировать методы класса и не зависеть от реализации -- соблюдается принцип инверсии зависимостей (и некоторые другие)

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

    try {
        echo
            (new PurchaseOrder(
                new LocalOrderStorage(
                    new NullOrderStorage()
                ),
                new OrderId($inputParams['order_id'])
            ))
                ->newInvoice(
                    new InvoiceNumber(
                        new Vendor(
                            new LocalVendorStorage(),
                            new VendorId($inputParams['vendor_id'])
                        ),
                        new VendorInvoiceNumber($inputParams['vendor_invoice_number']),
                        new DateTime($inputParams['date_time'])
                    ),
                    new VendorInvoiceNumber($inputParams['vendor_invoice_number']),
                    new DateTime($inputParams['date_time']),
                    new InvoiceAmount(
                        new Amount($inputParams['amount']),
                        new Currency($inputParams['currency'])
                    )
                )
                    ->json()
        ;
    } catch (Exception $exception) {
        return
            (new ErrorResult())
                ->json($exception->getCode(), $exception->getMessage())
            ;
    }

    Кроме того появляется куча параметров в проекте.

    На помощь приходит паттерн Dependency Injection Container (Service Container), который за нас это делает и всасывает в себя эту заботу, а мы продолжаем писать код и делать это быстро, доставляя features for customers
    Ответ написан
    1 комментарий
  • Куда размещать бизнес логику приложения laravel?

    @NubasLol
    Мое мнение, что в модельках должна быть логика только связанная с получением данных с базы. Бизнес логика, пишется в отдельных сервис классах, как у вас, например, класс фильтр.

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

    Контроллер же просто дерижер, который принимает запрос, обрабатывает, дергает нужные методы приложения, и отдает ответ. Сложной логики в нем писать не нужно
    Ответ написан
    9 комментариев
  • Как разделить массив php?

    mosesfender
    @mosesfender
    Меланхолик, параноик, падал с коек
    Для извлечения первого элемента есть array_shift(). Вставь его в новый массив. А что останется - то второй массив.
    Ответ написан
    Комментировать
  • Как правильно настроить автодеплой в веб разработке?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    в bitbacket встроенное средство pipelines
    Ответ написан
    Комментировать
  • Как перейти с utf8 на utf8mb4 в MySQL?

    При такой конфигурации
    [mysqld]
    init_connect='SET collation_connection = utf8mb4_unicode_ci'
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    
    [client]
    default-character-set = utf8mb4

    имеем

    +--------------------------+--------------------+
    | Variable_name                  | Value                       |
    +------------------------------+------------------------+
    | character_set_client          | utf8mb4                  |
    | character_set_connection | utf8mb4                  |
    | character_set_database    | utf8mb4                  |
    | character_set_filesystem  | binary                      |
    | character_set_results       | utf8mb4                   |
    | character_set_server        | utf8mb4                   |
    | character_set_system       | utf8                          |
    | collation_connection        | utf8mb4_general_ci |
    | collation_database          | utf8mb4_unicode_ci |
    | collation_server               | utf8mb4_unicode_ci |
    +-----------------------------+------------------------+
    10 rows in set (0.01 sec)
    Ответ написан
    2 комментария
  • Как правильно передавать один общий объект?

    @Alkimista
    Тут хорошая статья на эту тему :)
    Мы у себя на проекте активно использует подход с rxjs shareReplay.
    https://blog.thoughtram.io/angular/2018/03/05/adva...
    Ответ написан
    Комментировать
  • Как получить все Headers из Response?

    spnq
    @spnq
    Frontend Developer
    Попробуй добавить хедер 'access-control-expose-headers' : '<header-name>' на API.
    Про суть твоей проблемы вот тут есть.
    Вкратце, по-умолчанию открыты для получения только 6:
    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma
    Ответ написан
    1 комментарий
  • Как запустить скрипт на удаленном экране через ssh?

    vesper-bot
    @vesper-bot
    Любитель файрволлов
    Запустить xterm с командой, он подхватит DISPLAY и отобразится на локальных иксах, а вывод консольной команды отобразится в xterm. До консоли можно достать, если перенаправить вывод в /dev/ttyXX какая отвечает за консоль, или /dev/console, но возможны артефакты.
    Ответ написан
    1 комментарий