-Поиск по дневнику

Поиск сообщений в a1addin

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 20.06.2010
Записей: 245
Комментариев: 125
Написано: 872





Заметки непрограммиста: как пишу программу.

Воскресенье, 22 Февраля 2015 г. 09:32 + в цитатник

Диалог на производстве:

- Сделали проект для производства. Протестировали. Можно брать в работу?
- Не-е-ет.
- Почему?
- А надо еще, чтобы (по условию) результаты мастер проверял!

("Результаты" стоят в цехе, комп мастера стоит в бюро).

- Ладно... Давай так: система сама отследит наступление (события по условию) и на офисный принтер будет распечатывать задание на проверку? Мастер с заданием в цехе все проверит и потом в офисе на компе результат перенесет в систему?
- Давай попробуем.

Теперь надо браться за реализацию. С любого конца. Например, с этого:

Печать на офисный принтер

Хотелось бы следовать принципу, что вся конфигурация выполняется в программе и при замене, например, офисного принтера чтобы было достаточно указать его новый сетевой адрес.
Но есть еще драйверы принтеров и пришлось на сервере поставить CUPS и вывод на печать пустить через него:

   $printer = 'Samsung';  // название принтера в CUPS
   $cmd = "lp  -d ".$printer." /var/www/pdf.pdf";  //команду оформил как переменную PHP
   $log = "exec:".exec($cmd,$output)."<br>";    // и выполняю через ф-ю exec(). Результат

Наступление события по условию

После обдумывания немногочисленных вариантов (например с триггером MySQL) остановился на очевидном: проверять условие в PHP-скрипте при каждой регистрации единицы готовой продукции в базе данных.

Оформление задания

Хочется просто и эстетично. PDF-тэмплэйт ? Посмотрел, как из PHP сделать PDF-документ. Остановился на проекте mPDF

Нумерация задания

по порядку для каждой даты. Каждый день сначала. Формат: NN-YYMMDD

Педали

Надо добавить в панель управления возможность отключать эту проверку (1), менять параметр условия (2) и назначать принтер (3).

Запись в таблицу

Надо добавить в базу данных таблицу, в которой буду сохранять параметры задания (дата, номер, первый и последний проверяемый id) и отмечать выполнение (дата, кто проверял)

Запись в лог

"У меня все ходы записаны !" (Ильф, Петров. Двенадцать стульев)
Печать задания должна отображаться в логах.

Рубрики:  Технические обзоры
Программирование

Метки:  

Tunnelblick, добавление route после подключения

Четверг, 29 Января 2015 г. 07:49 + в цитатник

tblk (55x55, 4Kb)

В Tunnelblick добавление route после подключения можно сделать просто, если в состав tblk-пакета добавить скрипт connected.sh:

#!/bin/bash
/sbin/route -n add address gateway


Цитата: "...scripts are run as root..."

См.здесь: https://code.google.com/p/tunnelblick/wiki/cUsingScripts

Рубрики:  Технические обзоры

Метки:  

COMPRESS (ZIP) FOLDER ON LINUX DEBIAN

Понедельник, 26 Января 2015 г. 01:17 + в цитатник

Compress (ZIP) folder on Linux Debian:

tar -czvf name.tar.gz folder/

Decompressing (unzipping) is here:

gunzip name.tar.gz

Источник: https://jarik.wordpress.com/2013/04/05/compress-zip-folder-on-linux-debian/

Рубрики:  Технические обзоры

Метки:  

Тюнинг web-сервера

Пятница, 23 Января 2015 г. 22:31 + в цитатник
napiljnik (178x141, 31Kb)

Получил письмо с жалобой, что один из производственных серверов стал вместо отчетов возвращать сообщение об ошибке:

"Fatal error: Maximum execution time of 30 seconds exceeded in ..."

Ну что ж, не хватает 30 секунд, установленных по умолчанию?

Не проблема, в файле php.ini увеличил значение параметра max_execution_time в php.ini до 60 секунд.

Но проблема осталась, только изменилось сообщение об ошибке:

"Fatal error: Uncaught exception 'MyException' with message 'Database query failed! Query: exec rep_period...' Error: Timeout expired ' in [filename]:37 Stack trace: #0 [internal function]: __lambda_func(1024, 'Database query ...', [filename]', 37, Array) #1 [filename](37): trigger_error('Database query ...') #2 [filename](41): db_execute(Object(com), 'exec rep_period...') #3 {main} thrown in [filename] on line 37"

