• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

PHP OOP Nie odczytuje zmiennej w klasie.

VPS Starter Arubacloud
0 głosów
722 wizyt
pytanie zadane 15 czerwca 2018 w PHP przez nielotweb Bywalec (2,240 p.)

Cześć,

Mam taką zagwostkę. Mam przykładową klasę, w tej klasie metodę ( funkcję ) i w tej metodzie pewną zmienną która pochodzi z innego pliku ( ta zmienna tworzy obiekt innej klasy ), i właśnie mam ten problem że nie czyta tej zmiennej, tak jakby nie istniała. I tu moje pytanie dlaczego nie można inicjować 'wrogich' zmiennych z innych plików do klas? W jaki sposób mogę zrobić aby zaczęło ją 'czytać'?

Napiszę przykład bo tłumaczyć nie umiem.

W jednym pliku mam przykładowo to:

require 'vendor/autoload.php';

$Request = new Request; // <- To jest ta zmienna

A w innym to:

class Login
{
    public function loginUser()
    {
        if ( self::findUser() === true && $this->userStuff->email === $this->emailLogin)
        {
            if ( $this->userStuff->password === $this->passwordLogin )
            {
                //Session id
                Session::putIntoSession('loginSession', $this->userStuff->id);

                //Session true
                Session::putIntoSession('loginCorrect', true);

                //Redricted to board
                $Request->sendTo('board');  // I TO NIE CHCE DZIAŁAĆ, TZN. NIE CZYTA TEGO
          
            }
        }

    }
}

Czyli nie chcę czytać mi tej zmiennej $Request, choć gdy dam ją na samą górę poza klasę Login, to ją normalnie czyta. Może mi ktoś to wytłumaczyć?;p 

Z góry dziękuję!

1 odpowiedź

+2 głosów
odpowiedź 15 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
wybrane 19 czerwca 2018 przez nielotweb
 
Najlepsza

Login nie ma prawa wiedzieć o zmiennej Request, bo nie jest ona w jego zasięgu.

Jedno z wielu rozwiązań:

Dodaj w konstruktorze, dla klasy Login, parametr Request:

class Login
{
    private $request;

    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public function loginUser()
    {
        if ( self::findUser() === true && $this->userStuff->email === $this->emailLogin)
        {
            if ( $this->userStuff->password === $this->passwordLogin )
            {
                //Session id
                Session::putIntoSession('loginSession', $this->userStuff->id);
 
                //Session true
                Session::putIntoSession('loginCorrect', true);
 
                //Redricted to board
                $this->request->sendTo('board'); 
            }
        }
    }
}

A w pliku z poniższym kodem:

require 'vendor/autoload.php';
 
$Request = new Request; // <- To jest ta zmienna

Stwórz obiekt Login wraz z parametrem $Request.

require 'vendor/autoload.php';
 
$request = new Request; // <- To jest ta zmienna

$login = new Login($request);

Co się tyczy innych rzeczy:

Mam przykładową klasę, w tej klasie metodę ( funkcję )

Właściwie to metodę. Wyjaśnienie "( funkcję )", nie powinno mieć tutaj miejsca, choćby z tego powodu, że jest mylące.

inicjować 'wrogich' zmiennych z innych plików do klas

Wrogich???

Btw. Login nie powinno mieć jakiegoś namespace'a, aby dołączanie autoload'a miało sens?

Jeśli jesteś twórcą tej klasy Request, to nie sądzisz, że nazwa metody "sendTo" jest myląca, choćby z prostej przyczyny, że sam wyjaśniłeś w komentarzu:

                //Redricted to board
                $this-request->sendTo('board');

Sugeruję zmienić jej nazwę na: redirectTo().

Poza tym polecam ten kurs, gdyż Twoje słownictwo ze świata obiektowego jest ubogie:

https://webmastah.pl/jak-programowac-obiektowo-cz-1-wstep/

Dzięki zapoznaniu się z nim, będziesz mógł z większą łatwością objaśnić swój problem, aby inni forumowicze mogli Ci lepiej pomóc.

if ( self::findUser() === true && $this->userStuff->email === $this->emailLogin)

Klasa Login nie powinna mieć statycznej metody o nazwie "findUser". Zadaniem klasy Login jest logowanie, tylko i wyłącznie. Aby nie zostawić Cię z problemem i sobie radź polecam przekazać parametry, które są potrzebne do zalogowania, podobnie, jak zrobiłem to z Requestem. Gdyby klasa Login przeistoczyła się kiedyś w metodę kontrolera o nazwie Authorization - Wyciągaj te dane z własności (property) private $request.

komentarz 16 czerwca 2018 przez nielotweb Bywalec (2,240 p.)

Przepraszam że tak późno odpisuje:p

Tak już rozumiem czemu mi to nie działa, na czym to polega.

Właściwie to metodę. Wyjaśnienie "( funkcję )", nie powinno mieć tutaj miejsca, choćby z tego powodu, że jest mylące.

Okej zapamiętam.

 Wrogich???

Słowa mi zabrakło:P 

Jeśli jesteś twórcą tej klasy Request, to nie sądzisz, że nazwa metody "sendTo" jest myląca, choćby z prostej przyczyny, że sam wyjaśniłeś w komentarzu:

Tak wiem, sam to zauważyłem, że nazewnictwo mam ubogie i muszę nad nim popracować.

Dzięki zapoznaniu się z nim, będziesz mógł z większą łatwością objaśnić swój problem, aby inni forumowicze mogli Ci lepiej pomóc.

Okej na pewno sobie to przerobię:) 

Klasa Login nie powinna mieć statycznej metody o nazwie "findUser". Zadaniem klasy Login jest logowanie, tylko i wyłącznie. Aby nie zostawić Cię z problemem i sobie radź polecam przekazać parametry, które są potrzebne do zalogowania, podobnie, jak zrobiłem to z Requestem. Gdyby klasa Login przeistoczyła się kiedyś w metodę kontrolera o nazwie Authorization - Wyciągaj te dane z własności (property) private $request.

No dobra rozumiem, czyli jak przykładowo mam tą klase Login to ona ma tylko logować. Okej, a co z tym findUser, dla tego mam zrobić nową klasę? Myślałem że będzie szybciej i sobie po prostu dam metodę która znajdzie mi user'a a potem go zaloguje. 

no ale dobra bardzo dużo mi pomogłeś, dzięki wielkie!:)

1
komentarz 16 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 17 czerwca 2018 przez HaKIM

No dobra rozumiem, czyli jak przykładowo mam tą klase Login to ona ma tylko logować. Okej, a co z tym findUser, dla tego mam zrobić nową klasę? Myślałem że będzie szybciej i sobie po prostu dam metodę która znajdzie mi user'a a potem go zaloguje. 

Dokładnie tak, przydałaby się nowa klasa. Acz, ja bym to jeszcze trochę dopieścił.

Stwórz interfejs UserQueryInterface [1], do którego będziesz się odnosił, gdy chcesz wyciągnąć użytkownika.

Przykład:

<?php

declare(strict_types=1);

namespace App\Entity\User;

interface UserQueryInterface
{
    public function findById(string $id): User; # [2]

    public function findByEmail(string $email): User; # [2]

    public function getAll(): array;
}

Teraz klasa Login będzie wyciągać User'a w następujący sposób:

$this->userQuery->findByEmail('example@email.com');

W ten sposób wydzieliłem logikę wyciągania Usera z klasy Login.

Kod klasy Login:

class Login
{
    private $request;
    private $userQuery;

    public $email;
    public $password;

    public function __construct(Request $request, UserQueryInterface $userQuery)
    {
        $this->request = $request;
        $this->userQuery = $userQuery;
    }
    

    public function login(): Response
    {
        if (!filter_var($this->email, FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException("The email is not valid.");
        }

        $user = $this->userQuery->findByEmail($this->email);

        if ($user->getPassword() === $this->password) {
            /**
             * Ustawiasz sesje
             */

            return $this->request->redirectTo('board');
        } else {
            throw new \InvalidArgumentException("The password is incorrect".);
        }
    }
}

Co się tyczy [3]:

public $email; 
public $password;

Może zrobić dla tych danych strukturę danych?

Przykład:

final class LoginData
{
    private $email;

    private $password;

    public function __construct(string $email, string $password)
    {
        $this->email = $email;
        $this->password = $password;
    }

    public function getEmail(): string
    {
        return $this->email;
    }

    public function getPassword(): string
    {
        return $this->password;
    }
}

Może zauważyłeś, że nigdzie tutaj nie sprawdzamy, czy podany email jest prawidłowy. Robi to za nas klasa Login, to tam znajduje się cała logika logowania.

Jak wyglądałby kod po wrowadzeniu tej struktury?

