Задать вопрос
  • "Разработка cms" как тема диплома?

    copist
    @copist
    Empower people to give
    UPD: Одним из главных требований дипломной работы - применение работы в реальной жизни. Такие работы лучше оцениваются и защита проходит легче.


    Не вижу более идеального практического применения, как подтюнить новый или существующий сайт/блог/магазин/портал для сбора метрик или оценки usability. Очень практично - в работе пригодится. И наглядно - будет много картинок к диплому, графики.
    Ответ написан
    Комментировать
  • Как одному успевать учиться в университете, делать домашнюю работу, готовить, стирать, убирать, в свободное время пилить свой проект и не повеситься?

    copist
    @copist
    Empower people to give
    Лёгких путей ищете?
    Выкинь верёвки, провода, шнурки, ремни и другие штуки, на которых можно повеситься.
    Ответ написан
    Комментировать
  • Как вернуть мотивацию к обучению?

    copist
    @copist
    Empower people to give
    Я сначала хотел дать вот такую ссылку htt_://copi.st/demotivator но это голимый демотиватор. Не читай.

    На самом деле часто бывает разочарование из-за того, что время за книгами тянется, а ощущения "всемогущества" нет. Где-то изначально была ошибка в оценке времени. По моей оценке на технологию уходит месяца три, а то и больше. Вот мои рассчёты.
    Учитывая, что для веб-разработки мало знать один язык программирования, нужно пройти ещё дополнительно 3-4 курса и основательно попрактиковаться. 3 месяца * 4 курса = год, может быть полтора года на освоение того, что должен знать junior web developer.

    Не отчаивайся по поводу недостаточной скорости. Просто иди вперёд.

    И ещё постоянно хочется сменить направление. Неа. Занеси в todo, поставь зарубку на будущее, и двигайся дальше по плану. Если слишком часто менять курс, то будешь крутиться на месте.
    Ответ написан
    Комментировать
  • Как пишется программа под определенную систему?

    copist
    @copist
    Empower people to give
    Решения есть.
    Пишется общая часть с использованием библиотек (SDK). Код программы при этом один на все платформы. Почти один. А у этого SDK есть вторая часть - компилятор, которая обеспечивает исполнение программы на конкретной платформе. Свой программный код нужно либо под каждой платформой откомпилировать, либо эта вторая часть занимается конвертированием промежуточного кода (байткод) в конкретного процессора.

    Для мобильных: Обзор 7 самых популярных кроссплатформенных мобиль..., Выбираем мультиплатформенный движок для разработки... и часть 2
    И вот это ещё: www.develop-online.net/tools-and-tech/the-top-16-g...

    В гугле искать по фразам:
    кроссплатформенные игровые движки
    кроссплатформенная мобильная разработка
    cross platform engine
    Ответ написан
    Комментировать
  • Какая музыка эффективна для сопровождения работающего программера?

    copist
    @copist
    Empower people to give
    Могу только стили написать. Lounge, Trans, New Agе.
    Ответ написан
    Комментировать
  • Какие задачи нужно уметь выполнять на JS начинающему?

    copist
    @copist
    Empower people to give
    Какие задачи нужно уметь решать на чистом JS, перед тем как переходить к изучению библиотек и фреймворков?


    Кроме синтаксических конструкций, математических и логических выражений, нужно знать:
    • Область видимости переменных
    • Замыкания
    • Объектно-ориентированное программирование, в частности наследование через прототипы
    • Шаблон проектирования "модуль"
    • Операции над DOM
    • Понимание принципов событийно-ориентированного программирования
    Важно - нужно знать, откуда копипастить.
    Тебе нужно быть очень хорошо знакомым с одной-двумя-тремя популярными библиотеками на JavaScript. В идеале ты должен иметь представление о том, что определённый класс задач может быть решен с помощью определённых библиотек, хотя бы одной, но такие знания приходят с практикой. Вообще ты должен быть знаком с ними так близко, чтобы помнить, в какой части мануала по библиотеке можно найти описание форматов входных данных нужной тебе функции и какой будет результат, чтобы скопировать и вставить в свой код, а потом поправить, чтобы работало.

    Важно - инструменты программиста JavaScript
    У тебя должен быть удобный инструмент для разработки (IDE, Integrated Development Environment), чтобы он тебе подсвечивал код (syntax highlight) и подсказывал о синтаксических ошибках (syntax check), о формальных параметрах функций (type hinting), о стиле кодирования (code style), помогал писать код (live templates).
    Ты должен знать, как отлаживать скрипты в популярных браузерах (Firebug, Chrome Developer Tools и другое). Что такое точки останова, как управлять исполнением во время останова, как посмотреть и поменять содержимое переменных, как настроить останов по условию.

    Хотелось бы узнать что это за задачи(упомянутые вами 80%)


    Реальные задачи джунов:
    1. Возьми из сборника задач по javascript любой скрипт случайно и вслух расскажи, что он делает.
      Важно - читать и понимать чужой код намного важнее, чем писать свой. И на работе тебе это приддётся делать чаще, чем ты думаешь. Чтобы подключить к своему проекту чужую JS либу, нужно понимать что она делает, как она конфигурируется, как управлять её поведением. Скажу точно, что написать свой скрипт, который строит графики, намного сложнее, чем понять, как настраивается highcharts.

    2. Напиши скрипт на JS, который в заданном тексте удалит один или два символа, выбранных случайно
      1. Усложнение: удалять можно только буквы в словах, а знаки пунктуации и цифры удалять нельзя
      2. Усложнение: принять, что этот текст является программной на Javascript, удалить одну-две команды JS, но только если они не в строковых литерах (break как команду удалить можно, а в строке "break my heart" нельзя)
      3. Усложнение: воспользуйся этим скриптом и "попорти" код какого-нибудь другого скрипта на Javascript, а потом отладь, найди ошибку и восстанови работоспособность
      Важно - этим обычно все и занимаются - ищут баги. Только в реальной жизни они и без этого скрипта появляются. И не по одному, а прям пачками.

    3. На страницу HTML нужно встроить график курса доллара по отношению к рублю. Формат входного массива значений курса определи сам, исходя из своего скрипта для построения графиков.
      1. Усложнение: на одном графике должны быть два курса, по разным шкалам. Наприме, курс доллара к евро и курс юаня к рублю
      2. Усложнение: первоначально график вывести в детализации по месяцам, но чтобы можно было "приблизить" (drilldown) детализацию до дней
      3. Усложнение: первоначально график вывести текущем месяце, но чтобы можно было загрузить данные для предыдущего месяца без перезагрузки страницы (AJAX)

    4. При клике по картинкам, вставленным в текст HTML, показывать всплывающее окно для просмотра увеличенной картинки.
      1. Усложнение: в всплывающем окне сделать навигацию по картинкам, вперёд/назад и к нужной картинке
      2. Усложнение: в всплывающем окне вместо картинки показать видео-ролик с Youtube
      3. Усложнение: в всплывающем окне показать текст HTML

    5. По клику на кнопку "Click me" показать всплывающую форму.
      1. Усложнение: реализовать проверку данных на корректность перед отправкой формы (непустое значение, минимальное количество символов, максимальное количество символов, минимальное числовое значение, максимальное числовое значение)
      2. Усложнение: если в значении текстового поля встретилась гиперссылка, то считать её за 22 символа при любой длине этой ссылки (как в твитере)
      3. Усложнение: реализовать отправку формы на сервер через AJAX, без перезагрузки страницы
      4. Усложнение: саму форму в виде HTML загрузить с сервера через AJAX, в момент клика по кнопке "Click me", правила проверок данных должны как-нибудь "извлечься" из самой загруженной формы, например из аттрибутов полей ввода

    6. К форме ввода данных на поле ввода даты "навешать" всплывающий календарь для выбора даты.
      1. Усложнение: сделать форму календаря мультиязычной. Хотя бы через настройки на том же JavaScript
      2. Усложнение: сделать так, чтобы с помощью календаря можно было выбрать диапазон дат, чтобы она была привязана к двум полям формы "дата начала" и "дата окончания", и чтобы значение в поле "дата начала" обязательно была меньше чем в поле "дата окончания"
      3. Усложнение: сделать так, чтобы с помощью в календаре можно было видно визуально этот диапазон
      4. Усложнение: диапазон может быть открытым, но не пустым, то есть пользователь должен задать хотя бы дату начала или дату окончания.

    7. Сделать пред-просмотр веб-страницы HTML с разными темами. Тему страницы выбирать через селектор на javascript, а показывать в фрейме.
      1. Усложнение: сделать селектор "тип устройства", чтобы менять размер фрейма (например, "iPhone 5c 1136x640") и "чекбокс" для смены ориентации страницы "горизонтальная" или "вертикальная" (соответственно 1136x640 или 640x1136)
      2. Усложнение: в селекторе тем предусмотреть поиск тем по подстроке, и аналогично поиск устройств по части названия (авто-дополнение, auto-complete)
      3. Усложнение: тема страницы должна меняться без перезагрузки фрейма



    Задачи повышенной сложности, исходя из личного интереса
    1. Реализовать форму для многошагового мастера: форма должна состоять из нескольких страниц (шагов), пользователь может переключать страницы через какие-нибудь элементы управления "вперёд/назад" или "перейти на страницу".
      1. Усложнение: реализовать функциональную связь значений, когда некоторые данные зависят друг от друга (ввёл число в поле "количество" и в поле "сумма" значение пересчиталось)
      2. Усложение: доступность некоторых полей ввода должна зависеть от данных (например, если указал "есть личный самолёт", то значит можно ввести "марка самолёта")
      3. Усложение: видимость некоторых страниц должна зависеть от данных из предыдущих страниц (например, если указал "есть личный самолёт", значит появилась страница "ТТХ самолёта"; иначе страница должна скрыться)

    2. Реализовать однопользовательскую браузерную игру "змейка", "тетрис", "найди пару"
    3. Реализовать многопользовательскую браузерную игру "крестики-нолики", "морской бой" на два игрока в режиме "hot seat"
      1. Усложнение: два игрока на разных компьютерах, ходы передаются по websocket
      2. Усложнение: ограничение на ожидания окончания хода 15 секунд, по окончании ожидания автоматически делается случайный ход

    4. Реализовать todo-list. Пользователь вводит список, затем он превращается в строки с "чек-боксами". Когда "чекбокс" включен, строка зачёркивается.
      1. Усложнение: пользователь может переименовывать, удалять, добавлять строки
      2. Усложнение: список хранить в localStorage браузера, чтобы при перезагрузке страницы он восстанавливался
      3. Усложнение: пользователь может иметь несколько независимых списков todo

    5. Реализовать простой графический редактор. Пусть рисуется точка в месте, где пользователь кликнул.
      1. Усложнение: добавить переключатель режимов "точка"/"линия", в режиме "линия" рисуются линии между двумя последовательно кликнутыми точками
      2. Усложнение: можно менять толщину, цвет линий, размер точек
      3. Усложнение: последовательность кликов можно воспроизвести ещё раз с самого начала, равномерно или с реальной задержкой между кликами, с обычной скоростью или ускоренно
      4. Усложнение: можно выгрузить получившийся рисунок в формате PNG или SVG, причём SVG c анимацией воспроизведения



    Можно использовать любую существующую библиотеку.
    Например,
    для построения графиков www.highcharts.com
    для загрузки и передачи данных через AJAX: jquery.com + что-нибудь на сервере
    для всплывающих диалогов с картиками, видео и формами: fancyapps.com/fancybox и https://jqueryui.com/dialog/
    для валидации форм rickharrison.github.io/validate.js
    для календаря https://jqueryui.com/datepicker/
    для автодополнения https://jqueryui.com/autocomplete/
    для передачи данных между несколькими пользователями socket.io или обычный AJAX
    Ответ написан
    16 комментариев
  • Как удалить объект, вызвав какой-либо его же собственный метод (PHP)?

    copist
    @copist
    Empower people to give
    В объекте предусмотрите приватное свойство-флаг, который будет означать, что этот объект нехранимый.

    <?php
    class Dummy
    {
        /**
         * Хранимый ли?
         * @var boolean
         */
        private $persistent = true;
    
        public $me;
    
        function __construct($me)
        {
            $this->me = $me;
        }
    
        public function forgetMe()
        {
            $this->persistent = false; // теперь нехранимый
        }
    
        /**
         * Какая то логика при сохранении
         */
        public function save()
        {
            if (!$this->persistent) // если нехранимый
            {
                echo $this->me . " was NOT saved\n";
                return true; // понять, простить и забыть
            }
            echo $this->me . " saved OK\n";
        }
    }
    
    $obj1 = new Dummy('first');
    $obj2 = new Dummy('second');
    
    $obj1->forgetMe();
    $obj1->save(); // -> first was NOT saved
    $obj2->save(); // -> second saved OK
    Ответ написан
    Комментировать
  • Какую структуру WEB API вы используете в своих проектах: api.site.ru или site.ru/api/?

    copist
    @copist
    Empower people to give
    Выбор делается исходя не из красивости звучания, а по тому, являются ли api.site.ru и site.ru физически одной инсталяцией приложения или двумя.
    Если у двух доменов одна общая кодовая база, а отличается только логика на уровне роутинга запросов, то нет смысла заморачиваться с поддоменами.

    Минусы поддоменов:
    Отдельные поддомены - это отдельный запрос браузера к DNS. Это время.
    Если всё ваше приложение работает на SSL (а вам придётся перейти на него, когда захотите в статистике Google Analytics видеть рефереров) - на поддомены вам надо будет отдельные сертификаты, или wildcard сертификат.
    И если поддомены работают на SSL, то браузер сделает дополнительный хэндшейк для обмена ключами с каждым поддоменом.
    Если управление поддоменами ручное и вам придётся хостинг поменять, то руками двигать устанете.

    Почему к какого-нибудь сайта поддмены третьго-четвёртого уровня?
    Потому что, может быть, у них сервера API дублируются географически для распределения нагрузки.
    Можно сделать ping на каждый поддомен и убедиться - у них, скорее всего, будут разные IP.
    Выбираются автоматически или иным способом исходя из местонахождения пользователя.

    Адрес домена API на SEO почти не влияет. Почти - это потому что гуглобот считает время от обращение к серверу до момента отрисовки страницы целиком, включая загрузку стилей, шрифтов, скриптов JS, загрузку данных и рендеринг страницы в своём виртуальном браузере. Если учесть пункты выше, то на установку соединения и хэндшейки придётся потратить время. По косвенным признакам медленные сайты имеют больше позицию в поисковой выдаче, то есть дальше от первого места. А вот откуда данные на странице появились, гуглоботу начхать.

    Но иногда приходится жертвовать скоростью на DNS resolve и SSL handshake, и делать поддомены, если требуется выдавать много данных за раз. Например, если на странице очень много картинок, то браузер будет пытаться загружать их одновременно. В браузере есть ограничение на количество конкурентных запросов на один домен, кажется = 6. То есть пока не загрузятся 6 картинок (site.ru/img/1.jpg, ...), javascript не сможет обратиться к к данным на том же домене site.ru/api.
    Варианты:
    1. вынести всю статику (стили, картинки, скрипты) на поддомен static.site.ru - пусть статика тупит в отдельных запросах; причём javascript и css должны загрузиться первыми
    2. выделить для api поддомен api.site.ru

    Я обычно делаю первый вариант, но всё зависит от нагрузки.

    Пример: сайт icons8.com, API работает на домене api.icons8.com и является независимым приложением, статика отдаётся через maxcdn.icons8.com
    В данном случае я ожидаю рост нагрузки и при необходимости количество серверов будет увеличено, нагрузку распределю путём балансировки в nginx, а имя у них останется одно api.icons8.com
    Чтобы время на DNS resolve уменьшить, используем DNS Amazon - он вроде самый быстрый. Ну и MaxCDN тоже использует Amazon и в общем потеря почти не ощущается.

    Замеры времени делали через утилиту www.webpagetest.org - классный сервис, просто золото.
    Ответ написан
    Комментировать
  • Если одной группе пользователей доступна страница, которая недоступна другой, то какой редирект надо делать для второй группы?

    copist
    @copist
    Empower people to give
    302, чтобы браузер не запомнил этот редирект.
    301, чтобы запомнил. в том числе запоминает и гуглобот.

    В данном случает надо 302.
    А если авторизованный пользователь или аноним лезет куда-то, куда ему лезть не положено по его правам, то 403 без редиректов.
    Ответ написан
    Комментировать
  • Как сделать serialize?

    copist
    @copist
    Empower people to give
    Всё дело в том, что в вашем примере 53, 55 и 56 - это должны быть строки. Надо принудительно приводить числа к строкам, чтобы 1:1 получить именно результат a:3:{i:0;s:2:"53";i:1;s:2:"55";i:2;s:2:"56";}
    <?php
        $a = array(
            0 => "53",
            1 => "55",
            2 => "56"
        );
    
        $b = serialize($a);
        echo $b; # a:3:{i:0;s:2:"53";i:1;s:2:"55";i:2;s:2:"56";}
    Ответ написан
    4 комментария
  • Как убрать повторяющиеся блоки с собесдником?

    copist
    @copist
    Empower people to give
    Возможно, это тестовый пример чата. Первая реализация.
    Что ты хотел показать в списке сообщений? Все сообщения, которые кто-то кому-то написал? Тогда он работает правильно. Счётчик только не используется и зачем то в таблице есть dialog_id, но ты его тоже не используешь, а вместо этого группируешь по from + to.

    Я бы для удобства визуально чат по-другому построил.
    Посмотри вот на такой мокап https://icons8.com/2015/07/17/icons8-wpf-ui-framework/, точнее вот этот экран take.ms/5F5rr
    С левой стороны список контактов, кому недавно писал ты или кто ответил тебе.
    Для его построения нужен такой запрос
    SELECT DISTINCT A.`user_id`
    FROM(
       SELECT m1.`from` as `user_id`, m1.`date` FROM `messages` m1 WHERE m1.`to` = 7
       UNION
       SELECT m2.`to` as `user_id`, m2.`date` FROM `messages` m2 WHERE m2.`from` = 7
       ORDER BY `date` DESC
    ) A

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

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

    Как тестовый пример - норм. Вопросов нет.
    Если в пром эксплуатации, то хранить отдельные сообщения в реляционной базе накладно. Слишком много записей в таблицах. Желательно использовать NoSQL базу и хранить в одной записи базы один диалог целиком.
    Ответ написан
  • Почему переменная остается пустой, после присвоения ей значения в операторе switch?

    copist
    @copist
    Empower people to give
    Два замечания
    <?php
    $page = (isset($_GET['page'])) ? $_GET['page'] : 'index.php';
    
    $layoutModificator = '';
    
    // комментарий: определять значение $layoutModificator нужно до того, как она "эхается" в <body>
    switch ($page) {
    	case 'slider':
    		$includeFile = "page/slider.php";
    		break;
    	case 'animation':
    		$layoutModificator = "splash";
    		$includeFile = "page/animation.php";
    		break;
    }
    // комментарий: вот тут ниже пустая строка - потенциальная проблема, особенно при выдаче заголовков header(...);
    ?>
    <!-- .... -->
    <body class="<?php echo $layoutModificator;?>">
             <!-- .... -->
    				<?php include($includeFile); // вместо switch ?>


    Полный текст решения codepad.org/7dYnHaxp
    Ответ написан
    3 комментария
  • Как изменить uri на новый (для обработки другим локейшном) без редиректа?

    copist
    @copist
    Empower people to give
    Посмотри документацию на nginx/rewrite
    Если правило "куда" не включает схему (http:// или https://), то можно сделать внутренний редирект.

    Файлы
    /old/path/index.html с текстом "Old";
    /new/path/index.html с текстом "New";
    download?id=AmPy05G2J5pmqNOR6UxhRP56pXVj

    Попробуй такое правило
    location ~ /old/path {
        rewrite /old/path(.*) /new/path$1 break;
    }

    У меня браузер остался с прежним URL, но показал файл по новому пути
    download?id=jNnoITrzRcwF9wcxezeF8AzSoWp6
    Ответ написан
    Комментировать
  • Как распарсить doc Обработать php и сохранить обратно?

    copist
    @copist
    Empower people to give
    Посмотри вот этот набор библиотек для работы с документами MS Office https://github.com/PHPOffice

    В частности PHPWord
    A pure PHP library for reading and writing word processing documents


    После изучения исходников и stackoverflow, могу сказать, что в PHP нельзя беспроблемно прочитать любой документ MS Word.

    На этом месте я предлагаю выдохнуть, выпить зелёного чая с мятой, накапать валерьянки.
    Далее придётся работать с C# или c макросами на Visual Basic for Office.
    Как-то так.
    Ответ написан
    5 комментариев
  • Как общается фронтенд с БД в real-time webapp (на примере чата)?

    copist
    @copist
    Empower people to give
    Посмотрите вживую чат на технологии websocket chat.socket.io и код этого чата на github https://github.com/socketio/socket.io/tree/master/...

    Есть ли концептуальная разница между решениями этой задачи на бэкендах laravel и nodejs?

    Концептуальная разница в том, что в данном случае сервер websocket уже работает на node.js и сам может обращаться к базе данных. А в случае с Laravel нужна будет прослойка между PHP и node.js которая обычно делается на какой-нибудь асинхронной очереди типа RabbitMQ.

    As of November 2013, Socket.io's list of supported browsers was:

    Desktop:
    • Internet Explorer 5.5+
    • Safari 3+
    • Google Chrome 4+
    • Firefox 3+
    • Opera 10.61+

    Mobile:
    • iPhone Safari
    • iPad Safari
    • Android WebKit
    • WebOs WebKit


    They achieve this level of support by using a variety of transports, depending on what the browser is capable of (again, from November 2013):

    • WebSocket
    • Adobe® Flash® Socket
    • AJAX long polling
    • AJAX multipart streaming
    • Forever Iframe
    • JSONP Polling


    По-русски: они поддерживают всё браузерное старьё, что есть, путём комбинациии шести технологий, начиная от современного WebSocket и заканчивая JSONP
    Ответ написан
    3 комментария
  • Как настроить сортировку типа 1-2-10-11 для массива в PHP?

    copist
    @copist
    Empower people to give
    Сортировка массивов в натуральном порядке значений из подмассивов с помощью uksort + strnatcmp()

    $unsortedArray = array(
        'import_files/5d/namers.jpg' => array('description' => '1 колечко блестящее'),
        'import_files/5d/name31.jpg' => array('description' => '10 морозное утро'),
        'import_files/5d/name13.jpg' => array('description' => '4 морозное утро'),
         // ...
    );
    uksort($unsortedArray, function($a, $b) use($unsortedArray) {
        return strnatcmp($unsortedArray[$a]['description'], $unsortedArray[$b]['description']);
    });


    Решение полностью codepad.org/2AaS37SE
    Ответ написан
    Комментировать
  • Как организовать взаимодействие между REST бэкендами?

    copist
    @copist
    Empower people to give
    Это называется SOA: сервисы, общающиеся между собой.

    Таким образом, например, посылается почта - один бакенд (твой сервер) передаёт соощение другому бакенду (почтовый сервер) по протоколу SMTP.
    Можно заливать файлы на другой сервер - протокол WebDAV, FTP или CSP.
    Твой сервер может постить твиты от имени другого пользователя - это делается через HTTP, при наличии токена авторизации. Запросы отправляются через curl или Guzzle.

    Но как это лучше делать если серверам нужны данные друг от друга? Обычные curl запросы?

    В общем, curl - это норм.
    Ответ написан
    2 комментария
  • Как получить GET параметры в MVC?

    copist
    @copist
    Empower people to give
    Позвольте всобачить сюда свой велосипед. Так сказать, самый сок.

    Пример разбора параметров $_GET:
    <?php
    class AppRequest {
    
    	protected $_get;
    
    	/**
    	 * Normalizes the request data
    	 * This method strips off slashes in request data if get_magic_quotes_gpc() returns true
    	 */
    	protected function normalizeRequest() {
    		if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
    			if(isset($_GET)) {
    				$_GET = $this->stripSlashes($_GET);
    			}
    		}
    		if(isset($_GET)) {
    			$this->_get = $_GET;
    		}
    	}
    
    	/**
    	 * Returns the named GET parameter value
    	 * If the GET parameter does not exist, the second parameter to this method will be returned
    	 * @param string $name the GET parameter name
    	 * @param mixed|null $default the default parameter value if the GET parameter does not exist
    	 * @return mixed|null the GET parameter value
    	 */
    	public function getQueryVar($name, $default = null) {
    		if (isset($this->_get[$name])) {
    			return $this->_get[$name];
    		}
    		return $default;
    	}
    
    	/**
    	 * Returns the request URI portion for the currently requested URL
    	 * @return string the request URI portion for the currently requested URL
    	 */
    	public function getRequestUri() {
    		static $requestUri;
    		if (!isset($requestUri)) {
    			if(isset($_SERVER['REQUEST_URI'])) {
    				$requestUri = $_SERVER['REQUEST_URI'];
    				if(!empty($_SERVER['HTTP_HOST'])) {
    					if(strpos($requestUri, $_SERVER['HTTP_HOST']) !== false) {
    						$requestUri = preg_replace('/^\w+:\/\/[^\/]+/', '', $requestUri);  // remove schema and host name "schema://host/"
    					}
    				} else {
    					$requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri); // remove schema and host name "schema://host/"
    				}
    			}
    		}
    		return $requestUri;
    	}
    }

    весь код класса AppRequest

    Вариант логики разбора строки URL:
    Если есть какая-нибудь логика для коротких человеко-читаемых URL, то надо привести их к формату
    controller/action + все дополнительные параметры из URL перенести в переменные $_GET или завести для них отдельный специальный массив в класса AppRequest. Такое можно сделать путём статического разбора строки или регулярными выражениями.

    Пример:
    на вход / -> на выход home/index
    на вход /my-home-page/ -> на выход home/welcome
    на вход /photo/summer.jpg -> на выход gallery/view + $_GET['image-alias'] = 'summer.jpg'
    на вход /wiki/path/to/article.html -> на выход wiki/view + $_GET['page-alias'] = 'path/to/article'

    После этого преобразовать имя контроллера в имя класса, а имя действия - в метод (как в моём велосипеде).
    class HomeController {
        function indexAction() {
            echo "Welcome!";
        }
    }

    Полный пример разбора в классе AppRouter + файл конфигурации с правилами
    Пример правил для указанных выше 4х случаев:
    // Incoming URL mathing rules
    $rules = array(
    	// if request URI is empty
    	'' => array('home', 'index'), // -> код контролера + код действия
    
    	// if request URI looks like /my-home-page/ 
    	'/^my-home-page$/' => array('HomeController', 'indexAction'), // -> имя класса контроллера + имя функции
    
    	// if request URI looks like /photo/summer.jpg
    	'/^/photo/(?<alias>.+)$/' => array('gallery', 'view', array('image-alias' => ':alias')),
    
    	// if request URI looks like /wiki/path/to/article.html
    	'^/wiki/(?<alias>.+)\.html$' => array('wiki', 'view', array('page-alias' => ':alias')),
    );


    А можно поменять роутинг так, чтобы под каждое действие был отдельный класс
    class HomeIndex {
        function run() {
            return new AppResponse("Welcome!");
        }
    }

    В некоторых микро-фреймворках можно даже функции назначать
    function home_index() {
        return new AppResponse("Welcome!");
    }
    $routes = array(
        '/my-home-page/' => 'home_index',
    );

    И даже использовать анонимные функции, тогда у них вся логика приложения вообще в один конфигурационный файл вмещается
    $routes = array(
        '/my-home-page/' => function() { return new AppResponse("Welcome!"); },
    );
    Ответ написан
    Комментировать
  • Как научиться грамотно писать код?

    copist
    @copist
    Empower people to give
    Ну, может быть нанять лида или ментора - есть такие конторы. Будут ревьюить код и носом тыкать в неудачные места. Хочешь, я помогу.
    Контакты copist.ru/about
    Ответ написан
    Комментировать
  • Как в yii 1.1.16 заблокировать таблицу mysql на чтение и запись?

    copist
    @copist
    Empower people to give
    1. Права на запись пользовалем MySQL
    REVOKE *.* ON <database>.<table> FROM <username>@localhost;
    GRANT SELECT, REFERENCE ON <database>.<table> TO <username-readonly>@localhost; -- только SELECT c JOIN

    Из Yii подключаешься к базе пользователем <username-readonly>. Такой способ запретит создавать/изменять/удалять записи таблиц, на которые не были выданы права через GRANT пользователю <username-readonly>
    Не очень гибко. Админ наверное хотел бы писать во все таблицы.

    2. Права текущего пользователя Yii через ACL или RBAC
    www.yiiframework.com/wiki/346/acl-and-rbac
    Не очень надёжно. Можно забыть про проверку в каком-нибудь месте.

    3. Можно поковыряться с CActiveRecord или CMysqlCommandBuilder, чтобы на запросы, содержащие INSERT/UPDATE/DELETE в некоторые таблицы выдавался false или бросалось исключение, если текущий пользователь - не админ.
    Уже лучше, но парсить SQL запросы будет сложно.
    Ответ написан