Почитал документацию и понял, что действие max_execution_time не распространяется на обращения к базе данных. Значит надо смотреть способ подключения сервера к базе данных. В данном случае в код скрипта добавил строку:

$cnn->CommandTimeout=60;

и всё получилось.

Рубрики:  Технические обзоры
Программирование

Метки:  

HTML: передавать через SELECT массив значений

Воскресенье, 11 Января 2015 г. 11:57 + в цитатник
Как-то раз потребовалось и, к удивлению, получилось.
Удивление было еще большим, когда возвращенный массив вернул не только значения элементов массива, но и разделительные запятые как члены массива. У меня два решения. Правильное: при помощи explode сделать "правильный " массив и пользоваться им. Неправильное: "забить" на все нечетные элементы (которые возвращают запятые) и вызывать только четные.

Пока пользуюсь неправильным решением, ибо оно оптимально.

Метки:  

XML_data = func(XML_схема, Excel_форма)

Воскресенье, 11 Января 2015 г. 02:50 + в цитатник

Если надо подготовить XML-файл с данными для отправки куда-то, который надо подготовить руками и есть XML-схема (xsd-файл), то может выручить MS Excel.
Сначала в Excele проверяем включен ли риббон "Developer":

3854108_excel_xml_1 (700x356, 114Kb)

Затем подключим XML-схему в наш новый excel-файл:

3854108_excel_xml_2 (700x615, 230Kb)

Последнее, что осталось - драг&дропом замэпировать каждый элемент схемы с конкретной  ячейкой листа таблицы, чтобы получилось нечто вроде такого:

3854108_excel_xml_3 (700x325, 101Kb)

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

После заполнения сохраняем:

3854108_excel_xml_4 (246x74, 2Kb)

Проверяю результат в notepad:

3854108_excel_xml_5 (594x639, 42Kb)

Вижу то, что и требовалось.

Рубрики:  Технические обзоры
Программирование

Метки:  

Три флэшки - уже лаборатория.

Понедельник, 01 Декабря 2014 г. 01:06 + в цитатник

История первая: "Дебиан"
Давным давно начал проект, который планировал сделать на линуксе. Начал с конца и быстро-быстро соорудил эмулятор готового продукта. Чтобы проект можно было показать где угодно, то систему поставил на старую заслуженную 16Гб-флешку. Получилось надежно, неприхотливо и шустро. Ситстема запускается на любом неяблочном компьютере. Проект давно уже живет своей жизнью, а флешка - своей: у меня всегда под рукой рабочий линукс.

История вторая, про виртуализацию.
После того, как стал владельцем мощного мака, жизнь приобрела новые краски. Стал активно работать с виртуальными машинами, но стало жалко стремительно уменьшающегося обьема SSD-диска на маке. Принял решение: отселить виртуальные машины на флэшку (128Гб, usb 3.0).
Красота получилась!

История третья: лабораторная работа.
Не люблю (не допускаю) экспериментов на рабочей системе. Но и развивать систему, внедрять новые решения - надо. Поэтому взял еще одну флэшку, поставил на нее аналог рабочей системы (проект OpenFiler) и отладил метод подключения iSCSI-дисков к линукс-серверу с ОС Дебиан.

Важное примечание: во время лабораторных работ ни одна рабочая система не пострадала :)

Рубрики:  Технические обзоры
Вообще

Метки:  

На прощание с сайтом Gazeta.LV

Суббота, 18 Октября 2014 г. 23:34 + в цитатник

На прощание с сайтом Gazeta.LV.

Заодно, приглашаю к дискуссии.
А еще, сегодня подал заявку на доменное имя Gazeta2.lv
Пока - без какого либо плана.
И еще раз подтверждаю свою готовность поделиться архивом сайта по состоянию на 15 сентября.
Его размер - 25ГБ.

Вся суета - потом.

А сейчас время для музыки Энио Морриконе...



Рубрики:  Вообще

Метки:  

О Курске

Вторник, 02 Сентября 2014 г. 23:46 + в цитатник

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

 



118 погибшим военным морякам отдаю честь. 