    public function login(LoginData $loginData): Response
    {
        /** Logika logwania nie wycieka poza klasę Login. ^^ */
        if (!filter_var($loginData->getEmail(), FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException("The email is not valid.");
        }

        $user = $this->userQuery->findByEmail($loginData->getEmail());

        if ($user->getPassword() === $loginData->getPassword()) {
            /**
             * Ustawiasz sesje
             */
            
            return $this->request->redirectTo('board');
        } else {
            throw new \InvalidArgumentException("The password is incorrect".);
        }
    }

Mam jeszcze jedno zastrzeżenie, apropos:

 if ($user->getPassword() === $loginData->getPassword()) {
    [...]
}

Czy mi się zdaje, czy Ty tych haseł nie hashujesz? :D

Polecam:

http://php.net/manual/en/ref.password.php

Po wprowadzeniu tego feature'a logowanie nie zmieni się drastycznie, po prostu zamiast powżyszego kodu zastąp go:

if (password_verify($loginData->getPassword(), $user->getPassword())) {
    [...]
}

No i nareszcie, jak to wygląda po zebraniu do kupy:

$request = new Request();

/** Zamiast UserCleanQury wrzuć tutaj już istniejący system, implementujący UserQueryInterface, wyciągania User,
* który znajduje się w klasie Login.
*/
$login = new Login($request, new UserCleanSQLQuery());

try {
    $login->login(new LoginData('foo@bar.com', 'siekurlarozpisalem'));
} catch (\Exception $exception) {
    print '<a href="https://www.youtube.com/watch?v=u9erhDRkCD0">No coś nie pykło edwidentnie.</a>';
}

Z tych ważniejszych, wydaję mi się, że to tyle.

enlightened Nie każdy fragment kodu był przetestowany, dlatego nie załamuj się, gdyby odrazu wszystko po zmianach nie działało. Może po prostu gdzieś znalazła się literówka? \._./

[1] - Notka dla programistów, którzy mają styczność z CQRS; Tutaj nie ma archietkury CQRS! wink

[2] - Oczywiście, najlepiej by było abyś zwrócił jakiś model (ViewObject) dla widoku, ale nie ma co wystawiać Pfeifer-Zeliska .600 Nitro Express na muchy.

[3] - Te własności powinny być prywatne, acz w podanym kodzie nie widziałem setterów, stąd założyłem, że są publiczne.

komentarz 17 czerwca 2018 przez nielotweb Bywalec (2,240 p.)

Łoo Panie! :D

Więc tak, tyle tego jest że w jeden dzień tego na pewno nie ogarnę, więc będę musiał na spokojnie przy tym siąść.

Napisałeś i objaśniłeś mi wiele rzeczy których jeszcze nie poznałem, ale na pewno poznam, wszystko pomalutku. Mógłbym się teraz o każdą rzecz zapytać którą mi napisałeś ale widzę że muszę podstawy obiektówki ogarnąć bo nie wiedziałem że to jest tak obszerne:p 

Ale ogólnie zamysł i zarys tego co mi napisałeś rozumiem, tylko nie których małych rzeczy nie, typu:

public function findById(string $id): User; # [2]

o co chodzi to co napisałeś po nawiasie, właściwie dwukropku? Albo to:

public function login(): Response

A resztę rzeczy rozumiem.

Czy mi się zdaje, czy Ty tych haseł nie hashujesz? :D

Nie hashowałem bo chciałem najpierw zrobić system logowania, rejestracji i dopiero w systemie rejestracji zaincludować hashowanie i na końcu dorzucić hashowanie w logowaniu :D 

Bardziej to rozkminię za niedługo bo teraz mam egzamin na e13 i nie mam wiele czasu siąść przy tym, za wakacjach sobie siądę i ogarnę wszystko;p

A to jeszcze jedno pytanko, niby małe coś ale jednak ostatnio tego zrobić nie umiałem. Mam przykładowo system logowania, próbuję się logować ale mi się nie udało, i wyskakuje alert, wiadomość że błędne dane logowania. I chciałem zrobić tak że po odświeżeniu ( nie po od nowym załadowaniu strony ) zniknął ten alert o błędach logowania. Bo gdy mi wyskoczył alert i odświeżyłem stronę to błąd dalej był ustawiony, a chciałem żeby po odświeżeniu zniknął. ( po nowy załadowaniu strony znikał. A i ten alert był wyświetlany za pomocą sesji ).

Także wielkie dzięki jeszcze raz!

 

1
komentarz 17 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 17 czerwca 2018 przez HaKIM

Ale ogólnie zamysł i zarys tego co mi napisałeś rozumiem, tylko nie których małych rzeczy nie, typu:

public function login(): Response

Jest to typowanie (ang. Type hints). Ten zapis sprawia, że metoda Login MUSI zwrócić obiekt Response.

Jeśli już używasz typowania, nie zapomnij dodać tej deklaracji zaraz po otwarciu tagu <?php do pliku:

declare(strict_types=1);

IMHO. to bez tego typowanie w PHP nie ma zbyt wiele sensu. [1]

Przykład:

<?php

declare(strict_types=1);

namespace Jakis\Namespace;

class Login
{
    # [...]
}

Ciągłe dopisywanie tej linijki może wkurzać, więc, o ile używasz jakiegoś sprytnego IDE|Edytora zmień tworzenie templatki plików .php. W PhpStorm wyglądałoby to tak:

<?php

declare(strict_types=1);
#if (${NAMESPACE})

namespace ${NAMESPACE};

#end
class ${NAME} {

}

A to jeszcze jedno pytanko, niby małe coś ale jednak ostatnio tego zrobić nie umiałem. Mam przykładowo system logowania, próbuję się logować ale mi się nie udało, i wyskakuje alert, wiadomość że błędne dane logowania. I chciałem zrobić tak że po odświeżeniu ( nie po od nowym załadowaniu strony ) zniknął ten alert o błędach logowania. Bo gdy mi wyskoczył alert i odświeżyłem stronę to błąd dalej był ustawiony, a chciałem żeby po odświeżeniu zniknął. ( po nowy załadowaniu strony znikał. A i ten alert był wyświetlany za pomocą sesji ).

Zapomniałeś usunąć sesji po wyświetleniu.

Oto prosty kodzik który wyświetla wiadomość i niszczy sesje:

<?php

session_start();

function setFlashbag(string $name, string $message): void {
    $_SESSION['flashbag'][$name] = $message;
}

function getFlashbag(string $name): ?string {
    $error = $_SESSION['flashbag'][$name] ?? null; # [2]
    cleanFlashbag();
    return $error;
}

function cleanFlashbag(): void {
    unset($_SESSION['flashbag']);
}


setFlashbag('error', 'Invalid login data!');

print getFlashbag('error');

Nie korzystaj z tego kodziku! Nudziło mi się to sobie rozpisałem w 3 min. cheeky

Na Twoim miejscu skorzystałbym, o ile już robić system sesji, z jakiegoś pewniaka.

Choćby to cacko od twórców Symfony:

https://symfony.com/doc/current/components/http_foundation/sessions.html

[1] - https://3v4l.org/FMeVg | https://3v4l.org/3YdLt

[2] - http://php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op

komentarz 19 czerwca 2018 przez nielotweb Bywalec (2,240 p.)
Ojć myślałem że Ci odpowiedziałem, a jednak nie, więc sorki że tak późno;p

Większości z tych rzeczy rozumiem, więc na spokojnie wszystko sobie przeanalizuje!

Dzięki wielkie za poświęcony czas! :D
1
komentarz 19 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
Luzio! ^^

Jak ktoś pyta o obiektówkę i PHP to aż żal nie spróbować pomóc w morzu "dwuplikowców" z mieszaniną PHP (logiki biznesowej), HTML, JS a czasami to i CSS w atrybucie style wpierniczą... \._./
komentarz 24 czerwca 2018 przez nielotweb Bywalec (2,240 p.)

To znów ja ^^ Zacząłem to powoli ogarniać, ale tyle tego jest że się pogubiłem;p

A więc.. ten interfejs 'UserQueryInterface' jest po to aby przechowywał metody, a te metody wyciągały dane odnośnie usera z bazy danych?

W sensie do wyciągania mam oddzielną klasę nazwaną QueryBuilder, i tam sobie tworzę metody które wyciągają mi dane.

namespace App\Core\Database;

class QueryBuilder
{

    protected $pdo;

    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }

    public function selectUserLogin($email)
    {
        $statement = $this->pdo->prepare("SELECT * FROM users WHERE email = :email");
        $statement->bindParam(":email", $email, PDO::PARAM_STR);
        $statement->execute();

        return $statement->fetch(PDO::FETCH_ASSOC);
    }

}

Ja to tak rozumiem że w tym interfejsie wkładam sobie metodę z klasy QueryBuilder. Potem w konstruktorze w klasie Login pobieram sobie ten interfejs, i mogę prosto sobie odwołać do QueryBuilder'a. Przykład:

use App\Core\Database\QueryBuilder;

interface UserQueryInterface
{
    public function selectUserLogin(string $email): QueryBuilder; // selectUserLogin jest w klasie QueryBuilder jak coś
}

class Login
{
   public function __construct(UserQueryInterface $userQuery)
    {
        $this->userQuery = $userQuery;
    }
    public function login()
    {
        $user = $this->userQuery->selectUserLogin('email@gmail.com');
    }

}

ofc. napisałem to tylko dla przykładu, żeby pokazać o co mi chodzi;p

I nie rozumiem tego elementu:

/** Zamiast UserCleanQury wrzuć tutaj już istniejący system, implementujący UserQueryInterface, wyciągania User,

* który znajduje się w klasie Login.

*/

$login = new Login($request, new UserCleanSQLQuery());

Nie rozumiem co mam wstawić za ten new UserCleanSQLQuery.

Jak pojmę te dwie rzeczy to myślę że resztę będę umiał zrobić, tzn. pojmę logikę tego;p 

1
komentarz 24 czerwca 2018 przez HaKIM Szeryf (87,590 p.)

enlightenedZamiast UserCleanSQLQuery posługuję się teraz nazwą SQLUserView, na dole wyjaśniam, dlaczego jednak taka nazwa.

A więc.. ten interfejs 'UserQueryInterface' jest po to aby przechowywał metody, a te metody wyciągały dane odnośnie usera z bazy danych?

Chodziło mi o:

<?php

declare(strict_types=1);

class SQLUserView implements UserQueryInterface
{
    public function findById(string $id): User
    {
        /** @TODO: Zaimplmenetuj tę metodę */
    }

    public function findByEmail(string $email): User
    {
        /** @TODO: Zaimplmenetuj tę metodę */
    }

    public function getAll(): array
    {
        /** @TODO: Zaimplmenetuj tę metodę */
    }
}

UserQueryInterface jest po to, abyś mógł z łatwością dodać inne drogi wyciągania Usera, jak poprzez system plików, jakieś API czy skorzystanie z ORM'a [1].

W jaki sposób ułatwia? Otóż, interfejs narzuca na wszystkie jego implementacje ten sam sposób (nazwa metody oraz zwracany typ) i te same możliwości wyciągania daych.

Dzięki temu nie musisz się martwić, że podczas zmiany z MySQL na system plików, zabraknie jakieś metody lub zwracany typ będzie inny, który używa i posługuje się jeden z komponentów.

W sensie do wyciągania mam oddzielną klasę nazwaną QueryBuilder, i tam sobie tworzę metody które wyciągają mi dane.

Twój QueryBuilder ma trochę mylącą nazwę. Jesto to raczej AFuckingBigDataStorage [2]

BTW. Zacznij krozystać z błogosławieństw PHP 7.

Zamiast:

    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }
 

