Clicky

Skocz do zawartości


Zdjęcie
- - - - -

[K2] Komponenty a'la Symfony - include_component()

33 odpowiedzi w tym temacie

  • Zaloguj się, aby dodać odpowiedź

#26 crashu

crashu

    Początkujący

  • Użytkownik
  • Pip
  • 6 postów

Napisano 06 marzec 2009 - 16:59

nie każdy musi podążać ta samą scieżka do celu, przedstawiłem tylko inne rozwiazanie

#27 nrm

nrm

    webmastah

  • Admin
  • 1106 postów
  • Skąd:Katowice

Napisano 06 marzec 2009 - 22:16

Każdy robi co mu się podoba. Nie mniej przy takich rozwiązaniach trzeba dodawać, że jest to nieprawidłowe podejście i należy go unikać.

#28 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 07 marzec 2009 - 11:48

Nie mniej przy takich rozwiązaniach trzeba dodawać, że jest to nieprawidłowe podejście i należy go unikać.

Rozumiem, że nawiązujesz do samej idei komponentów. Zgadzam się połowicznie. Nie jest to prawidłowe podejście - fakt. Ale czy należy go unikać? Tu bym się kłócił. Dla mnie jest to bardzo wygodne rozwiązanie, które często stosuję. Całą logikę dla danej sekcji strony zamykam w niewielkim pliku, nie muszę babrać się z kontrolerami. Równie dobrze możnaby się doczepić do tego, że Kohana nagminnie wykorzystuje singletony, co również nie jest powszechnie używane za dobry nawyk. Ja jednak nie potrzebuję narzędzia, które będzie zgodne z wszystkimi magicznymi ideami OOP (np. ZF), które do wykonania jakiejś prostej operacji będzie musiało załadować 5 klas abstrakcyjnych oraz 10 interfejsów. Zdecydowanie wyżej stawiam prostotę, szybkość działania oraz wygodę użytkowania :)
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#29 Zepco

Zepco

    Senior Mastah

  • Moderator
  • 1583 postów
  • Skąd:Kielce

Napisano 07 marzec 2009 - 12:01

@phppion, nrm miał chyba na myśli grzebanie w "sercu" Kohany. Wolnoć Tomku w swoim frameworku. ;) Jak Ci się podoba modyfikowanie plików systemu, to proszę bardzo. Dla większości jednak jest to teren, na który wstęp jest tylko do odczytu, bo zapis często prowadzi do chaosu.
Znakomitą większość rozszerzeń funkcjonalności Kohany można zrobić nie naruszając jej struktury, do tego służy kaskadowy system plików, dziedziczenie oraz haki.

OŚWIADCZENIE: Ja, niżej podpisany, świadomy wszystkich konsekwencji tego posta postanawiam go dopuścić do użytku publicznego, albowiem bo gdyż aczkolwiek uważam, że nie wyrządzi on (znaczy: post) krzywdy nikomu innemu niźli mnie samemu (czyli autorowi posta).
-- Zepco --


#30 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 07 marzec 2009 - 13:19

A to sory  :-*
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#31 nrm

nrm

    webmastah

  • Admin
  • 1106 postów
  • Skąd:Katowice

Napisano 07 marzec 2009 - 16:01

j.w. chodzi o /system/

#32 Zepco

Zepco

    Senior Mastah

  • Moderator
  • 1583 postów
  • Skąd:Kielce

Napisano 08 marzec 2009 - 00:14

Jak mówiłem bez grzebania w system też się da zrobić :D
Wystarczy utworzyć hak component_loader.php
<?php defined('SYSPATH') OR die('No direct access allowed.');

class Component_Loader
{

public static function init()
{
spl_autoload_register(array('Component_Loader', 'auto_load'));
}

static public function auto_load($class)
{
if (class_exists($class, FALSE))
return TRUE;

if (($suffix = strrpos($class, '_')) > 0)
{
// Find the class suffix
$suffix = substr($class, $suffix + 1);
}
else
{
// No suffix
$suffix = FALSE;
}

if ($suffix === 'Component')
{
$type = 'components';
$file = substr($class, 0, -10);
}

if ($filename = Kohana::find_file($type, $file))
{
// Load the class
require $filename;
}
else
{
// The class could not be found
return FALSE;
}
}
}

Event::add('system.ready', array('Component_Loader', 'init'));


Teraz możecie używać
Moj_Component::jakas_funkcja_statyczna();
Ewentualnie
new Moj_Component;
Zależy kto co lubi.
Oczywiście zachowany jest kaskadowy system plików. A komponenty są przechowywane w podkatalogu 'components', czyli np. application/components albo modules/moj_modul/components.