Рубрики:  Вообще

Метки:  

Головоломка для себя: создание страницы из панелей.

Понедельник, 01 Сентября 2014 г. 09:15 + в цитатник

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

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

Задача:

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

3854108_img0_1_ (416x274, 7Kb)

Решение

Составляю список параметров:

  1. кол-во строк с  панелями по вертикали Ny
  2. кол-во панелей по горизонтали для строки N(y)
  3. левое поле (отступ) Oleft
  4. правое поле (отступ) Oright
  5. верхний отступ Otop
  6. нижний отступ Obottom
  7. отступ между строками панелей Oy
  8. отступ между панелями в строке Ox
  9. закругление углов панели R
  10. высота панелей в строке H(y)
  11. ширина панели W(y,x)

Точка отсчета - верхний левый угол экрана.

Далее, продолжаю работать в относительной системе измерения, т.е. за основу берется максимальный размер экрана как 100%

Положим, кол-во строк с  панелями по вертикали Ny = 3 (как на рисунке)

Кол-во панелей по горизонтали N(1) =1; N(2) = 1; N(3) = 3

Левое поле (отступ) Oleft = Oright = Otop = Obottom = Oy = Ox = 5%

Высота панелей в строке H(1) = H(2) = H(3) = (100% - Otop - Obottom - (Ny -1) * Oy) / Ny = 80% / 3 = 26.6 %

Ширина панели W(1,1)  = W(2,1)  = 100% - Oleft - Oright  = 90%

Ширина панели W(3,1)  = W(3,2)  = W(3,3) = (100% - Oleft - Oright - (Nx -1) * Ox) / Nx = 26.6%

 

Теперь пишу CSS-файл test.css:

body {
background: #99CCFF;
}

#panel_1_1{
    position:absolute;
    top: 5%;
    left: 5%;
    width: 90%;
    height: 26.6%;
    border-radius: 20px;
    background: #FFFFCC;
}

#panel_2_1{
    position:absolute;
    top: 36.6%;
    left: 5%;
    width: 90%;
    height: 26.6%;
    border-radius: 20px;
    background: #FFFFCC;
}

#panel_3_1{
    position:absolute;
    top: 68.2%;
    left: 5%;
    width: 26.6%;
    height: 26.6%;
    border-radius: 20px;
    background: #FFFFCC;
}

#panel_3_2{
    position:absolute;
    top: 69%;
    left: 36.6%;
    width: 26.6%;
    height: 26.6%;
    border-radius: 20px;
    background: #FFFFCC;
}

#panel_3_3{
    position:absolute;
    top: 69%;
    left: 68.2%;
    width: 26.6%;
    height: 26.6%;
    border-radius: 20px;
    background: #FFFFCC;
}

И собственно html-файл test.html:

<html>
   <head>
      <link href="test.css" rel="stylesheet" type="text/css" />
   </head>
   <body>
      <div id="panel_1_1">
         panel_1_1
      </div>
      <div id="panel_2_1">
         panel_2_1
      </div>
      <div id="panel_3_1">
         panel_3_1
      </div>
      <div id="panel_3_2">
         panel_3_2
      </div>
      <div id="panel_3_3" onclick="alert('It work !');">
         panel_3_3
      </div>
</body>
</html>

Любую панель можно использовать как кнопку, чтобы вызывать событие. Для этого надо добавить инструкцию onclick в тег div.

Решение проверил в броузерах Firefox, Opera, Chrome и IE 8.0: только в IE страница отображается  некорректно.

Дополнение 1

Чтобы контент в панелях распологался строго по центру, я в css-файл включил класс:

.cnt {
    position:absolute;
    text-align: center;
    width: 100%;
    top: 50%;
}

Естесственно, что надо не забыть в HTML-коде "обернуть" контент в тег DIV или SPAN с этим классом.

Дополнение 2

Если надо построить вариант посложнее:

3854108_img0 (417x274, 9Kb)

то в этом случае предлагаю сл. принцип нумерации панелей:

  • нумерация выполняется по верхнему левому углу.
Рубрики:  Программирование

Метки:  

Mikrotik. Шаг за шагом.

Суббота, 23 Августа 2014 г. 20:20 + в цитатник