Raczej:

    public function __construct(\PDO $pdo)
    {
        $this->pdo = $pdo;
    }
 

A już najlepiej:

    public function __construct(ConnectionInterface $connection)
    {
        $this->conncetion = $connection;
    }
 
interface UserQueryInterface
{
    public function selectUserLogin(string $email): QueryBuilder; // selectUserLogin jest w klasie QueryBuilder jak coś
}

Na polski Twoja metoda do wyciągania Usera brzmi: wybierzUżytkownikaLogin (dzięki emailowi) zwróć QueryBuilder; <- Straaaaaaaaaaaaaasznie myląca nazwa, nie sądzisz?

Zamiast tego, sugeruję:

interface UserQueryInterface {
    public function findUserByEmail(string $email): array;

    # Albo, jeżeli email jest unikalny dla każdego użytkownika 
    # i to właśnie za pośrednictwem jego chciałbyś 
    # wyciągać pojedynczego User'a:

    public function user(string $email): array; # [3]
}

Ja to tak rozumiem że w tym interfejsie wkładam sobie metodę z klasy QueryBuilder. Potem w konstruktorze w klasie Login pobieram sobie ten interfejs, i mogę prosto sobie odwołać do QueryBuilder'a. Przykład:

I tak... I nie.

Po pierwsze: Ten interfejs nie zadziała, bo Twój QueryBuilder nie implementuje UserQueryInterface. Dodatkowo, QueryBuilder nie powinien implementować tego interfejsu, bo zaraz dojdzie PostsQueryInterface i Twój QueryBuilder zacznie być Twoim największym koszmarem (patrz [2]).

Wzamian tego sugeruję stworzenie adaptera UserQueryInterface pod nazwą: SQLUserView.

Dlaczego SQLUserUser? Abyś przy wielu adapterach UserQueryInterface nie musiał patrzeć na namesapce klasy, aby wiedzieć, jaki to adapter.

Dlaczego SQLUserView? Chodzi o widok/wygląd Usera po wyciągnieciu danych. Poza tym, SQLUser jest zbyt abstrakcyjną nazwą, jak na konkretną implementacje.

Przykładowa ściezka do implemetnacji wyglądałby tak: src/Infrastructure/SQL/Query/UserView

Tudzież: src/Model/Infrastructure/SQL/Query/UserView

Nie rozumiem co mam wstawić za ten new SQLUserView.

Cóż, z tego powodu, że nie do końca zrozumiałeś mojej intencji.

Przy takim założeniu konstruktora klasy Login:

    public function __construct(Request $request, UserQueryInterface $userQuery) {}

Wsadziłbyś, w miejsce UserQueryInterface, SQLUserView. Jeżeli jednak chcesz pozostać przy monolicie QueryBuilder, to właśnie on zostałby przekazany [4].

❗️[1] - ORM nie został stworzony z myślą o wyciąganiu danych, przez co przy sporej ich ilości, Twoja infrastrktura może spowolnić.

[2] - O ile teraz tego nie widać, to gdy aplikacja się rozbuduje, dojdą specyficzne zapytania jak findActiveUsers czy findUsersWithRole(string $role) to twój QueryBuilder przyjmie formę tysięcznika (Pliku z tysiącami linii kodu).

[3] - Metoda user(), jako sama w sobie, cholernie mało nam mówi. Acz, w kontekście interfejsu UserQuery, łatwiej jest zrozumieć jej zachowanie.

[4] - Jeżeli zgodziłby się (QueryBuilder) na implementację UserQueryInterface.

komentarz 25 czerwca 2018 przez nielotweb Bywalec (2,240 p.)

Szczerze, nadal to sobie w głowie nie umiem poukładać. Załóżmy że nie ma tego QueryBuilder'a, w sensie całkiem usunę tę klasę i plik. 

Czyli w interfejsie UserQueryInterface będę miał to ( bo wystarczy jak po emailu dane wyciągne, tzn. email i hasło ) :

interface UserQueryInterface
{
    public function findByEmail(string $email): array;
}

więc nasuwa mi się jeszcze jedno pytanie, otóż mam takie coś, jak sam napisałeś:

class SQLUserView implements UserQueryInterface
{
    public function findByEmail(string $email): array
    {

    }
}

i w środku tej metody findByEmail tworzę sobie po prostu zapytanie PDO wyciągające dane o podanym emailu? Czy źle to rozumiem? 

Bo gdyby chciał użyć tej mojej klasy QueryBuilder to musiałbym włożyć ją w środek tej metody findByEmail. Żeby po prostu pobierało dane poprzez ten QueryBuilder?

Jak to nadal źle rozumiem to się poddaje:p 

1
komentarz 25 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 25 czerwca 2018 przez HaKIM

(Sorry za brak ogonkow; brak PL klawy w pracy).

Jestes na dobrym szlaku.

Ja bym to zrobil w ten sposob:

class SQLUserView implements UserQueryInterface
{
    private $queryBuilder;

    public function __construct(QueryBuilder $queryBuilder)
    {
        $this->queryBuilder = $queryBuilder;
    }

    public function findByEmail(string $email): array
    {
        $this->queryBuilder
            ->select('u.name', 'u.email')
            ->from('users')
            ->where('email = :email')
            ->setParameter('email', $email);
        
        # [...]
    }
}

metody QueryBuilder'a bralem na podstawie Doctrine Query Builder [1].

To wszystko do kupy by wygladalo mniej wiecej:

$connection = new \PDO();
$queryBuilder = new QueryBuilder($connection);
$login = new Login($request, new SQLUserView($queryBuilder))

enlightenedOfc. wszystkie te zmienne nie musza byc jedna pod druga. :p

Mozesz tez obejsc sie bez QueryBuildera, piszac wlasne zapytania SQL w findByEmail. W takim wypadku zamiast QueryBuildera wymagaj ConnectionInterface (W Twoim przypadku byloby to \PDO), i po prostu wywoluj zapytania z poziomu tej metody.

$query = $this->comnnection->prepare("SELECT u.name, u.email FROM users u WHERE email = :email");
$this->connection->bindParam(':email', $email, PDO::PARAM_STR);

$this->connection->execute();

Btw. slyszales juz o wzorcu architektonicznym MVC?

[1] - Niestety, nie znalazlem go w formie osobnego komponentu. Wzamian to znalazlem inne, jak: https://github.com/usmanhalalit/pixie lub zrobic samemu.

komentarz 25 czerwca 2018 przez nielotweb Bywalec (2,240 p.)
edycja 25 czerwca 2018 przez nielotweb

Mamy to! Mały sukces, bo działa:p

Jednak usunąłem QueryBuilder'a. Wszystko działało, dopóki nie zaimplementowałem Sesji, tzn. klasy z sesją. Błąd: 'Fatal error: Uncaught Error: Class 'SessionManagement' not found' - Czyli wskazuje że nie czyta klasy SessionManagement chociaż wszystko zaimplementowałem jak trzeba. I mam zagwostkę czemu nie wczytuje tej klasy..

Tutaj jest cały kod:

declare(strict_types=1);

use App\Core\Database\Connection;
use App\Core\{Request, SessionManagement};

interface UserQueryInterface
{
    public function findByEmail(string $email): array;
}

class SQLUserView implements UserQueryInterface
{
    private $pdo;

    public function __construct(\PDO $pdo)
    {
        $this->pdo = $pdo;
    }

    public function findByEmail(string $email): array
    {
        $statement = $this->pdo->prepare("SELECT * FROM users WHERE email = :email");
        $statement->bindParam(":email", $email, PDO::PARAM_STR);
        $statement->execute();

        return $statement->fetch(PDO::FETCH_ASSOC);
    }
}

class Login
{
    private $request;
    private $userQuery;
    private $session;

    public $email;
    public $password;

    public function __construct(Request $request, UserQueryInterface $userQuery, SessionManagement $session)
    {
        $this->request = $request;
        $this->userQuery = $userQuery;
        $this->session = $session;
    }

    public function login(LoginData $loginData): Response
    {
        if (!filter_var($loginData->getEmail(), FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException("The email is not valid.");
        }

        $user = $this->userQuery->findByEmail($loginData->getEmail());

        if ($user['password'] === $loginData->getPassword()) {

            $this->session->set('loginAccess', 'jest'); // testowa sesja

            return $this->request->redirectTo('board');

        } else {
            throw new \InvalidArgumentException("The password is incorrect");
        }
    }

}

final class LoginData
{
    private $email;

    private $password;

    public function __construct(string $email, string $password)
    {
        $this->email = $email;
        $this->password = $password;
    }

    public function getEmail(): string
    {
        return $this->email;
    }

    public function getPassword(): string
    {
        return $this->password;
    }
}

$session = new SessionManagement();
$session->start();

$request = new Request();
$connection = new Connection();

$login = new Login($request, new SQLUserView($connection->make()), $session);

try {
    $login->login(new LoginData('balwanek@wp.pl', 'balwanek11'));
} catch (\Exception $exception) {
    print '<a href="https://www.youtube.com/watch?v=u9erhDRkCD0">No coś nie pykło edwidentnie.</a>';
}

Przy okazji jak Ci się chce, będę wdzięczny jak sprawdzisz czy nie popełniłem jakiegoś tragicznego błędu:p

A co do tej Sesji to nie mam pojęcia czego jej nie wczytuje.

Btw. slyszales juz o wzorcu architektonicznym MVC?

Tak słyszałem, nawet coś próbowałem tworzyć opartym właśnie na MVC.

Btw. Ile w konstruktorze można dawać argumentów? Jest jakiś limit? bo choćby w tym 'moim' kodzie w klasie Login są trzy argumenty i już za bardzo czysto to nie wygląda.

