Category Archive PHP

laravel: install in subdirectory / subfolder / shre

laravel ออกแบบมาไม่เหมาะกับ server ที่เป็น share host หรือจำเป็นต้องวางไว้ใน subdirectory / subfolder ร่วมกับโปรเจคอื่นๆ เท่าไหร่เพราะว่าตัวที่ทำงานจะอยู่ที่ /public/index.php แต่ไฟล์ config จะอยู่ที่ /.env นี่ไม่รวมที่เก็บไฟล์ ที่อยู่ใน /storage แต่มันก็เหมือน php framework อื่น ๆ ทุกเจ้านั่นละ

สาเหตุที่มันไม่เหมาะเพราะว่า ใส่ไปใน document root ทั้ง project ( / ) แบบนี้เวลาเรียกใช้จะเป็นแบบ http://localhost/blog/public ก็ดูไม่มีปัญหาอะไร แต่ถ้าคนที่เป็น hacker มาเห็น มาดูว่าเว็บนี้เขียนมากับ laravel นี่หวามหมูเลยเพราะถ้าเรียก http://localhost/blog/public/.env นี่จะสามารถโหลด config file ออกไปได้เลย ซึ่งเป็นอะไรที่พลาดมาก

ถ้าแก้ไม่ได้ ก็ทำได้โดยการแก้ apache ให้เห็น folder นี้เป็น Alias Directive หรือที่ iis ใช้คำว่า Virtual Directory ( เป็นวิธีที่ตั้งให้เรียก folder ใน url ได้เหมือนกับว่ามี folder นั้นตาม path นั้น ๆ แต่จริงๆ แล้ว folder นั้นไม่มีอยู่จริงๆ อาจจะชื่ออื่น หรือ link ไป folder อื่น )

  1. ถ้าใช้ xampp (เรารู้ว่าคนเขียน PHP ชอบ) config ของ apache จะอยู่ที่ C:\apache\conf\extra\httpd-vhosts.conf ถ้าใช้ตัวอื่นก็หาไฟล์ .conf ใน apache\conf ดูครับ
  2. เพิ่มบรรทัด Alias “/blog” “C:\xampp\htdocs\blog\public”
    1. “/blog” คือ folder ปลอม ๆ ที่จะให้เห็นใน url
    2. “C:\xampp\htdocs\blog\public” คือ path ของ folder ที่เก็บไฟล์จริงๆ
    3. restart apache

ถ้ายังใช้ไม่ได้อาจจะเพราะว่า config จากส่วนมีผลทำให้ใช้ไม่ได้อาจจะเพิ่ม

<Directory C:\xampp\htdocs\blog\public>
    AllowOverride All
    Require all granted
</Directory>

จากนั้น restart อีกครั้ง ในส่วนนี้จะยังไม่สามารถส่ง query string ได้จะต้องแก้ /public/.htaccess โดยเพิ่ม RewriteBase /laravel-site เช่น RewriteBase /blog จากตัวอย่าง

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

แก้เป็น

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    RewriteBase /blog

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

ทดสอบดูโดย

  • เปิดเว็บ http://localhost/blog จะต้องเข้าเว็บได้ปกติ
  • เปิดเว็บ http://localhost/blog/robots.txt จะต้องเห็นไฟล์ robots.txt ที่อยู่ใน C:\xampp\htdocs\blog\public
  • เปิดเว็บ http://localhost/blog/.env ต้องไม่เห็น เนื้อหาของไฟล์เด็ดขาดจะเป็น error 404 หรืออะไรก็ว่าไป

ข้อมูลเพิ่มเติม

  1. Alias Directive

Laravel: mix

มันคือ webpack ที่อธิบายง่าย ๆ คือ การ pack รวมเอา css, js มาไว้เป็นไฟล์เดียว หรือแค่ไฟล์ 4 ไฟล์ แทนที่จะโหลด css โหลด javascript หลาย ๆ ไฟล์ทำให้เว็บเราโหลดเร็วขึ้นเยอะเลย

เพราะว่าต้องใช้ npm ในการทำงานแนะนำว่าให้ทำตาม npm: ‘cross-env’ Is Not Recognized as an Internal or External Command ก่อนเพื่อป้องกันปัญหาที่จะเกินขึ้น

เริ่มจากการเพิ่ม package ที่จะใช้ใน command line ก่อนเช่น

  • npm i @fortawesome/fontawesome-free
  • npm i datatables
  • npm i icheck-bootstrap
  • npm i jquery
  • npm i jquery-ui
  • npm i moment
  • npm i numeral
  • npm i overlayscrollbars
  • npm i sweetalert2