-- edit --
Stworzyłem własną małą modyfikację i zamknąłem to wszystko w module, oto on
http://zepco.pl/kohana/components.zip

Wywołanie metody test komponentu user wygląda następująco:

1. Component::factory('user')->test();
2. Component::factory('user', 'test');
3. Component::factory('user', 'test', 'parametry');


OŚWIADCZENIE: Ja, niżej podpisany, świadomy wszystkich konsekwencji tego posta postanawiam go dopuścić do użytku publicznego, albowiem bo gdyż aczkolwiek uważam, że nie wyrządzi on (znaczy: post) krzywdy nikomu innemu niźli mnie samemu (czyli autorowi posta).
-- Zepco --


#33 phpion

phpion

    Senior Mastah

  • Użytkownik
  • PipPipPip
  • 774 postów
  • Skąd:Sosnowiec, Dąbrowa Górnicza

Napisano 08 marzec 2009 - 10:53

:) Fajna modyfikacja, nie wiem czy się na nią nie przestawię. Moja idea z symfony::include_component wzięła się z samego Symfony, gdzie komponent ładuje się poprzez include_component(). Zachowałem takie same parametry metody. Po prostu chciałem uzyskać jak najbliższy odpowiednik tej funkcjonalności.
Notifero - Technologie Informatyczne | Warsztat: Kohana 3.x/2.x + PostgreSQL/MySQL | Programista Kohana

#34 Adam16

Adam16

    Początkujący

  • Użytkownik
  • Pip
  • 18 postów
  • Skąd:Niemcy

Napisano 27 kwiecień 2009 - 10:47

Znalezione im Forum: http://forum.kohanap...0&page=1#Item_0

An extended and 2.3-compatible Dispatch library, based on dlib's class