Попробую систематизировать процесс настройки рутера "с нуля". Не столько для того, чтобы "как делать", сколь для того, чтобы настраивая очередной рутер не забыть что-либо настроить. Т.е. - это некий TODO-список. Как пиджак украшают пуговицы и карманы, так и я украсил этот список заголовками и картинками.

Начинаю настройку с того, что подключаюсь через WinBox и соглашаюсь на предлагаюмую конфигурацию:

3854108_start (700x480, 244Kb)

 

 Обновление софта

Сначала открываю System - License и смотрю на номер версии, до которой позволено обновлять рутер:  

3854108_license (700x404, 62Kb)

Затем, открываю System - Packages и проверяю тип процессора (mipsbe) и текущую версию софта (5.24):

3854108_packages (700x402, 99Kb)

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

На сайте www.mikrotik.com проверяю доступную для обновления версию:

3854108_site (700x418, 161Kb)

В моем случае - это routeros-mipsbe-6.19rc.npk. Скачиваю этот файл и загружаю на рутер. Обновление выполнится автоматически после перезагрузки рутера.

 

Идентификация рутера

По пути System - Identify прописываю имя для рутера. Это имя будет отображаться в титульной строке программы и в имени бэкапных файлов.

 

Отделяю wlan-интерфейс из LAN-сети

  1. В окне Interfaces блокирую интерфейс wlan1
  2. В окне IP - Addresses адрес LAN-сети назначаю интерфейсу ether2-master-port
  3. В окне Bridge в закладке Ports удаляю все записи
  4. В окне Bridge в закладке Bridge удаляю  запись

 

Упорядочиваю порты рутера

В дефолтной конфигурации 1-й порт назначен для гэйтвея, 2-й порт - для мастер-порта свича LAN-сети.

Я предпочитаю "главные" порты разносить по краям, а порты между ними впоследствии гибко переназначать. Например, в моей практике бывают случаи, когда магистральный кабель надо подключить к двум приборам. В этом сдучае удобно 1-й и 2-й порты рутера обьединить бриждем, а 3,4,5-й порты оставить в LAN-свитче. 

  1. В окне Interfaces для всех портов устанавливаю для master-port значение none
  2. В окне IP - Addresses адрес LAN-сети назначаю интерфейсу ether5
  3. В окне Interfaces для 2,3,4-го портов устанавливаю для master-port значение ether5
  4. В окне Interfaces для 2-го и 5-го портов исправляю название 

 

Изменение адреса LAN-сети

По умолчанию LAN-сети присвоен адрес 192.168.88.0 

Если надо адрес LAN-сети изменить, то:

  1. В окне IP - Addresses устанавливаю нужный адрес LAN-сети, например "192.168.200.0/24"
  2. В окне IP - Pool правлю адреса
  3. В окне IP - DHCP Server в закладке Networks  правлю запись

После изменения надо подключиться к рутеру уже по новому адресу.

 

Новые учетные записи

Работа под учетной записью "admin" совсем нежелательна, т.к. ее хакеры пытаются взламывать в первую очередь. А то, что попытаются подбирать пароль к учетной записи "vecais" вероятность близка к нулю.

Поэтому в окне System - Users создаю новую учетную запись с полными правами и уникальным паролем.

Подключаюсь к рутеру под новым именем и сразу же удаляю учетную запись "admin"

Настройка даты и времени

На этом этапе желательно иметь подключение к интернету.

  1. В окне System - Clock в закладке Time устанавдиваю TimeZoneName в Europe/Riga
  2. В окне System - SNTP Client в поля NTP Server записываю строки "lv.pool.ntp.org" и "lv2.pool.ntp.org" и отмечаю чекбокс Enable

 

Файрвол

В окне IP - Firewall в закладке NAT правлю masquerade-запись:

  1. В закладке General в поле Src. Addresses вписываю адрес LAN-сети, например "192.168.200.0/24"
  2. Если есть необходимость дать доступ к конфигурированию рутера через интернет, то в окне IP - Firewall в закладке Filter Rules добавляю новую запись: Chain = input; Protocol = 6(tcp); Dst.Port = 8291; In.Interface = ether1-gateway; Action = accept

 