เพิ่มโค้ทในไฟล์ /resources/js/bootstrap.js และเพิ่มโค้ทในไฟล์ /resources/sass/app.scss ตามคู่มือ 6.9 Laravel Mix

run command
npm run production
จะมีไฟล์เพิ่มมาใน /public/css/app.css และ /public/js/app.js

แก้ config AdminLte ให้ใช้ mix โดยเปิดไฟล์ /config/adminlte.php เปลี่ยน ‘enabled_laravel_mix’ => false, เป็น ‘enabled_laravel_mix’ => true,

จากนั้นลองใช้งานเว็บและ view source ดูจะเห็นว่าส่วนที่โหลด css และ javascript จะหายไปเยอะเลย

Laravel: AdminLTE

AdminLTE เป็น Control Panel หรือหรือที่ฝรั่งเรียกว่า dashboard ทีี่นิยมใช้กันมานานเพราะสวย ฟรี แม้แต่ตอนนี้ที่ laravel จะแนะนำให้ใช้ dashboard ทางการคือ Laravel Horizon แต่มันจะต้องการ extension pcntl ในการทำงานซึ่งใน windows จะติดตั้งไม่ได้ง่าย ๆ ทางที่ดีคือ ทางที่ง่ายที่สุด ใช้เจ้าเพื่อนเก่าของเรานี่ละ

มีคนทำ package ให้สามารถใช้ AdminLTE ง่าย ๆ ใน laravel โดยไม่ต้องเขียน code ให้ยุ่งยากคือ jeroennoten/Laravel-AdminLTE การติดตั้งก็ทำได้ง่ายแค่

  1. composer require jeroennoten/laravel-adminlte
  2. php artisan adminlte:install
  3. จากนั้นก็เปิดไฟล์ /resources/views/welcome.blade.php ขึ้นมาแล้วเอาตัวอย่างในเว็บ Usage วางแทนที่ของเดิมแค่นี้ก็ได้ตัวสวย ๆ มาใช้แล้วเปิดเว็บ laravel ดูก็ต่างจากหน้าขาวๆ แต่เดิมคนละเรื่องเลย

ที่นี้เริ่มจะเห็นว่า themes ที่ได้มาจะต่างจากตัวอย่าง LIVE PREVIEW อยู่หลาย ๆ จุด เราก็สามารถเปลี่ยนให้เป็นแบบที่ต้องการเริ่มด้วยคำสั่ง php artisan adminlte:install –only=main_views จะเป็นการ copy Blade Templates ของธีมนี้ไปไว้ที่ resources/views/vendor/adminlte ให้เราจัดการแก้ได้ตามความต้องการ

npm: ‘cross-env’ Is Not Recognized as an Internal or External Command

ใช้ npm แล้วมี error ‘cross-env’ Is Not Recognized as an Internal or External Command ทุกครั้ง ทั้งๆ ที่ทำตามคู่มือทุกอย่าง

วิธีแก้

  1. ลบโพลเดอร์ node_modules
  2. ลบไฟล์ package-lock.json
  3. เปิด command prompt โดยใช้ Run as administrator
  4. ใช้คำสั่ง npm install
  5. ทดสอบโดยใช้คำสั่ง npm run dev

หลังจากนี้ สามารถใช้ npm ได้ตามปกติแล้ว

php: download ไฟล์จาก server

ตัวอย่าง code php ไว้ download ไฟล์จาก server

PHP/download.php
<?php
$fileDir = '../assets/';
$token = 'HH89VOiirgXlCdEqDrFs';

if ($_REQUEST['token'] != $token) {
    exit('bad token');
}

$file = $fileDir . $_REQUEST['file'];
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: ' . mime_content_type($file));
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));

    //readfile($file);
    echo file_get_contents($file);
} else {
    exit('file not found');
}

เพราะว่า ออกแบบให้สามารถโหลดไฟล์อะไรก็ได้จาก server เลยมีการใช้ token ช่วยในการตรวจสอบความปลอดภัยเล็กน้อย ของจริงต้องแก้ให้ตรวจ token ซับซ้อนกว่านี้เพื่อความปลอดภัย

IIS: การตั้ง Virtual Directory