 A i właśnie, co daje zwrócenie 'Response' przy metodzie login? Co to zmienia?

public function login(LoginData $loginData): Response

 

1
komentarz 25 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 25 czerwca 2018 przez HaKIM

Przy okazji jak Ci się chce, będę wdzięczny jak sprawdzisz czy nie popełniłem jakiegoś tragicznego błędu:p

Najważaniejsze: Nie trzymaj tego wszystkiego w jednym pliku. Ogólnie to jest taka zasada, że na jedną klasę/interfejs/klasę abstract./etc. przypada jeden plik.

Nie widzę abyś, korzystał z namespaceów.

Poproś JetBrains o lickę dla studenciaka (możesz też być uczniem 4 klasy podsatawówki), o lickę na ich IDE do nauki.

Odrazu znalazłbyś zbędne właściwości jak:

    public $email;
    public $password;

w klasie Login.

Btw. Ile w konstruktorze można dawać argumentów? Jest jakiś limit? bo choćby w tym 'moim' kodzie w klasie Login są trzy argumenty i już za bardzo czysto to nie wygląda.

Nie ma limitu. Ja stosuję standardy PSR-2, gdzie konstruktor, gdy jest zbyt długi, rozbija się nową linią.

public function __cosntruct(
    Request $request,
    UserQueryInterface $userQuery,
    SessionManagement $session
) {
    # [...]
}

 A i właśnie, co daje zwrócenie 'Response' przy metodzie login? Co to zmienia?

 Well, w Symfony Response'a się zwraca, widocznie automatycznie musiałem zapisać. :P

W takim wypadku zmień z Response na void (nic) i usuń return. yes

No i w końcu...

Jednak usunąłem QueryBuilder'a. Wszystko działało, dopóki nie zaimplementowałem Sesji, tzn. klasy z sesją. Błąd: 'Fatal error: Uncaught Error: Class 'SessionManagement' not found' - Czyli wskazuje że nie czyta klasy SessionManagement chociaż wszystko zaimplementowałem jak trzeba. I mam zagwostkę czemu nie wczytuje tej klasy..

 Spróbuj zawrzeć plik z tą klasą (require) do tego kodu. Jeśli zadziała: Problem tkwi w loaderze, a reczej jego błędnej konfiguracji.

W obu przypadkach wyślij zawartość composer.json + strukturę katalogów.

Btw. jeśli nie masz w planach PHPSpeca (Skubaniec nie przyjmuje finalnych do testów) to klasa SQLUserView powinna być finalna, jak LoginData. Tak samo Login.

Nie chcesz, aby ktoś Ci rozszerzył SQLUserView i tym samym utrudnił dalszy jej rozwój. Wzamian niech zaimplementuje interfejs. [1]

[1] - Mówię to w osobie trzeciej, acz to się też tyczy Ciebie, żeby Ci nie przyszło nieabstrakcyjnych klas rozszerzać.

komentarz 25 czerwca 2018 przez nielotweb Bywalec (2,240 p.)
edycja 25 czerwca 2018 przez nielotweb

Ale przypał.. na śmierć zapomniałem odświeżyć(?) Composera i dlatego nie czytało tej klasy.. mój błąd:p

Najważaniejsze: Nie trzymaj tego wszystkiego w jednym pliku. Ogólnie to jest taka zasada, że na jedną klasę/interfejs/klasę abstract./etc. przypada jeden plik.

Nie rozumiem, w sensie teraz trzymam to w jednym pliku, kontrolerze logowania..

Mam folder controllers i w nim login.php w którym jest to wszystko, czyli.. mam sobie zrobić folder controllers/login/ i tutaj muszę rozdzielić to na pojedyncze pliki dla tego logowania tak?

Btw. jeśli nie masz w planach PHPSpeca (Skubaniec nie przyjmuje finalnych do testów) to klasa SQLUserView powinna być finalna, jak LoginData. Tak samo Login.

Co do testów jednostkowych, i innych jakie istnieją to jest dla mnie jeszcze nie znany temat, nie bawiłem się jeszcze tym więc na razie zostawię to tak jak jest.

Poproś JetBrains o lickę dla studenciaka (możesz też być uczniem 4 klasy podsatawówki), o lickę na ich IDE do nauki.

Mam już i na nim piszę kod, ale co do tych 2 właściwości to storm nie uznał tego jako zbędne, tzn. nic o nich nie krzyczał:d

Nie widzę abyś, korzystał z namespaceów.

Korzystam, tylko tutaj zapomniałem dodać.

1
komentarz 26 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 26 czerwca 2018 przez HaKIM

Nie rozumiem, w sensie teraz trzymam to w jednym pliku, kontrolerze logowania..

Mam folder controllers i w nim login.php w którym jest to wszystko, czyli.. mam sobie zrobić folder controllers/login/ i tutaj muszę rozdzielić to na pojedyncze pliki dla tego logowania tak?

Noo... prawie.

Aby odrazu nie cisnac z grubej rury po 9 warstw stworz na rowni z folderem Controller (pod nim, w sensie nie w nim :P) folder Model.

W folderze Model stworz podfolder o nazwie Query, tam trzymaj UserQueryInterface. Stworz kolejny podfolder do Query o nazwie View, tam trzymaj SQLUserView jak i inne implementacje QueryInterface (MovieQueryInterface czy nasz UserQueryInterface). Jesli chcesz, oczywiscie mozesz trzymac implementacje w bardziej posegregowany spsob: src/Model/Query/View/User/SQLUserView lub jeszcze bardziej specyficznie: src/Model/Query/SQL/View/User/SQLUserView choc, to oczywiscie przesada jak na Twoj przypadek. Sugeruje pierwsze rozwiazanie: src/Model/Query/View/SQLUserView.

QueryBuilder'a mozesz wsadzic do podfoldera DB, w Modelu: src/Model/DB/QueryBuilder. Gdyby jednak QueryBuilder sie rozbudowal i przyniosl ze soba osobne komponenty wsadzilbym go do: src/Model/DB/QueryBuilder/QueryBuilder.

Mam folder controllers i w nim login.php w którym jest to wszystko, czyli.. mam sobie zrobić folder controllers/login/ i tutaj muszę rozdzielić to na pojedyncze pliki dla tego logowania tak?

Problem w tym, ze TEN Login NIE jest kontrolerem, a przynajmniej nie powinien byc. Rzeczywisty kontroler LoginController moglby korzystac z tego komponentu, acz sam w sobie nie zawieralby calej tej logiki.

Sugeruje stworzenie rzeczywistego kontrolera w miejsce Login, pod nazwa LoginController.

Ja bym zrobil to tak: LoginController zawieralby dwie metody, jedna z nich to index(): Response, ktory renderowalby widok - formularz - do zalogowania.

Nastepna metode nazwalbym: login(): Response, to wlasnie do niej przekierowywalbym formularz z index'a. W tym miejscu kontroler zarzadzalby zbudowaniem (przekazaniem parametrow jak SQLUserView czy Request) do LoginService i rozpoczeciem procesu logowania (wtwolalbys metode login serwisu login). * LoginService to klasa Login. Znajdowalaby sie w podfolderze Model, o nazwie Servicesrc/Model/Service/Authorization/LoginService.

Problem, jaki powstal, to:

Jak kontroler powinien zarzadzac procesem logowania i w jaki sposob zrobic to najlepiej. Moglbys przechwycic wyjatek jak:

throw new \InvalidArgumentException("The password is incorrect".);

Acz, kontrolwanie stanu rzeczy przy pomocy wyjatkow jest anty-wzorcrem, wiec odpada.

Wiec, zmienilbym zachowanie metody login, serwisu LoginService, na takie:

public function login(LoginData $loginData): Response
{
    if (!filter_var($loginData->getEmail(), FILTER_VALIDATE_EMAIL)) {
        throw new \InvalidArgumentException("The email is not valid.");
    }

    $user = $this->userQuery->findByEmail($loginData->getEmail());

    if (!$user) {
        $this->session->flashbag->set('error', 'Podany login jest bledny'); # Normalnie to bym tutaj uzyl jakiegos translatora jak: https://symfony.com/doc/current/translation.html
        return $this->request->redirectTo('board', 400); # 400 = Status Code
    }

    if ($user['password'] === $loginData->getPassword()) {

        $this->session->set('loginAccess', 'jest'); // testowa sesja

        return $this->request->redirectTo('board');

    } else {
        $this->session->flashbag->set('error', 'Podane haslo jest bledne'); # Normalnie to bym tutaj uzyl jakiegos translatora jak: https://symfony.com/doc/current/translation.html
        return $this->request->redirectTo('board', 400); # 400 = Status Code
    }
}

Czym jest this->session->flashbag? Ogolnie zasada dzialania polega na tym, ze po wyswietleniu takiej wiadomosci z flashbaga, ona sie usuwa z sesji. Czyli dokladnie to, czego potrzebujemy, aby ostrzec uzytkownika o blednych danych logowania.

Tworzysz warunek w widoku, ktory sprawdza czy zainstnial error, jesli tak; poinformuj o tym uzytkownika.

Moze Ci sie to wydawac skomplikowane, acz tak naprawde to, co sie zmienilo w kodzie, to tylko 4 linijki + metoda index dla LoginController. :D

Reszta to po prostu segregacja.

Nie zapomnij, poza nazwa klas, zmienic nazwe plikow podczas segregacji. Inaczej autoloader nie zadziala.

enlightenedNazwy plikow jak i foldery, zawierajace klasy/interfejsy/abstract./etc., powinny byc z duzej litery.

komentarz 26 czerwca 2018 przez nielotweb Bywalec (2,240 p.)
O jezuniu, to jest zbyt skomplikowane.. czuję się jakbym nowego facebooka tworzył:p

Jest to trochę skomplikowane bo.. nie wiem gdzie i co do jakiego folderu mam umieścić.. W sensie te rzeczy mi objaśniłeś to wiem ale w przyszłości nie będę wiedział gdzie co umieścić żeby to razem współpracowało i grało..

 Znasz jakąś stronę na której jest wyjaśnione gdzie co trzymać?

A ja zawsze myślałem że wystarczy jeden plik do jednej usługi, jak tutaj do logowania, a tutaj każdą klasę/interfejs.etc trzeba na oddzielny plik umieścić.. Mój mózg płonie:P
1
komentarz 26 czerwca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 27 czerwca 2018 przez HaKIM