Создаю ip-адрес для WiFi-сети

  1. В окне IP - Addresses добавляю запись с адрес для WiFi-сети, например "192.168.100.0/24"
  2. В окне IP - Pool добавляю запись с новым диапазоном адресов для DHCP Server-а WiFi-сети
  3. В окне IP - DHCP Server в закладке Networks  добавляю запись для DHCP Server-а WiFi-сети
  4. В окне IP - DHCP Server в закладке DHCP  добавляю запись для DHCP Server-а WiFi-сети

 

Настройка WiFi интерфейса

Начинаю с создания в окне Wireless в закладке Security Prifiles нового профиля:

3854108_wlansecprofile (369x475, 18Kb)

В окне Wireless в закладке Interfaces правлю имеющуюся запись. Все исправления делаю в закладке Wireless. Некоторые опции можно увидеть лишь нажав кнопку "Advanced Mode".

3854108_wlaninterface (425x700, 119Kb)

 

Добавляю записи в файрвол для WiFi-сети

В окне IP - Firewall в закладке NAT добавляю masquerade-запись:

  1. В закладке General в поле Src. Addresses вписываю адрес WiFi-сети, например "192.168.100.0/24"
  2. Изолирую Lan и WiFi сети друг от друга: в окне IP - Firewall в закладке Filter Rules добавляю новые записи:
  • Chain = forward;  In.Interface = ether5-master-local;Out.Interface = wlan1; Action = drop
  • Chain = forward;  In.Interface = wlan1;Out.Interface = ether5-master-local; Action = drop

В окне Interfaces разблокирую интерфейс wlan1.

 

Строю IPSec c главным офисом

В окне IP - IPsec в закладке Proposals создаем новый proposal:

3854108_proposal (302x403, 11Kb)

В окне IP - IPsec в закладке Peers создаем новый peer:

3854108_peer (351x700, 86Kb)

В окне IP - IPsec в закладке Policies создаем новую политику:

3854108_policyg (354x305, 9Kb)

3854108_policya (354x304, 9Kb)

Чтобы пакеты вместо туннеля не уходили через NAT  в окне IP -Firewall в закладке NAT правлю masquerade-запись: в поле Dst. Addresses вписываю адрес  vpn-сети,  например "! 192.77.0.0/24"

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

Рубрики:  Технические обзоры
mikrotik

Метки:  

FireBird. Первый успех.

Вторник, 12 Августа 2014 г. 00:58 + в цитатник

Уже есть навыки работы с разными б/д, но c firebird-ом не получалось.

И, вот первый заработавший вариант!

И, кроме того, поправил сервер:

  • в папку apache/bin скопировал файл fbclient.dll из инсталляции FireBird;
  • поправил файл php.ini

 

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<style>
html, body {
    margin:0px;
    padding:0px;
    font-family:  Arial, Helvetica, sans-serif;
    text-align: center;
    background-color:#ffffff;
    font-size:12px;
}
table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
    text-align: center;
}
table tbody tr:nth-child(odd) td {
    background-color: #f2f2f2;
}

table th {
    background-color:blue;
    color:white;
}
</style>
</head>
<body>
<center>
<h2>Jantar, lietotāju saraksts</h2><br>
<?php
try {
    $str_conn ="firebird:dbname=192.168.1.1/3050:C:\Program Files\Jantarik\DB.GDB";
    $conn = new PDO($str_conn, "SYSDBA", "masterkey");
}   
catch (PDOException $e) {
    echo $e->getMessage();
}
try {
    $sql = "SELECT * FROM USERS ORDER BY CODE";
    echo "<table>";
    echo '<tr><th>CODE</th><th>NAME</th><th>DEPARTMENT</th><th>CARD Nr.</th></tr>';
    foreach($conn->query($sql) as $row) {
    echo '<tr><td>'.number_format($row['CODE'],0,'','').'</td><td>'.$row['NAME'].'</td><td>'.$row['DEPARTMENT'].'</td><td>'.number_format($row['CARD'],0,'','').'</td></tr>';
    }
    echo "</table>";
} catch(PDOException $ex) {
   //handle me.
}

?>
</body>
</html>

Рубрики:  Технические обзоры
Программирование

OpenVPN сервер на Mikrotik-е. Конспект.

Четверг, 07 Августа 2014 г. 09:44 + в цитатник