iis เดิมมีเว็บที่เป็น c# อยู่แล้วและไม่สะดวกที่จะเพิ่ม domain name เข้าไปใหม่ จะตั้งเป็น site ให้ใช้อีก port ก็ติด firewall ที่ยอมให้ใช้ port 80 เท่านั้น และเพื่อความปลอดภัย framework อย่าง laravel ไม่ควรวาง folder ให้สามารถเรียกใช้ php ไฟล์อื่นได้นอกจาก /public/index.php จึงเลือกที่ใช้วิธี Virtual Directory คือ การสร้าง folder ใน url ให้ชี้ไปอีก folder ที่อยู่นอก C:\inetpub\wwwroot

การตั้ง Virtual Directory

  1. เปิดโปรแกรม Internet Information Services (IIS) Manager
  2. คลิกขวาที่ site ที่ต้องการ เช่น Default Web Site
  3. Add Virtual Directory
    Alias
    คือ folder จำลอง เช่น punpun_uat
    Physical path:
    คือ path จริง ที่ทำ shortcut ชี้ไปหา เช่น C:\www\punpun_v1_uat
  4. (ไม่จำเป็น) คลิกที่ site หรือ server แล้ว restart
  5. ทดสอบโดยเรียก url เช่น http://localhost/punpun_uat

วิธีนี้จะมีข้อดีคือ

  1. สามารถติดตั้งหลายเว็บ โดยใช้ domain และ port เดียวกันได้
  2. สามารถควบคุมการเข้าถึงไฟล์ที่ไม่ต้องการได้เช่น ถ้าวาง file ของ larave ไว้ใน C:\inetpub\wwwroot ตามปกติ ผู้ไม่หวังดีสามารถเรียกใช้ไฟล์อื่นๆ นอกจากไฟล์ /public/index.php ได้โดยตรงเช่น ไฟล์ php ที่สามารถ upload ไฟล์ได้โดยไม่มีการตรวจสอบสิทธิทำให้ไม่ปลอดภัย
  3. สามารถรัน code เดียวกันโดยใช้ php หลาย version หรือมี config คนละแบบได้โดยใช้วิธี การติดตั้ง PHP หลายเวอร์ชั่น บน IIS
  4. ซ่อน หรือย้าย folder ที่เก็บงานไปไว้ไดร์อื่น

การติดตั้ง PHP หลายเวอร์ชั่น บน IIS

การติดตั้ง PHP หลายๆ เวอร์ชั่นบน IIS หรือการติดตั้ง UAT และ production server อยู่ในเครื่องเดียวกัน สามารถทำได้โดยใช้ Handler Mappings

การตั้งค่า Handler Mappings

  1. เปิดโปรแกรม Internet Information Services (IIS) Manager
  2. คลิกที่ site ที่ต้องการ, folder ที่จะให้สามารถ run PHP ได้ หรือที่ชื่อ server ถ้าต้องการให้ ทุก site สามารถ run PHP ได้
  3. คลิก Handler Mappings
    Request path:
    *.php
    Module:
    FastCgiModule ถ้าไม่มีให้เลือก GGI เพิ่มในตัวเลือกการติดตั้ง IIS หรืออ่าน note ในหน้า Using FastCGI to Host PHP Applications on IIS 7
    Executable:
    ใส่ path ชี้ไปที่ php-cgi.exe เช่น C:\Program Files\PHP\v7.2\php-cgi.exe อย่าลืมเปลี่ยนช่องด้านหลังจาก *.dll เป็น *.exe ด้วย
    Name:
    เช่น PHP_via_FastCGI 7.2
  4. คลิก OK
  5. ตอบ Yes
  6. (ไม่จำเป็น) คลิกที่ site หรือ server แล้ว restart
  7. Test

rewrite url ใน iis

โดยปกติ PHP จะใช้ Apache HTTP Server เป็น server ถ้าต้องการให้ URL เรียบร้อยสวยงามก็ใช้ไฟล์ .htaccess แต่ถ้าเราใช้ Internet Information Services (IIS) ก็ต้องไปใช้ไฟล์ ที่คู่กันคือ Web.Config แทน

การที่จะ rewrite url ใน iis จะต้องมีการติดตั้ง URL Rewrite extension เอาไว้ก่อน

ตัวอย่างไฟล์ Web.Config ที่ทำหน้าที่ แปลง ค่าใน url ไปให้ไฟล์ index.php โดยที่จะซ่อนไฟล์ index.php ออกจาก url[code language=”text” title=”Web.Config”]<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="remove index.php" patternSyntax="Wildcard">
<match url="*" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="index.php" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>[/code]นำไปว่างใน folder ที่ต้องการใช้เช่น folder public ของ laravel เป็นต้น