 Znasz jakąś stronę na której jest wyjaśnione gdzie co trzymać?

Jeśli chodzi o tworzenie stron, to posłużyłbym się strukturą Symfony.

http://fabien.potencier.org/symfony4-directory-structure.html

Jest to trochę skomplikowane bo.. nie wiem gdzie i co do jakiego folderu mam umieścić.. W sensie te rzeczy mi objaśniłeś to wiem ale w przyszłości nie będę wiedział gdzie co umieścić żeby to razem współpracowało i grało..

Też miałem z tym spory problem, w sumie to problem z tym mam do dziś. laughWażnym jest, aby nie myśleć "folderami", a w pierwszej kolejności warstwami. Architektura MVC składa się z trzech warstw:

  1. M - (Model) Modelu
  2. V - (View) Widoku
  3. C - (Controller) Kontrolera

Bolączką MVC moim zdaniem jest właśnie w Model, gdyż wszystko, co nie jest Kontrolerem ani Widokiem, jest tutaj Modelem.

Aby dobrze rozmieścić kod w warstwie Modelu postaraj się zbytno nie rozdrabniać, acz też zostawić sobie możliwość stworzenia innych ścieżek do rozwiązania problemu.

Pisałem o tym na górze:

W folderze Model stworz podfolder o nazwie Query, tam trzymaj UserQueryInterface. Stworz kolejny podfolder do Query o nazwie View, tam trzymaj SQLUserView jak i inne implementacje QueryInterface (MovieQueryInterface czy nasz UserQueryInterface). Jesli chcesz, oczywiscie mozesz trzymac implementacje w bardziej posegregowany spsob: src/Model/Query/View/User/SQLUserView lub jeszcze bardziej specyficznie: src/Model/Query/SQL/View/User/SQLUserView choc, to oczywiscie przesada jak na Twoj przypadek. Sugeruje pierwsze rozwiazanie: src/Model/Query/View/SQLUserView.

QueryBuilder'a mozesz wsadzic do podfoldera DB, w Modelu: src/Model/DB/QueryBuilder. Gdyby jednak QueryBuilder sie rozbudowal i przyniosl ze soba osobne komponenty wsadzilbym go do: src/Model/DB/QueryBuilder/QueryBuilder.

Kontroler to taki szef, który tylko rozkazuje warstwą niżej, co mają robić. Sam dużo nie myśli nad rozwiązaniem problemu, po prostu zleca zadania innym, zapewniając im odpowiednie środki (Przekazanie odpowieniego UserQuery, Requesta, Komendę, etc).

Znajdź proszę wolną godzinkę i przeczytaj ten tutorial (od deski do deski):

https://symfony.com/doc/current/create_framework/index.html

Zrozumiesz, jak połączyć to wszystko w całość (Front Controller).

komentarz 28 czerwca 2018 przez nielotweb Bywalec (2,240 p.)

Dobra już mniej więcej rozumiem, i przeanalizuje sobie to wszystko co napisałeś.. Bo naprawdę tyle dobrej wiedzy w jednym miejscu nie widziałem.. Więc na razie daje Ci spokój laugh (śmieszkuje;p) 

Już nie mam pytań, znaczy żadne mi się nie nasuwa.. ;p Dzięki jeszcze raz za poświęcony czas! :D

komentarz 5 lipca 2018 przez nielotweb Bywalec (2,240 p.)
edycja 5 lipca 2018 przez nielotweb

Cześć, jeśli chce Ci się mi jeszcze troszkę pomóc to będę wdzięczny :D

Zrobiłem ten kontroller logowania, i wygląda on tak:


declare(strict_types=1);

namespace App\Controllers\Core;

use App\Controllers\Controller;

use App\Core\Database\Connection;
use App\Core\{Request, SessionManagement};

use App\Model\Service\Authorization\Login;
use App\Model\Service\Helpers\LoginData;
use App\Model\Query\View\SQLUserView;


class LoginController extends Controller
{

    private $email;
    private $password;

    public $session;
    public $request;
    public $connection;

    public function index() : void
    {

        // Create a login view
        Controller::renderView(
            'Authorization/Login'
        );

        // Take form input's
        $this->email = $_POST['name'];
        $this->password = $_POST['password'];

    }

    public function login() : void
    {

        $session = new SessionManagement();
        $request = new Request();
        $connection = new Connection();

        $login = new Login($request, new SQLUserView($connection->make()), $session);

        try {
            $login->login(new LoginData($this->email, $this->password));
        } catch (\Exception $exception) {
            print '<a href="https://www.youtube.com/watch?v=u9erhDRkCD0">No coś nie pykło edwidentnie.</a>';
        }

    }

}

Zrobiłem tak jak mówiłeś(?), metoda index tworzy widok, i przy okazji bierze wartości z formularza. Natomiast metoda login przekazuje wartości min. do LoginServica. 

I tu pytanie, bo żeby jakaś klasa zadziałała trzeba ją zainicjować tworząc jej obiekt.. więc gdzie mogę tworzyć ten obiekt tej klasy LoginController? Żeby to zadziałało?

Czy po prostu w tym samym pliku dać:

$login = new LoginController();
$login->index();
$login->login();

Jestem pewien że tak nie można, ale gdzie to mogę inicjować?

1
komentarz 15 lipca 2018 przez HaKIM Szeryf (87,590 p.)
edycja 15 lipca 2018 przez HaKIM

Sorry, że nie odpisywałem. Byłem na urlopie. devil

Dałeś radę rozkminić sprawę czy nadal istnieje problem?

 

komentarz 15 lipca 2018 przez nielotweb Bywalec (2,240 p.)
Spoczko, rozumiem :D

Nie, tego ostatniego problemu dalej nie rozumiem, opisałem go post wcześniej:P
1
komentarz 15 lipca 2018 przez HaKIM Szeryf (87,590 p.)
    public function index() : void
    {
 
        // Create a login view
        Controller::renderView(
            'Authorization/Login'
        );
 
        // Take form input's
        $this->email = $_POST['name'];
        $this->password = $_POST['password'];
     }

Na Twoim miejscu usunąłbym stąd te linijki, przekierował formularz bezpośrednio do login() i tam odebrał te dane.

Póki co nie korzystasz z bibliotek trzecich, więc ja bym to zrobił w ten sposób:

    public function login(Request $request): void
    {
        # [...]
        $email = $request->get('email', null);
        $password = $request->get('password', null)
        # [...]
     }

 

I tu pytanie, bo żeby jakaś klasa zadziałała trzeba ją zainicjować tworząc jej obiekt.. więc gdzie mogę tworzyć ten obiekt tej klasy LoginController? Żeby to zadziałało?

 W grę może wejść DI.

https://www.phptherightway.com/#dependency_injection

Dodaj do konstruktura LoginController wszystkie składowe, które on potrzebuje.

Wyglądałby to mniej więcej tak:

class LoginController extends Controller
{
    # [...]

    private $session;
    private $connection;

    public function __construct(
        SessionManagement $session,
        Connection $connection
    ) {
        $this->session = $session;
        $this->connection = $connection;
    }

    public function login(Request $request): void
    {
        $email = $request->get('email', null);
        $password = $request->get('password', null);

        $login = new Login($request, new SQLUserView($this->connection->make()), $this->session);

        try {
            $login->login(new LoginData($email, $password));
        } catch (\Exception $exception) {
            print '<a href="https://www.youtube.com/watch?v=u9erhDRkCD0">No coś nie pykło edwidentnie.</a>';
        }
    }

    # [...]
}

Teraz jedynie wstrzykasz poszczególne komponenty w pliku gdzie stworzyłeś obiekt LoginController; new LoginController(...).

Sądzę też, że to dobry moment na zainteresowanie się bytem jak Dependency Injection Container. Ja od siebie moge polecić Pimple.

Btw. zrób sobie interfejsy dla dla Connection i Session. Gdy dojdzie Ci kolejna implementacja Connection, np. dla postgresa, to zaoszczędzisz sobie trochę klepania kodu.

komentarz 16 lipca 2018 przez nielotweb Bywalec (2,240 p.)

Teraz jedynie wstrzykasz poszczególne komponenty w pliku gdzie stworzyłeś obiekt LoginController; new LoginController(...).

No właśnie nie wiem gdzie tworzyć te obiekty, tzn. np. tego kontrolera. Mam normalnie napisać to pod klasą, w tym samym pliku?;p

Btw. zrób sobie interfejsy dla dla Connection i Session. Gdy dojdzie Ci kolejna implementacja Connection, np. dla postgresa, to zaoszczędzisz sobie trochę klepania kodu.

I właśnie tak mnie teraz naszło pytanie, kiedy mam tworzyć sobie interfejsy? W sensie nie wiem kiedy potrzebuje jakiegoś interfejsu.. 

Na Twoim miejscu usunąłbym stąd te linijki, przekierował formularz bezpośrednio do login() i tam odebrał te dane.

Stworzyłem tą metodę, bo sam tak zaproponowałeś, i żeby ona tworzyła widok:p 

1
komentarz 17 lipca 2018 przez HaKIM Szeryf (87,590 p.)

No właśnie nie wiem gdzie tworzyć te obiekty, tzn. np. tego kontrolera. Mam normalnie napisać to pod klasą, w tym samym pliku?;p 

W Twoim front-controllerze. Podesłałem Ci tutorial od SensioLabs, twórców Symfony; tam jest przedstawiony taki byt.

https://symfony.com/doc/current/create_framework/front_controller.html

No offensive, ale przed przeczytaniem tego tutoriala od deski do deski to bym się wstrzymał z pytaniami. xD

Stworzyłem tą metodę, bo sam tak zaproponowałeś, i żeby ona tworzyła widok:p 

Tak, ale nie aby jeszcze zajmowała się settowaniem danych z formularza. :D

Ja bym zrobil to tak: LoginController zawieralby dwie metody, jedna z nich to index(): Response, ktory renderowalby widok - formularz - do zalogowania.

Nastepna metode nazwalbym: login(): Response, to wlasnie do niej przekierowywalbym formularz z index'a. W tym miejscu kontroler zarzadzalby zbudowaniem (przekazaniem parametrow jak SQLUserView czy Request) do LoginService i rozpoczeciem procesu logowania (wtwolalbys metode login serwisu login). * LoginService to klasa Login. Znajdowalaby sie w podfolderze Model, o nazwie Servicesrc/Model/Service/Authorization/LoginService.

I właśnie tak mnie teraz naszło pytanie, kiedy mam tworzyć sobie interfejsy? W sensie nie wiem kiedy potrzebuje jakiegoś interfejsu.

Ciężko mi zebrać myśli, bo mam słabą głowę a wypiłem, ale ująłbym to tak: Jeżeli przepuszczasz, że dana instancja obiektu może być wiele razy używana w projekcie oraz gdy ta może być zastępiona inną, robiącą podobną rzecz, acz dla innego "operatora", wtedy twórz interfejs dla podzbioru tychże klas.

Wkręciłem się w opisywanie sytuacji kiedy stosować interfejsy etc., ale doszedłem do wniosku, że lepsi ode mnie to już zrobili i opublikowali. Ja oszczędzę sobie wywodu i masę poprawek, aby załatać nieścisłości.

Może zacznij od tego: https://webmastah.pl/jak-programowac-obiektowo-cz-8-interfejsy/

komentarz 18 lipca 2018 przez nielotweb Bywalec (2,240 p.)

W Twoim front-controllerze. Podesłałem Ci tutorial od SensioLabs, twórców Symfony; tam jest przedstawiony taki byt.

https://symfony.com/doc/current/create_framework/front_controller.html

No offensive, ale przed przeczytaniem tego tutoriala od deski do deski to bym się wstrzymał z pytaniami. xD

Aaa takie buty, dobra przeczytam całe i obczaję wszystko:p

Ciężko mi zebrać myśli, bo mam słabą głowę a wypiłem, ale ująłbym to tak: Jeżeli przepuszczasz, że dana instancja obiektu może być wiele razy używana w projekcie oraz gdy ta może być zastępiona inną, robiącą podobną rzecz, acz dla innego "operatora", wtedy twórz interfejs dla podzbioru tychże klas.

Wkręciłem się w opisywanie sytuacji kiedy stosować interfejsy etc., ale doszedłem do wniosku, że lepsi ode mnie to już zrobili i opublikowali. Ja oszczędzę sobie wywodu i masę poprawek, aby załatać nieścisłości.

Może zacznij od tego: https://webmastah.pl/jak-programowac-obiektowo-cz-8-interfejsy/