1. Сначала генерируем сертификаты. Мне удобно генерировать в модуле OpenVPN Administration Webmin-а:
- в Certification Authority List создаю новую Certification Authority и там же генерирую серверный и клиентский сертификат;
- экспортирую сертификаты на рабочий комп.
2. Далее работаю с Mikrotik-ом:
- update !
- импортирую сертификаты ca и собственно сервера. импортирую ключ сервера через путь System - Certificates, кнопка Import.
- IP - Pool: создаю пул адресов для туннельных клиентов. Например: 10.123.123.2-10.123.123.100
- PPP - закладка Profiles: создаю open-vpn профиль. В закладке General присваиваю имя, адрес и указываю созданный выше пул адресов. Например: Name=ovpn-profile, Local address=10.123.123.254, Remote address=vpn-pool. В закладке Protokols отмечаю Use encription=required
- PPP - закладка Interface - кнопка OVPN Server:

3854108_ovpnserver (330x390, 9Kb)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

- PPP - закладка Secrets: добавляю имя клиента и, при необходимости, пароль.

3. Конфигурирую клиента.

 

Мой файл mikrotik.ovpn:

client

dev tap
proto tcp
remote WAN-address 1191

resolv-retry infinite
nobind

ns-cert-type server

persist-key
persist-tun

ca ca.crt
cert zanis.crt
key zanis.key
dh dh1024.pem

tls-client
port 1191

cipher AES-256-CBC
auth SHA1
auth-user-pass
pull

verb 3

route-up "route add LAN-address mask 255.255.255.0 10.123.123.254"

 

Рубрики:  Технические обзоры

Метки:  

Любите ли вы костыли так, как люблю их я?

Понедельник, 14 Июля 2014 г. 05:51 + в цитатник

На айпаде жены закончилось свободное место.
Айпад стал глючить, и ничего не позволил слить на хост.
Подключил проводом и синхронизация тут же навсегда убила последние и очень нужные видеозаписи.
(В этот момент я уже догадался, что танцор из меня никакой)
Как бы там ни было, а проблему надо решать: необходим переносной, внешний сторидж с очень понятным управлением.

Apple предлагает AirPort Time Capsule. Вариант непереносной и недешевый.

Тогда подумалось о внешнем WiFi кард-ридере типа Intenso Memory 2 Move Max:



У Verbatim есть его полный аналог (см. здесь)

Если в такой девайс поставить SD-карту побольше, то получится:

  • внешний диск с WiFi-подключением;
  • внешний USB 2.0 порт для флэшек и внешних дисков;
  • небольшая подзарядка.

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


Дополнено позже:

Данный девайс оказался удачным решением:

  • супруга освоила его без затруднений;
  • работает без нареканий.
Рубрики:  Технические обзоры

Метки:  

Паттерн MVC в языке PHP

Четверг, 03 Июля 2014 г. 08:38 + в цитатник

Вот и "дорос" до понимания паттернов (шаблонов). Интуитивно уже давно к этому шел и наконец прозрел. Идея хорошо изложена в этом видео:



Теперь разберусь в рабочем примере, взятом с YOUTUBE:



Файл login.php:
<html>
<head>
<style>
    #login-controls {
        margin: 0 auto;
        border: 1px solid #ccc;
        padding: 50px;
        width: 300px;
    }
    .error-text{
        color: #f00;
    }
</style>
</head>
<body>
<div id="login-controls">
    <h2>Login</h2>
    <form method="POST" action="index.php">
        <p>Username:<br />
        <input type="text" name="user" />
        </p>
        <p>Password:<br />
        <input type="password" name="pass" />        
        </p>
        <input type="submit" name="op" value="login" />
    </form>
</div>
</body>
</html>

Здесь все просто: обычный HTML-код для отображения формы. Заполненные поля передаются файлу index.php:

<?php

require_once('user_controller.inc.php');
require_once('user_model.inc.php');

@$op = $_REQUEST['op'];

$user_controller = new UserController();

switch($op){
    case 'login':
        $username = $_POST['user'];
        $password = $_POST['pass'];
    
        if ($user_controller -> login($username,$password)){
            header("Location:main.php");
        }else header("Location:login.php?err=1");
    break;
    
    case 'logout':
        $user_controller -> logout();
        header("Location:login.php");
    break;
    
    default:
        header("Location:login.php");
    break;
}
?>

