Symfony framework как работи?

anonimen

Super Moderator
Скорошните теми на даката (и техните отговори) ме заинтригуваха (мерси дака :D) и реших да поразуча някой фреймуърк, реших това да е Symfony.

Създадох проект, подкарах го, добавих някои контролери по модела в pdf-книгата и всичко работи - и точно това ми е проблема :D:D

Просто се чудя как така в папката src/AppBundle/Controller слагам файлове, които автоматично фрейма ги намира, търси по коментарите и изпълнява метода под тях.

Ето пример: слагам в горната директория файл с произволно име (someco.php) и вътре клас "someco" без да спазвам никакви конвенции и т.н. със следното съдържание:

PHP:
<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;

class someco {
    /**
     * @Route("qwerty/{qw}")
     */
    public function popopop ($qw) {
        return new Response("Hello! $qw");
    }
}

След това отварям http://localhost:8000/app_dev.php/qwerty/7 и по някакъв автомагически начин фрейма намира файла someco.php, вижда @Route, прочита го, вижда че матчва на url-то и изпълнява метода под коментара popopop() като подава параметър "7".
На всичкото отгоре ако сменя $qw на $erty, дава грешка - очевидно прочита и името на параметъра и го сравнява с това, което съм дал в @Route.
Интересно е също, че каквото и име да дам на метода, той пак се изпълнява...

Ако може някой да обясни какво се случва тук :shock: че тези магийки не са ми познати :D :D :D

п.п. google-нах за php annotations и намерих обяснение как става това с четенето на коментари, но изобщо не ми е ясно защо е направено така ?
 
Идея си нямам. Това е просто можеби удобно но утежняващо кода. Простият лоадър на неймспейсове който Иван Ванков бе драснал за неговата система в уроците си а и от други источници на мен ми върши повече от прекрасна работа. Създавам две области системна и юзър област след което просто си правя структорното описване на папките и се получава повече от прекрасно. За твоето питане това е удобно направено но някак си не ме радва много много. Самото четене на анонтациите дърпа време и производителност.
 
Анотациите са един от вариантите. Другия е yaml конфигурации. Всичко това се кешира и не се парсва с всяко зареждане на страниците. Защо е направено така - за удобство, за да е структурирано (предпочитам yaml пред анотациите). :)
 
dakata__92 каза:
Идея си нямам. Това е просто можеби удобно но утежняващо кода. Простият лоадър на неймспейсове който Иван Ванков бе драснал за неговата система в уроците си а и от други источници на мен ми върши повече от прекрасна работа. Създавам две области системна и юзър област след което просто си правя структорното описване на папките и се получава повече от прекрасно. За твоето питане това е удобно направено но някак си не ме радва много много. Самото четене на анонтациите дърпа време и производителност.
Може да е удобно но ми се вижда доста странно... Би ли постнал линк към въпросния "лоадър на неймспейсове"? Досега не бях чувал за такова нещо и ще ми е интересно да го видя. Демек правиш нещо като foreach(scandir('.') as $file) { include $file; } ли или какво? :idea:

Някакси ми липсва "строга дисциплина" в symfony-то... Всеки случай ще разгледам и laravel, за него мисля че gatakka имаше туториали.

djman каза:
Анотациите са един от вариантите. Другия е yaml конфигурации. Всичко това се кешира и не се парсва с всяко зареждане на страниците (би било глупаво да е иначе, нали?)
Да, предполагам :D
Но каква е идеята на това да ползваш собствени имена за всеки контролер и метод? Просто ми е странно че можеш да си ползваш каквито си искаш имена без да ги указваш никъде...
 
Искаш да ти изтрещи грешка, че иска {SomeName}Controller.php ли? Ти ако имаш глава, няма да пишеш asdfmovie.php контролер в истински проект. :D Между другото actions трябва да имат суфикс Action, но предполагам това не важи за анотации, странно.

Symfony, imo, балансира между strictness и свобода.

Преди писах на Laravel, но след като открих симфонията.... живота стана хубав. :D
 
Това е кодът на гатака. Естествено аз съм с иго преработил за моите нужди но реално когато създаваш неймспейсове и регистрираш неймспейс в лоадъра после когато се упитваш да направиш инстанция на класът лоадъра проверява дали съществува въпросният неймспейс къде се намира класът и го добавя. Гатака ползва include аз include_once за допълнителна защита.

PHP:
<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of Loader
 *
 * @author gatakka
 */

namespace GF;

class Loader {

    private static $namespaces = array();

    private function __construct() {
        
    }

    public static function registerAutoLoad() {
        spl_autoload_register(array("\GF\Loader", 'autoload'));
    }