 Już rozumiem, tzn. po tym co napisałeś już mniej więcej zrozumiałem, ale to co podesłałeś też sobie poczytam. Więc na razie nie mam innych pytań, ale zapewne za niedługo znów coś nie będę wiedział i napiszę o ile będziesz miał jeszcze zapał mi pomóc;p

komentarz 20 lipca 2018 przez nielotweb Bywalec (2,240 p.)

Poczytałem i troszkę nie rozumiem tego FrontController'a.. 

Front Controller działa podobnie jak Router czyli może zajmować się przetwarzaniem URL (router ma za zadanie tylko to robić), natomiast Front może również być bezpośrednio odpowiedzialny za wywoływanie poszczególnych klas czy metod. Doczytałem że przykładowo w Symfony za front controller odpowiada plik index.php. 

A więc Front Controller odpowiada za wywoływanie klas, czyli o to mi chodziło, ale nie rozumiem jednej rzeczy, front controller to jest jeden plik czyli np. tą klasę kontrolera Loginu mam tam wywołać? Nie rozumiem logiki tego.

Tutaj mam plik index.php (załóżmy że robi on za front controller) 

use App\Core\{Router, Request};

    /* Require composer */
    require 'vendor/autoload.php';

    /* Require routes and router */
    $Request = new Request;
    $Router = new Router;

    require 'Routes.php';
    require $Router->direct($Request::uri());

I tutaj wywoływać te klasy z kontrolerów? Jestem pewien że to nie tak ma być jak myślę;p

1
komentarz 21 lipca 2018 przez HaKIM Szeryf (87,590 p.)

I tutaj wywoływać te klasy z kontrolerów? Jestem pewien że to nie tak ma być jak myślę;p

Nie... i tak. Tutaj możesz np. dołączyć plik controllers.php i tam wywoływać te klasy.

The front controller software design pattern is listed in several pattern catalogs and related to the design of web applications. It is "a controller that handles all requests for a website",[1] which is a useful structure for web application developers to achieve the flexibility and reuse without code redundancy.

https://en.wikipedia.org/wiki/Front_controller

Sądzę, że ten Front Controller wszystko Ci wyjaśni:

https://github.com/HaKIMus/slim-template/blob/master/public/index.php

komentarz 22 lipca 2018 przez nielotweb Bywalec (2,240 p.)

Dobra już obczaiłem, i wiem o co chodzi.

Mam inny, mały problem. Bo gdy się próbuję logować, to mi wywala błąd na pół strony. Ale ten błąd wyskakuje tylko wtedy gdy emailu nie ma w bazie.

Problem tkwi w tym:

    public function findByEmail(string $email) : string
    {
        $statement = $this->pdo->prepare("SELECT * FROM users WHERE email = :email");
        $statement->bindParam(":email", $email, PDO::PARAM_STR);
        $statement->execute();

        return $statement->fetch(PDO::FETCH_ASSOC);
    }

gdy email jest w bazie to normalnie pyka, wyskakuje komunikat że złe dane logowania (ofc. gdy jest złe hasło), ale gdy wpisanego emailu nie ma w bazie to wywala błąd że ta metoda 'findByEmail' zwraca boolena ( bool(false) ) a nie zwraca dane z bazy.

Gdy usunę ' : string ' to się nie krzaczy i wszystko działa. Jak mogę na to zaradzić? W sensie nie mam pomysłu co mogę dać za ten :string, albo czy zostawić go puste, tzn. usunąć.

1
komentarz 22 lipca 2018 przez HaKIM Szeryf (87,590 p.)

Możesz spróbować dodać:

public function findByEmail(string $email) : ?string

Ten ?string oznacza: Ta metoda musi zwrócić STRING albo NULL.

Stąd wnioskuję, że taki kod powinien się sprawdzić:

    return ($statement->fetch(PDO::FETCH_ASSOC)) ? $statement->fetch(PDO::FETCH_ASSOC) : null;

http://us2.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary

https://davidwalsh.name/php-shorthand-if-else-ternary-operators


Zapomniałem wyjaśnić:

ale gdy wpisanego emailu nie ma w bazie to wywala błąd że ta metoda 'findByEmail' zwraca boolena ( bool(false) ) a nie zwraca dane z bazy.

 Dzieje się tak gdyż fetch, podczas braku wyników, zwraca false. Nasza metoda obsługuje tylko stringa albo null.

Skąd wiem, że zwraca false? Dokumentacja (or, jeśli używasz phpstorma, ctrl + click na metodę fetch i tam czytasz phpdoca). :D

komentarz 25 lipca 2018 przez nielotweb Bywalec (2,240 p.)
przywrócone 27 lipca 2018 przez HaKIM

Dzieje się tak gdyż fetch, podczas braku wyników, zwraca false. Nasza metoda obsługuje tylko stringa albo null.

Skąd wiem, że zwraca false? Dokumentacja (or, jeśli używasz phpstorma, ctrl + click na metodę fetch i tam czytasz phpdoca). :D

Wiem właśnie to obczaiłem wcześniej tylko zapomniałem Ci napisać:P

Zrobiłem sobie teraz ten system wyświetlania wiadomości, niby wszystko działa ale nie tak jak chciałem. Tzn. po wpisaniu błędnych informacji wyświetla się odpowiednia wiadomość, tylko że dopiero po odświeżeniu strony. 

Czyli wpisuje dane (błędne) klikam zaloguj, formularz robi swoje, odświeża się strona i nie ma wiadomości. Wyświetli się dopiero gdy ją sam drugi raz odświeżę. 

A drugi defekt jest taki że te wiadomości znikają po zbyt długim czasie, muszę z 5-15 razy odświeżyć stronę żeby znikneły.

A zamysł jest taki że: Klikam loguj, od razu się wyświetla, ja odświeżam i od razu znika.

A tutaj cały kod:

// PLIK FLASHMESSAGES.PHP

declare(strict_types=1);

namespace App\Core;

class FlashMessages {

    public function __construct()
    {
        // Create flash_message variable if doesn't exists yet.
        if (!array_key_exists('flash_messages', $_SESSION))
        {
            $_SESSION['flash_messages'] = array();
        }

    }

    public function add(string $type, string $messages)
    {
        $_SESSION['flash_messages'][$type][] =  $messages;
    }

    public function display(string $type) : string
    {
        $message = $this->formatMessage($type);
        $this->cleanMessage();
        return $message;
    }
    public function cleanMessage()
    {
        unset($_SESSION['flash_messages']);
    }
    public function formatMessage(string $type) : string
    {
        $implode = implode(',', $_SESSION['flash_messages'][$type]);
        $output = trim($implode);

        return $output;
    }

}
<!doctype html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<?php

    use App\Core\FlashMessages;

    require './Core/FlashMessages.php';

    $flash = new FlashMessages();