В файле index.php:

  • подключаются файлы user_controller.inc.php и user_model.inc.php;
  • создается обьект UserController;
  • проверяется значение полученной от файла login.php переменной "op".

Предусмотрены три варианта. Если переменная "op" имеет значение:

  1. "login" - контроллер проверяет доступ и, в случае успеха, открывется страница main.php. если авторизация не прошла, то возврат на страницу login.php с кодом ошибки err=1;
  2. "logout" - контроллеру сообщается об отключении и возврат на страницу login.php без кода ошибки;
  3. любое другое, либо не определено - возврат на страницу login.php без кода ошибки.

Разбираюсь с контроллером (обьект UserController) и смотрю файл user_controller.inc.php:

<?php
class UserController {  
    function UserController() //constructor
    {

    }

    function create($username,$password,$email){   
    }
    function login($username,$password){
        if ($this->authenticate($username,$password)){
            session_start();
            $user = new UserModel($username);
            $_SESSION['user']=$user;
            return true;
        }else{
            return false;
        }
    }
    static function authenticate($u,$p){
        $authentic=false;
        if($u=='admin' && $p =='admin') $authentic=true;
        return $authentic;
    }
    function logout(){
        session_start();
        session_destroy();
    }
}
?>

Класс содержит 4 метода:

  • с таким же названием, как класс. Это конструктор, он нужен для инициализации новых обьектов. Собственно код отсутствует;
  • login() - метод обращается к методу authenticate и в случае успешной авторизации начинает новую сессию и создается экземпляр класса UserModel для доступа к данным. Таким образом, доступ к данным возможен лишь после успешной авторизации;
  • authenticate;
  • logout.

Вернусь к рассмотрению файла index.php. Если метод login() контроллера $user_controller вернет значение "true", то загрузится страница main.php.

Файл main.php:

<?php
 require_once('user_model.inc.php');
 session_start();
 if(!isset($_SESSION['user'])){
    header("Location:login.php");
 }else{
    $user = $_SESSION['user'];
 }
?>
<html>
<head>
</head>
<body>
    <p>
    You are now logged in <?php print $user->get_username()?>
    ...this is the main.
    <a href="index.php?op=logout">Logout</a>
    </p>
</body>
</html>

Чисто для демонстрации работы с данными через класс UserModel в файле main.php выводится имя пользоателя через метод get_username().

И, наконец, некоторый демо-вариант файла user_model.inc.php:

<?php

class UserModel{
    private $username;
    
    function UserModel($username){
        $this->username = $username;
    }
 
    function get_username(){
        return $this->username;
    }
 
    function set_username($username){
        $this->username = $username;
    } 
}
?>

Для модели MVC (model-view-controller) назначение файлов такое:

  • Model: user_model.inc.php
  • View: login.php, main.php
  • Controller: index.php, user_controller.inc.php

В этом примере 2 точки входа:  файлы index.php и login.php

Разбор примера закончен.

 

Использованные источники:

  1. Ляпин,Никитин, "PHP - это просто", БХВ-Петербург, 2012
Рубрики:  Технические обзоры
Программирование

Метки:  

Двухсторонняя печать документации на принтере без дуплекса

Вторник, 20 Мая 2014 г. 08:04 + в цитатник

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

  • принтер Samsung SCX-4623FN
  • компьютер Apple

Сначала печатаю все (Pages: All) четные страницы (Pages to Print: Odd only) в обратном порядке (Page Order: Reverse)

3854108_Screen_Shot_20140520_at_07_24_03 (700x462, 155Kb)

Затем, сохраняя ориентацию пачки напечатанных страниц, переворачиваю пачку через длинную сторону и возвращаю в лоток подачи бумаги

и печатаю все (Pages: All) нечетные страницы (Pages to Print: Even only) в прямом порядке (Page Order: Normal):

3854108_Screen_Shot_20140520_at_07_07_13 (700x460, 156Kb)

Получаю распечатку с правильным расположением листов и готовую к переплёту.

 

Алгоритм проверен и работает на компьютерах с ОС Windows  с принтером HP LaserJet 2015.

Рубрики:  Технические обзоры
Вообще

Метки:  

Поиск сообщений в a1addin
Страницы: 12 11 [10] 9 8 ..
.. 1 Календарь