Sätt upp session i Pico

By , . Latest revision .

För att Pico ska kunna veta om den ska ladda in ert vanliga tema eller det mörka temat så behöver vi sätta upp en session. Vi tar vara på våra kunskaper ifrån webtec och sätter upp det i Pico. Artikeln är uppdelad i ett par olika delar där varje del är filer ni behöver uppdatera.

#Config

Vi börjar med att sätta upp konfigureringsfilen för sessionen. I config/-mappen så kan det vara så att ni har en config.php, beroende på när ni började jobba med kursen. Vi vill i vilket fall att den ska finnas där och se ut såhär:

<?php
if (session_status() == PHP_SESSION_NONE) {
    $name = preg_replace("/[^a-z\d]/i", "", __DIR__);
    session_name($name);
    session_start();
}

Vi startar sessionen om den inte är igång med samma unika sessionsnamn som i webtec. Den bygger på sökvägen till filen, så på studentservern behövs detta för att ni ska få en unik session.

#Index

Nästa fil vi ska in i är index.php, den som driver hela ramverket. Vi ska lägga till lite egen kod där, men vi kan börja med hur den ser ut innan så ni är med på vilken fil jag menar.

/* index.php */
<?php
if (is_file(__DIR__ . '/vendor/autoload.php')) {
    require_once(__DIR__ . '/vendor/autoload.php');
} else {
    die("Cannot find 'vendor/autoload.php'. Run `composer install`.");
}

require_once(__DIR__ . "/config/config.php");

// instance Pico
$pico = new Pico(
    __DIR__,    // root dir
    'config/',  // config dir
    'plugins/', // plugins dir
    'themes/'   // themes dir
);

// override configuration?
//$pico->setConfig(array());

// run application
echo $pico->run();

Här ska vi börja med att uppdatera “Override configuration”. Anledningen till detta är för att vi behöver nå sessionen i våra .twig-filer och på detta sätt så kan vi skapa en variabel, likt {{ theme_url }}, som vi kan jobba med. Vi lägger till att sessionen ska laddas in under variabeln session.

// override configuration?
$pico->setConfig(array(
    'session' => $_SESSION
));

Sådär, nu är vår session igång och rullar och vi kan nå den vart som i våra .twig-filer genom att hämta den såhär: {{ config.session }}.

#Formulär

Men vi har inget sätt att uppdatera vår session och det känns onödigt att bygga formulär för det. Jag löser det istället med hjälp av två länkar som använder sig utav GET, en för att uppdatera temat och en för att nollställa sessionen. Den sista är en bra sak att ha.

I och med att vi laddar in vår config/config.php så väljer jag att lägga logiken för sessionen där. Vi börjar med att lägga till en if-sats som kollar ifall $_GET["action"] är satt:

if (isset($_GET["action"])) {

}

Där i väljer jag att bygga vidare med de två länkar jag ska hantera, ?action=theme som uppdaterar temat och ?action=session_destroy som nollställer sessionen. Vi börjar med ?action=theme:

if (isset($_GET["action"])) {
    if ($_GET["action"] == "theme") {
        $previousValue = isset($_SESSION["theme"]) ? $_SESSION["theme"] : null;

        if ($previousValue == "dark") {
            unset($_SESSION["theme"]);
        } else {
            $_SESSION["theme"] = "dark";
        }

        $url = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"];
        $url = preg_replace("/index.php\//", "", $url);
        header("Location: $url");
    }
}

Andra raden kollar ifall $_SESSION["theme"] är satt och använder den ifall den är det, annars sätts den till null. Vi använder $previousValue för att veta om vi ska byta tillbaka till ljus tema eller om vi ska sätta den till mörkt. I slutet bygger vi en URL som gör att länken skickar tillbaka dig till samma sida som du var på.

Sen vill vi även kunna nollställa sessionen helt (?action=session_destroy), det gör vi med nedanstående kod:

if ($_GET["action"] == "session_destroy") {
    session_destroy();
    $url = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"];
    $url = preg_replace("/index.php\//", "", $url);
    header("Location: $url");
}