    if ( isset($_SESSION['flash_messages']['error']) )
    {
        $data = explode(',', $flash->display('error'));

        foreach ($data as $value)
        {
            echo '<ul><li>' . $value . '</li></ul>';
        }
    }



?>
    <form action="login" method="POST">
        <input type="text" class="email" name="email">
        <input type="text" class="password" name="password">
        <input type="submit" class="submit" name="submit">
    </form>
</body>
</html>

Gdzie robię błąd?

-----------------------------------

EDIT: Nie wiem jak ale jakimś cudem to naprawiłem. Tzn. wiadomość od razu się wyświetla, tylko jeszcze ten jeden mały defekt, czyli jak zrobić żeby od razu po odświeżeniu zniknęła wiadomość? Bo ona znika wtedy gdy sam przeładuję stronę ( od nowa wpiszę adres ) a nie gdy odświeżę, a chcę żeby po odświeżeniu zniknęła;p

1
komentarz 27 lipca 2018 przez HaKIM Szeryf (87,590 p.)

Bo ona znika wtedy gdy sam przeładuję stronę ( od nowa wpiszę adres ) a nie gdy odświeżę, a chcę żeby po odświeżeniu zniknęła;p

Problem leży po stronie usuwania sesji, radziłbym się mu przyjrzeć. W teorii, jeśli został wykonany proces - po wyświetleniu - usuwania jej danych, wtedy, po refresh'u, żaden komunikat z nią związany nie powinien się pojawiać.

Gdybyś sam nie mógł znaleźć problemu, poszukaj na google jak poprawnie usunąć sesje w PHP, jeśli google nie pomoże; Daj znać, to pomyślimy. :D 

komentarz 12 sierpnia 2018 przez nielotweb Bywalec (2,240 p.)

Cześć, ciągle, powolutku sobie robię tę stronę. I mam jedno pytanko.

Chodzi mi o widoki, otóż gdy chce kodzik php włożyć to muszę wywoływać klasy itd. i z tego robi się 'burdel'. Nie wiem jak to wytłumaczyć, dam po prostu kawałek jednego pliku ( widoku )

<?php require './View/Template/Header.php'; ?>

<head>
    <title>Panel kontrolny admina</title>
</head>

<?php

    use App\Model\Service\Helpers\UserData;
    $userData = new UserData();

    use App\Model\Service\Helpers\Dashboards\Admin\AdminDashboardData;
    $dashboardData = new AdminDashboardData();

    use App\Core\Request;
    $request = new Request();

    use App\Core\Messages\FlashBag;
    $flash = new FlashBag();

    use App\Core\SessionManagement;
    $session = new SessionManagement();

?>

<body>

    <nav class="uk-margin uk-background-dark" uk-navbar>
        <div class="uk-navbar-left">
            <div class="uk-margin-medium-left">
                <a class="uk-navbar-item uk-logo" href="#">PhotoMagic</a>
            </div>
        </div>
        <div class="uk-navbar-right">
            <div class="uk-margin-medium-right">
                <ul class="uk-navbar-nav">
                    <li class="uk-flex uk-flex-middle">
                        <div class="uk-width-auto">
                            <img class="uk-border-circle uk-card-default" width="50" height="50" src="<?php echo $userData->getAvatar(); ?>">
                        </div>
                    </li>
                    <li>
                        <a class="uk-button-text" href="#">
                            <?php echo $userData->getName(); ?>
                            <span class="uk-margin-small-left uk-label uk-label-success">ONLINE</span>
                        </a>
                        <div uk-dropdown="pos: bottom-right; mode: click" class="uk-navbar-dropdown">

                            <ul class="uk-nav uk-dropdown-nav">
                                <li>
                                    <a href="#">Profil</a>
                                </li>
                                <li>
                                    <a href="#">Wiadomości</a>
                                </li>
                                <li class="uk-nav-header">Ustawienia</li>
                                <li>
                                    <a href="#">Dane profilu</a>
                                </li>
                                <li>
                                    <a href="#">Bezpieczeństwo</a>
                                </li>
                                <li class="uk-nav-header">Ustawienia admina</li>
                                <li>
                                    <a href="#">Główne ustawienia</a>
                                </li>
                                <li>
                                    <a href="#">Użytkownicy</a>
                                </li>
                                <li>
                                    <a href="#">Strony</a>
                                </li>
                                <li>
                                    <a href="#">Zabezpieczenia</a>
                                </li>
                                <li class="uk-nav-divider"></li>
                                <li>
                                    <a href="#">Pomoc</a>
                                </li>
                                <li>
                                    <a href="logout" class="uk-button uk-button-danger uk-margin-small-top">Wyloguj</a>
                                </li>
                            </ul>

                        </div>
                    </li>
                </ul>

            </div>
        </div>
    </nav>

    <div class="uk-container-large uk-align-center">
        <div class="uk-alert-primary" uk-alert>
            <a class="uk-alert-close" uk-close></a>
            <p>Cześć <?php echo $userData->getName(); ?>, znajdujesz się aktualnie w panelu admina.</p>
        </div>
    </div>

    <div class="uk-section uk-padding-remove-vertical uk-margin">
        <div class="uk-container-large uk-align-center">
            <div class="uk-child-width-1-3@m uk-grid-match" uk-grid>
                <div>
                    <div class="uk-card uk-card-default uk-card-hover uk-card-body">
                        <h3 class="uk-card-title">Ilość wrzuconych zdjęć</h3>
                        <h1 class="uk-h1 uk-margin-remove-top uk-text-bold">19 201</h1>
                        <span class="uk-label uk-label-success">Ostatnie zdjęcie wrzucił</span>
                    </div>
                </div>
                <div>
                    <div class="uk-card uk-card-default uk-card-hover uk-card-body">
                        <h3 class="uk-card-title">Ilość użytkowników</h3>
                        <h1 class="uk-h1 uk-margin-remove-top uk-text-bold">2019</h1>
                        <span class="uk-label uk-label-warning">Najnowszy użytkownik: Hubert Kruk</span>
                    </div>
                </div>
                <div>
                    <div class="uk-card uk-card-default uk-card-hover uk-card-body">
                        <h3 class="uk-card-title">Suma danych</h3>
                        <h1 class="uk-h1 uk-margin-remove-top uk-text-bold">304 019 GB</h1>
                        <span class="uk-label uk-label-default">Ostatni plik waży: 1,5mb</span>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="uk-section uk-padding-remove-vertical uk-margin">
        <div class="uk-container-large uk-align-center">
            <table class="uk-table uk-table-striped">
                <thead>
                <tr>
                    <th>Nickname</th>
                    <th>Email</th>
                    <th>Flaga</th>
                    <th class="uk-width-medium">Opcje</th>
                </tr>
                </thead>
                <tbody>
                    <?php foreach ($dashboardData->getAllDataFromUsersTable() as $data) : ?>

                        <tr>
                            <td>
                                <img class="uk-border-rounded uk-margin-small-right" data-src="<?php echo $data['avatar'] ?>" width="50" height="50" alt="User avatar" uk-img>
                                <?php echo $data['nickname']; ?>
                            </td>
                            <td class="uk-text-middle">
                                <?php echo $data['email']; ?>
                            </td>
                            <td class="uk-text-middle">
                                <?php if ($data['is_admin'] == true): ?>
                                    <span class="uk-label uk-label-danger">Admin</span>
                                <?php else: ?>
                                    <span class="uk-label uk-label-success">Użytkownik</span>
                                <?php endif; ?>
                            </td>
                            <td class="uk-text-middle">
                                <a href="admin/users/delete?user=<?php echo $data['id']; ?>" id="delete-user" class="uk-button uk-button-danger uk-margin-small-right">Dezaktywuj</a>
                                <a href="#" class="uk-button uk-button-primary">Edytuj</a>
                            </td>
                        </tr>

                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </div>

<?php require './View/Template/Footer.php'; ?>

I zobacz że tworząc te klasy, i wkładając ten cały kod robi się zament. Jest jakiś sposób żeby to upiększyć? 

I drugi problem, czy twoim zdaniem taki Front Kontroler ma sens?

<?php

declare(strict_types=1);

use App\Core\{Request, SessionManagement};
use App\Core\Database\Connection;
use App\Core\Messages\FlashBag;
use App\Core\Security\Auth;

use App\Model\Service\Helpers\UserData;
use App\Model\Service\Authorization\UserService;

// Starting session
$Session = new SessionManagement();
$Session->start();

// Starting Auth controller
$Auth = new Auth( new UserService(new UserData()), new SessionManagement());


/*
 *
 *  Running controllers
 *
 */

    // Login controller
    if ( Request::uri() == 'loginAction' )
    {
        if ( $Auth->checkAccessToPage('isLogged') == true ) { Request::redirectTo('user/dashboard'); }

        $loginController = new App\Controllers\Core\LoginController( new SessionManagement(), new Connection() );
        $loginController->login( new Request() );
    }
    if ( Request::uri() == 'login' )
    {
        if ( $Auth->checkAccessToPage('isLogged') == true ) { Request::redirectTo('user/dashboard'); }

        $loginController = new App\Controllers\Core\LoginViewController();
        $loginController->index();
    }

    // Logout controller
    if ( Request::uri() == 'logout' )
    {
        if ( $Auth->checkAccessToPage('isLogged') == false ) { Request::redirectTo('login'); }

        $logoutController = new App\Controllers\Helpers\LogoutController( new SessionManagement() );
        $logoutController->logout();
    }

    //
    //  User section
    //
        if ( Request::uri() == 'user/dashboard' )
        {
            if ( $Auth->checkAccessToPage('isLogged') == false ) { Request::redirectTo('login'); }

            $userDashboard = new App\Controllers\Core\Dashboards\User\UserDashboard( new SessionManagement(), new Connection() );
            $userDashboard->index();
        }


    //
    //  Admin section
    //
        if ( Request::uri() == 'admin/dashboard' )
        {
            if ( $Auth->checkAccessToPage('isLogged') == false ) { Request::redirectTo('login'); }
            if ( $Auth->checkAccessToPage('isAdmin') == false ) { Request::redirectTo('user/dashboard'); }

            $adminDashboard = new App\Controllers\Core\Dashboards\Admin\AdminDashboard( new SessionManagement(), new Connection() );
            $adminDashboard->index();
        }