<?php
/**
* \brief Wraps a Controller object and allows to grab the output of its methods.
*
* This class is tipically used to compose a view with the result of the execution of multiple controllers.
* One controller, the "composite" controller, uses the "factory" method to instantiate components and
* the "method" method to generate the subviews, assigning them to the variables of a template view.
*
* \note This class is based on dlib's Dispatch library, extended and adapted to KohanaPHP v2.3 routing/filesystem.
*/
class Component {

/// When a component is instantiated, the original Router static properties are backed up here.
protected $router_state_backup;

/// The component controller instance
protected $controller;
/// The component controller name as it appears in Router::$controller
protected $router_controller;

/**
* Instantiates the specified controller, optionally replacing $_GET and $_POST contents before calling the component constructor.
* \note The original $_GET and $_POST array are restored as soon as the component is instantiated.
* @param $controller The name of the controller class to be instantiated, lowercase, without the "Controller_" prefix.
* @param $get The array that should replace $_GET.
* @param $post The array that should replace $_POST.
* @return A new Component object.
*/
public static function factory($controller, $get = null, $post = null) {

// Backup router state
$old_router = array();
$old_router['current_route'] = Router::$current_route;
$old_router['current_uri'] = Router::$current_uri;
$old_router['query_string'] = Router::$query_string;
$old_router['complete_uri'] = Router::$complete_uri;
$old_router['controller'] = Router::$controller;
$old_router['method'] = Router::$method;
$old_router['arguments'] = Router::$arguments;

// The following three variables could be determined by running Router code and passing an url, but:
// 1) The performance penalty would be high
// 1) It's not a good idea for a controller to alter its behaviour depending on them, anyway
//Router::$current_route = '';
//Router::$current_uri = '';
//Router::$complete_uri = '';

Router::$controller = $controller;

// We don't know these yet
Router::$method = '';
Router::$arguments = array();

// If get or post parameters are passed, alter $_GET, $_POST and Router::$query_string accordingly
// NOTE: Should we alter $_SERVER['QUERY_STRING'] too?
if ($get !== null) {
$old_get = $_GET;
$_GET = $get;
Router::$query_string = '?'.http_build_query($get);
}
if ($post !== null) {
$old_post = $_POST;
$_POST = $post;
}

// If class is not defined already, load controller file
$controller_class = 'Controller_'.ucfirst($controller);
if (!class_exists($controller_class, false)) {
$controller_file = str_replace('_', '/', strtolower($controller_class));

// If the component file doesn't exist, fire exception
$filepath = Kohana::find_file('classes', $controller_file, true);

// Include the Controller file
require_once $filepath;
}

// Run system.pre_controller
Event::run('dispatch.pre_controller');

// Initialize the controller
$controller_instance = new $controller_class;

// Run system.post_controller_constructor
Event::run('dispatch.post_controller_constructor');

// Revert $_GET and $_POST changes
if ($get !== null) $_GET = $old_get;
if ($post !== null) $_POST = $old_post;

// Revert Router state
Router::$current_route = $old_router['current_route'];
Router::$current_uri = $old_router['current_uri'];
Router::$query_string = $old_router['query_string'];
Router::$complete_uri = $old_router['complete_uri'];
Router::$controller = $old_router['controller'];
Router::$method = $old_router['method'];
Router::$arguments = $old_router['arguments'];

return new Component($controller_instance, $controller, $old_router);
}

private function __construct(Controller $controller_instance, $router_controller, $router_state_backup) {
$this->controller = $controller_instance;
$this->router_controller = $router_controller;
$this->router_state_backup = $router_state_backup;
}


/// Magic method: returns the $key property of the wrapped Controller
public function __get($key) {
return $this->controller->$key;
}

/// Magic method: sets the $key property of the wrapped Controller
public function __set($key,$value) {
$this->controller->$key = $value;
}

/// Magic method: checks if the $key property of the wrapped Controller is set.
public function __isset($key) {
return isset($this->controller->$key);
}

/// Calls __toString() on the wrapped Controller
public function __toString() {
return $this->render();
}

/// Calls __toString() on the wrapped Controller
public function render() {
return (string) $this->controller;
}

/// Magic method: invoke method $name (with arguments $arguments) of the wrapped Controller.
/// \note This method is slow. Use the "method" method directly if you can.
public function __call($name, $arguments = null) {
return $this->method($name, $arguments);
}

/**
* Invokes method $method (with arguments $arguments) of the wrapped Controller, optionally replacing
* $_GET and $_POST contents before making the call.
* @param $method The name of the method to invoke.
* @param $arguments The arguments to pass.
* @param $get The array that should replace $_GET.
* @param $post The array that should replace $_POST.
* @param $capture If true (default) any output generated by the method is captured and returned,
*        otherwise the method's return value itself is returned.
* @return The called method's output or its return value, depending on $capture.
*/
public function method($method, $arguments = null, $get = null, $post = null, $capture = true) {

// If method does not exist, call the "__call" magic method
// This can be made faster by catching an exception in the switch statement below
if (!method_exists($this->controller, $method)) {
$arguments = array($method, $arguments);
$method = '__call';
}

// Change Router state to reflect call
//Router::$current_route = '';
//Router::$current_uri = '';
//Router::$complete_uri = '';
Router::$controller = $this->router_controller;
Router::$method = $method;
if ($arguments === null) Router::$arguments = array();
else Router::$arguments = $arguments;

// If get or post parameters are passed, alter $_GET, $_POST and Router::$query_string accordingly
// NOTE: Should we alter $_SERVER['QUERY_STRING'] too?
if ($get !== null) {
$old_get = $_GET;
$_GET = $get;
Router::$query_string = '?'.http_build_query($get);
}
if ($post !== null) {
$old_post = $_POST;
$_POST = $post;
}

// Start output capture
if ($capture) {
ob_implicit_flush(0);
ob_start();
}

if (is_string($arguments)) $arguments = array($arguments);

// Invoke method
switch (count($arguments)) {
case 1:
$result=$this->controller->$method($arguments[0]);
break;
case 2:
$result=$this->controller->$method($arguments[0], $arguments[1]);
break;
case 3:
$result=$this->controller->$method($arguments[0], $arguments[1], $arguments[2]);
break;
case 4:
$result=$this->controller->$method($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
break;
default:
// Resort to using call_user_func_array for many arguments (slower)
$result=call_user_func_array(array($this->controller, $method), $arguments);
break;
}

// Run system.post_controller
Event::run('dispatch.post_controller');

// Stop output capture
if ($capture) {
$result = ob_get_contents();
ob_end_clean();
}

// Revert $_GET and $_POST changes
if ($get !== null) $_GET = $old_get;
if ($post !== null) $_POST = $old_post;

// Revert Router state
//Router::$current_route = $this->router_state_backup['current_route'];
//Router::$current_uri = $this->router_state_backup['current_uri'];
//Router::$complete_uri = $this->router_state_backup['complete_uri'];
Router::$query_string = $this->router_state_backup['query_string'];
Router::$controller = $this->router_state_backup['controller'];
Router::$method = $this->router_state_backup['method'];
Router::$arguments = $this->router_state_backup['arguments'];

return $result;
}
}

System komputerowy jest tylko na tyle bezpieczny i dobry
jak jego Administrator ktory go obsługuje.

Jak dobrze jednak ten Administrator swoje umiejetniosci
wykorzystac moze, jest juz zapisane w tym systemie.




Użytkownicy przeglądający ten temat: 0

0 użytkowników, 0 gości, 0 anonimowych