Hela config.php ser alltså ut så här nu:

<?php
if (session_status() == PHP_SESSION_NONE) {
    $name = preg_replace("/[^a-z\d]/i", "", __DIR__);
    session_name($name);
    session_start();
}

if (isset($_GET["action"])) {
    if ($_GET["action"] == "theme") {
        $previousValue = isset($_SESSION["theme"]) ? $_SESSION["theme"] : null;

        if ($previousValue == "dark") {
            unset($_SESSION["theme"]);
        } else {
            $_SESSION["theme"] = "dark";
        }

        $url = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"];
        $url = preg_replace("/index.php\//", "", $url);
        header("Location: $url");
    }

    if ($_GET["action"] == "session_destroy") {
        session_destroy();
        $url = $_SERVER["REQUEST_SCHEME"] . "://" . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"];
        $url = preg_replace("/index.php\//", "", $url);
        header("Location: $url");
    }
}

Nu kan vi, oavsett vilken sida vi står på, uppdatera temat genom att lägga till ?action=theme på vår URL eller nollställa sessionen genom att lägga till ?action=session_destroy. En bra start, men rimligen vill vi göra det mer användarvänligt så i nästa del löser vi det genom att göra två knappar.

#Twig & Meta

Jag väljer att lägga mina länkar i min footer med hjälp av content/_meta.md, men ni kan själva välja att lägga länkarna varsom med hjälp av följande:

<!-- Länkarna om ni inte vill ha dem i er footer --->
<a href="?action=session_destroy">Destroy Session</a>
<a href="?action=theme">Swap theme</a>

Jag lägger till mina i min _meta.md, så den ser ut såhär:

---
Logo: image/me.jpeg
Tagline: University Lecturer
icon: fas fa-snowflake
Social:
    - title: Link till sidans github repo.
      url: https://github.com/AuroraBTH/design-example
      icon: fab fa-github
    - title: Dark Mode
      url: ?action=theme
      icon: fas fa-moon
    - title: Destroy Session
      url: ?action=session_destroy
      icon: fas fa-trash-alt
---

Sådär, nu har jag tillgång till mina länkar, men jag behöver uppdatera så min sida håller koll på vilken stylesheet den ska ladda in. I min header.twig-fil har jag följande länk som laddar in temat:

<link rel="stylesheet" href="{{ theme_url }}/css/style.min.css" type="text/css" />

Jag behöver bygga om denna så den laddar in style.min.css (eller style.css) om jag har det ljusa temat och style-dark.min.css (eller style-dark.css) om det mörka temat är aktiverat. Jag skriver till en snygg if-sats som kollar det mot sessionen, som jag kan nå med config.session:

{% if config.session.theme == "dark" %}
    <link rel="stylesheet" href="{{ theme_url }}/css/style-dark.min.css" type="text/css" />
{% else %}
    <link rel="stylesheet" href="{{ theme_url }}/css/style.min.css" type="text/css" />
{% endif %}

Trycker ni nu på länken för att byta tema så borde ni ha en sida utan tema alls. Tryck igen för att få tillbaka ert vanliga tema.

#SCSS

Nu behöver jag fixa mina .scss filer så att allt det här fungerar. Jag börjar med att skapa en ny fil i mitt tema, kmom02/scss/style-dark.scss som ska ligga till grund för mitt tema. Min style-dark.scss får i nuläget vara en kopia på min style.scss, utöver att jag lägger in följande regel för att se att det fungerar.

/* Längst ner i min style-dark.scss */
.main {
    background-color: yellow;
}