    public static function autoload($class) {
        self::loadClass($class);
    }

    //TODO central error reporting
    public static function loadClass($class) {        
        foreach (self::$namespaces as $k => $v) {
            if (strpos($class, $k) === 0) {
                $file = realpath(substr_replace(str_replace('\\', DIRECTORY_SEPARATOR, $class), $v, 0, strlen($k)) . '.php');                               
                if ($file && is_readable($file)) {
                    include $file;
                } else {
                    throw new \Exception('File cannot be included:' . $file);
                }
                break;
            }
        }
    }    
    
    public static function registerNamespace($namespace, $path) {
        $namespace = trim($namespace);
        if (strlen($namespace) > 0) {
            if(!$path){
                throw new \Exception('Invalid path');
            }
            $_path = realpath($path);
            if ($_path && is_dir($_path) && is_readable($_path)) {
                self::$namespaces[$namespace.'\\'] = $_path . DIRECTORY_SEPARATOR;
            } else {
                throw new \Exception('Namespace directory read error:' . $path);
            }
        } else {
            throw new \Exception('Invalid namespace:' . $namespace);
        }
    }   
    
    public static function registerNamespaces($ar) {
        if (is_array($ar)) {
            foreach ($ar as $k => $v) {
                self::registerNamespace($k, $v);
            }
        } else {
            throw new \Exception('Invalid namespaces');
        }
    }
    
    
    public static function getNamespaces() {
        return self::$namespaces;
    }

    public static function removeNamespace($namespace) {
        unset(self::$namespaces[$namespace]);
    }

    public static function clearNamespaces() {
        self::$namespaces = array();
    }

}
 
Ок добре, сега още един въпрос - как да го подкарам с обикновено apache.

Копирам целия проект в htdocs и го отварям така - http://localhost:8080/SymphonyTest/web/ като SymfonyTest е името на проекта. Така тръгва.
Но ако сложа един htaccess

Код:
RewriteEngine On
RewriteRule (.*) web/$1
И го отворя така - http://localhost:8080/SymphonyTest/ дава 404...

А custom сървъра на symfony-то прави ли нещо различно от apache-то? Например да разпознава урл и да отваря файлове или дявол знае какво...
 
anonimen каза:
Ок добре, сега още един въпрос - как да го подкарам с обикновено apache.

Копирам целия проект в htdocs и го отварям така - http://localhost:8080/SymphonyTest/web/ като SymfonyTest е името на проекта. Така тръгва.
Но ако сложа един htaccess

Код:
RewriteEngine On
RewriteRule (.*) web/$1
И го отворя така - http://localhost:8080/SymphonyTest/ дава 404...
Ако се опитваш да подкараш кода на гатака за неймспейсовете в симфония няма смисъл. Реално той го писа за неговите уроци по MVC и го дадох като обуснение за инклудване на файловете. В неговият случай файла се добавя когато се прави инстанция на класът. :)
 
Не, не, под "го" имам предвид symfony проекта, не лоадъра. Не се опитвам да ги комбинирам :D

А иначе може ли един кратък пример как се ползва (лоадъра)?
 
Вчера @eLite написа как: http://web-tourist.net/forum/viewtopic.php?p=664629#664629
В случая на симфони, DocumentRoot ще бъде X:\......\web
 
anonimen каза:
Не, не, под "го" имам предвид symfony проекта, не лоадъра. Не се опитвам да ги комбинирам :D

А иначе може ли един кратък пример как се ползва (лоадъра)?
Само това е.
PHP:
\GF\Loader::registerNamespace('GF', dirname(__FILE__) . DIRECTORY_SEPARATOR);
        \GF\Loader::registerAutoLoad();
 
djman каза:
Вчера @eLite написа как: http://web-tourist.net/forum/viewtopic.php?p=664629#664629
В случая на симфони, DocumentRoot ще бъде X:\......\web
Успях да го подкарам, мерси :) Ще видя още какво мога да попитам...

дака, ако реша да отложа симфонито за по-късно ще пробвам и този loader, все още не съм сигурен с какво може да ми помогне :idea:
 
anonimen каза:
djman каза:
Вчера @eLite написа как: http://web-tourist.net/forum/viewtopic.php?p=664629#664629
В случая на симфони, DocumentRoot ще бъде X:\......\web
Успях да го подкарам, мерси :) Ще видя още какво мога да попитам...

дака, ако реша да отложа симфонито за по-късно ще пробвам и този loader, все още не съм сигурен с какво може да ми помогне :idea:

http://gatakka.eu/?p=1131
Ами да ти кажа честно на мен ми върши страшна работа. Естествено аз съм си го преработил и подобрил но базата е негова.
 

Back
Горе