        if ( Request::uri() == 'admin/users/delete' )
        {
            if ( $Auth->checkAccessToPage('isLogged') == false ) { Request::redirectTo('login'); }
            if ( $Auth->checkAccessToPage('isAdmin') == false ) { Request::redirectTo('user/dashboard'); }

            $deleteUsers = new App\Controllers\Core\Dashboards\Admin\DeleteUsersController( new Connection(), new Request(), new FlashBag() );
            $deleteUsers->deleteUser();
            $deleteUsers->index();
        }

 

1
komentarz 13 sierpnia 2018 przez HaKIM Szeryf (87,590 p.)
I drugi problem, czy twoim zdaniem taki Front Kontroler ma sens?

Tak. Tylko przenieś router do pliku router.php a potem tylko include(__DIR__ . '/sciezka/do/router.php');

No i radziłbym zainteresowaniem się DI Container i jego, tak samo jak wymieniłem na górze router, też includował.

enlightened Dołączaj go przed routerem, bo to do klas w routerze będziesz te zależności wstrzykiwał.

Chodzi mi o widoki, otóż gdy chce kodzik php włożyć to muszę wywoływać klasy itd. i z tego robi się 'burdel'. Nie wiem jak to wytłumaczyć, dam po prostu kawałek jednego pliku ( widoku )

Co się tyczy tego problemu, zaimplementuj Twig'a i powiedz pa pa PHPowi w templatach. ;)

https://twig.symfony.com/doc/2.x/intro.html

Stwórz sobie AbstractController i tam wstrzyknij Twig_Environment, cobyś nie musiał za każdym razem wstrzykiwać tego systemu do każdego z kontrolerów.

Wynik powinien prezentować się w ten deseń:

$this->twig->render('homepage.twig', [
'userData' => $userData
]);

// Gdzie $userData jest już wcześniej przygotowane w kontrolerze.

komentarz 14 sierpnia 2018 przez nielotweb Bywalec (2,240 p.)

No i radziłbym zainteresowaniem się DI Container i jego, tak samo jak wymieniłem na górze router, też includował.

Okej na pewno poczytam. 

Co się tyczy tego problemu, zaimplementuj Twig'a i powiedz pa pa PHPowi w templatach. ;)

 W sumie słyszałem o nim.. nawet myślałem żeby to wprowadzić ale wolałem się spytać i upewnić;p

Dzięki, już nie mam pytań, jak na razie;p bo będę miał remont w domu i brak dostępu do stacji więc.. znów muszę przerwę od tego zrobić.. no cóż.. ale dzięki wielkie!

Albo w sumie inne pytanie, z innej beczki. Ty zawodowo zajmujesz się php'em? Pracujesz jako phpowiec? Pytam bo widzę że bardzo to ogarniasz. Ofc. nie musisz odpowiadać jak nie chcesz, ciekawski jestem po prostu ;D

1
komentarz 14 sierpnia 2018 przez HaKIM Szeryf (87,590 p.)

Albo w sumie inne pytanie, z innej beczki. Ty zawodowo zajmujesz się php'em? Pracujesz jako phpowiec? Pytam bo widzę że bardzo to ogarniasz. Ofc. nie musisz odpowiadać jak nie chcesz, ciekawski jestem po prostu ;D

Nope. Moje zawodowe doświadczenie, o ile można to tak nazwać, to jedynie rok praktyk od których nabawiłem się lęku wstawania, odruchów wymiotnych z rana, typowego „tylko #$@% nie to” gdy widzisz Monday na telefonie oraz myśli jak już odejdę, którym niejednokrotnie towarzyszyła ekstaza. Była to wyłącznie moja wina; nie potrafiłem powiedzieć dość oraz „ja w tym gównie nie będę się babrał”, już na samym początku.

Właśnie jestem w trakcie wykonywania zadania rekrutacyjnegoa i mam nadzieję, że zaowocuje to umową o pracę. Oczywiście, już w innej firmie i z technologiami, które jak najbardziej lubię.

Opisałem to tyćkę obszerniej, niż zamierzałem, abyś mógł wyciągnąć pewne wnioski. Choć jakie, to już do ustalenia oddaję Tobie.

komentarz 15 sierpnia 2018 przez nielotweb Bywalec (2,240 p.)

No takiej odpowiedzi się nie spodziewałem. 

Nope. Moje zawodowe doświadczenie, o ile można to tak nazwać, to jedynie rok praktyk od których nabawiłem się lęku wstawania, odruchów wymiotnych z rana, typowego „tylko #$@% nie to” gdy widzisz Monday na telefonie oraz myśli jak już odejdę, którym niejednokrotnie towarzyszyła ekstaza. Była to wyłącznie moja wina; nie potrafiłem powiedzieć dość oraz „ja w tym gównie nie będę się babrał”, już na samym początku.

Po tym fragmencie wnioskuje że zawód programisty nie taki kolorowy jakby się wydawało. Albo po prostu to efekt firmy w której te doświadczenia nabierałeś?

Właśnie jestem w trakcie wykonywania zadania rekrutacyjnegoa i mam nadzieję, że zaowocuje to umową o pracę. Oczywiście, już w innej firmie i z technologiami, które jak najbardziej lubię.

Ale już po tym widzę że Cię ciągnie jednak na ten zawód. W sumie jak mnie, tylko pytanie, czy to jest dobry wybór. Mam dopiero 18 lat, w następnym roku matura i potem trzeba wybrać co będę robił w życiu. W sumie mam dwie opcje. Albo się kształtować, jak to teraz robię na programistę, albo na moją drugą zajawkę, grafikę komputerową. Zadałem to pytanie czy zawodowo siedzisz w php, bo chciałem się dowiedzieć czy warto :D 

 

1
komentarz 15 sierpnia 2018 przez HaKIM Szeryf (87,590 p.)

Albo po prostu to efekt firmy w której te doświadczenia nabierałeś?

Jestem w stu procentach przekonany i mógłbym dowieść, że była to tylko i wyłącznie moja wina. Złe decyzje i brak odwagi, po prostu.

Ale już po tym widzę że Cię ciągnie jednak na ten zawód.

Hmm... Szczerze mówiąc, to już mam dość programowania. Za mało w nim adrenaliny. Ja czuję wewnętrzną potrzebę do podejmowania ryzyka, a programowanie nie jest w stanie tej potrzeby zaspokoić. Tak, nawet deployami w piątek! devil

Na bank chcę wykorzystać stosunkowo dobre zarobki programistów na rynku, aby dostarczyć sobie mocnych wrażeń, przez co programowanie byłoby fajną odskocznią i równowagą.

Mam dopiero 18 lat, w następnym roku matura i potem trzeba wybrać co będę robił w życiu. W sumie mam dwie opcje. Albo się kształtować, jak to teraz robię na programistę, albo na moją drugą zajawkę, grafikę komputerową. 

Rób to, co w długoterminowej grze przyniesie Ci przede wszystkim więcej szczęścia.

Zadałem to pytanie czy zawodowo siedzisz w php, bo chciałem się dowiedzieć czy warto :D 

Jeśli chodzi o: czy warto, bo będę przez to szczęśliwy: To zależy od tego czy lubisz programować. Dodatkowo, programowanie w biurze od tego w domu trochę się różni. Może dać Ci więcej frajdy, a może jest coś, czego nie znosisz i 8h ledwo co wytrzymujesz. Choć, na szczęście w tym zawodzie można pracować z domku. Sam musisz ustalić czy to dla Ciebie. cheeky 

Jeśli chodzi o pieniądze, to jak jesteś bardzo dobry technicznie oraz masz wysokie umiejętności personalne, a to właśnie takich programistów jest brak na rynku, to ogromne stawki będziesz zarabiał niezależnie od języka.

komentarz 16 sierpnia 2018 przez nielotweb Bywalec (2,240 p.)

Rób to, co w długoterminowej grze przyniesie Ci przede wszystkim więcej szczęścia.

I tu mam ten problem że sam nie wiem co mi daje więcej szczęścia. Programowanie jest spoko, bo mnie to jeszcze nie męczy, tylko nie wiem jak to będzie na dłuższą metę. Grafiką komputerową jarałem się od małego, w podstawówce już coś w gimpie skrobałem. W sumie to ja we wszystkim sił próbowałem, od muzyki po animacje 3D. Naprawdę wiele rzeczy próbowałem, ale wiele już odpuściłem bo stwierdziłem że już za późno na naukę nowej dziedziny :D Ale jednak chyba zostanę na razie przy programowaniu, grafice i jeszcze ostatnio zaczynam skrobać coś w modelingu 3D pod level design w grach - w sumie to jest pochodna grafiki komputerowej więc to jest to samo. 

Ale na co by nie patrzeć mam jeszcze czas na 'luźną zabawę' a potem na poważnie za coś się wezmę. Bo na pewno nie będę robił w życiu tego co mnie nie jara i mnie nudzi;p

Więc dzięki za te wartościowe dla mnie informacje! :D One serio dają do myślenia! 

komentarz 25 sierpnia 2018 przez nielotweb Bywalec (2,240 p.)
Cześć to znów ja;p Mam mały problem. Otóż gdy po wejściu na stronę otwiera się od razu box i trzeba go zaakceptować. Po zaakceptowaniu go ma się stworzyć ciasteczko że został zaakceptowany. Tylko mam ten problem że nie wiem jak to mogę ugryźć, bo działa to tak że po kliknięciu buttona z html ma się wywołać funkcja z klasy Cookies.

Czy tutaj potrzeba zasięgnąć ajaxa? Czy jakiś innym sposobem mogę to zrobić?
1
komentarz 25 sierpnia 2018 przez HaKIM Szeryf (87,590 p.)

Może założysz osobny temat do tego problemu? :D

Sądzę, że i tak za dużo tutaj pisaliśmy. cheeky

Tak, możesz użyć Ajax'a. Możesz również stworzyć Cookie w JS'ie po naciśnięciu na button "akceptuj".

komentarz 25 sierpnia 2018 przez nielotweb Bywalec (2,240 p.)
Masz racje, chyba zrobiliśmy jeden z dłuższych tematów na forum:P

Dobra to tak jak myślałem ajaxem spróbuję.

Podobne pytania

+1 głos
1 odpowiedź 177 wizyt
pytanie zadane 11 lutego 2022 w PHP przez ZnaQu Nowicjusz (130 p.)
0 głosów
0 odpowiedzi 97 wizyt
pytanie zadane 26 kwietnia 2020 w PHP przez creend Gaduła (4,700 p.)
0 głosów
1 odpowiedź 278 wizyt
pytanie zadane 16 grudnia 2019 w PHP przez Piotr Jarema Użytkownik (970 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...