För slippa behöva köra två kommandon uppdaterar jag mina script i package.json. Såhär ser nu hela min script ut:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "stylelint \"**/*.scss\"",
    "watch": "sass kmom02/scss/style.scss:kmom02/css/style.css kmom02/scss/style-dark.scss:kmom02/css/style-dark.css --no-source-map --watch",
    "watch-min": "sass kmom02/scss/style.scss:kmom02/css/style.min.css kmom02/scss/style-dark.scss:kmom02/css/style-dark.min.css --no-source-map --watch --style compressed",
    "style": "npm run style-light && npm run style-dark",
    "style-min": "npm run style-light-min && npm run style-dark-min",
    "style-dark": "sass kmom02/scss/style-dark.scss kmom02/css/style-dark.css --no-source-map",
    "style-dark-min": "sass kmom02/scss/style-dark.scss kmom02/css/style-dark.min.css --no-source-map --style compressed",
    "style-light": "sass kmom02/scss/style.scss kmom02/css/style.css --no-source-map",
    "style-light-min": "sass kmom02/scss/style.scss kmom02/css/style.min.css --no-source-map --style compressed"
},

Jag kan då köra npm run style för att bygga både mitt ljusa och mörka tema och jag har även uppdaterat min watch så den kollar båda filerna efter ändringar. Och vi kan köra npm run style-min för att bygga de komprimerade .min.css filerna. Se till att köra rätt script för att bygga det Stylesheet du har laddat i din header.twig.

#@use och @forward

@import börjar närma sig pensionsåldern och har blivit deprecated, tittar vi i detta stycke på hur vi kan ersätta @import från ovan.

Vi skapar först en variables-katalog i vår scss katalog i temat vi vill jobba med, i detta exempel använder jag kmom02 som tema namn. Jag skapar alltså katalogen me/portfolio/themes/scss/variables. I variables-katalogen skapar jag två filer _index.scss och _variables.scss. Jag har i detta exempel filträdet:

├── blockquotes.scss
├── code.scss
├── container.scss
├── footer.scss
├── gallery.scss
├── header.scss
├── style-dark.scss
├── style.scss
├── tables.scss
├── technology.scss
├── typography.scss
└── variables
    ├── _index.scss
    └── _variables.scss

I filen variables.scss definierar jag mina variabler och använder nyckelordet !default för att i ett senare skede kunna skriva över dessa variabler.

// themes/kmom02/variables/_variables.scss
$main-background-color: #fff !default;
$main-font-color: #333 !default;

I filen använder vi nyckelordet @forward för att “vidarebefordra” våra variabler och göra de tillgängliga i andra filer.

// themes/kmom02/variables/_index.scss
@forward 'variables';

Nu kan vi i style.scss-filen använda våra variabler genom att ladda in de globalt med hjälp av as *.

// themes/kmom02/style.scss
@use 'variables' as *;

@use 'typography';
@use 'container';

@use 'header';
@use 'footer';

@use 'blockquotes';
@use 'code';

@use 'technology';
@use 'tables';

@use 'gallery';

Sedan kan vi i till exempel typography.scss använda variablarna genom att även ladda de där.

// themes/kmom02/typography.scss
@use 'variables' as *;

body {
    line-height: 1.4;
    font-family: "Montserrat", sans-serif;
    color: $main-font-color;
}

p {
    font-size: 1.4em;
    margin-bottom: 1.96rem;
}

För att sedan skapa det mörka temat har vi filen style-dark.scss. Här börjar vi med att använda konstruktionen with för att skriva över våra variabler för det mörka temat.

// themes/kmom02/style-dark.scss
@use 'variables' as * with (
    $main-background-color: #333,
    $main-font-color: #fff
);

@use 'typography';
@use 'container';

@use 'header';
@use 'footer';

@use 'blockquotes';
@use 'code';

@use 'technology';
@use 'tables';

@use 'gallery';

När vi nu kompilerar om våra stylesheet bör vi alltså få olika värden för de två variabler beroende på vilken av de resulterande filerna vi kollar i.

#Avslutningsvis

Vi har nu möjlighet att köra ett mörkt tema tillsammans med vårt vanliga tema, det känns bra. Hojta till om något är oklart!

#Revision history

  • 2024-12-05: (B, efo) Uppdaterad HT2024.
  • 2020-11-19: (A, nik) Skapad inför HT2020.

Document source.

Category: design, pico.