This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/includes/kohana/modules/userguide/guide/nl/about.upgrading.md
2011-05-03 09:49:01 +10:00

12 KiB

Upgraden vanaf 2.3.x

De code van Kohana v3 werkt grotendeels anders dan Kohana 2.3, hier is een lijst van de meeste valkuilen en tips om succesvol te upgraden.

Naming conventies

In 2.x versies onderscheiden de verschillende soorten van classes (zoals controller, model, ...) zich met elkaar met behulp van achtervoegsels. Mappen in de model / controller mappen hadden geen invloed op de naam van de class.

In 3.0 werd aanpak geschrapt ten gunste van de Zend framework bestandssysteem conventies, waar de naam van de class het pad is naar de class zelf, gescheiden door een underscore in plaats van slashes (dus /some/class/file.php bekomt Some_Class_File). Zie de conventies documentatie voor meer informatie.

Input Library

De Input Library is verwijderd in 3.0, er wordt nu aanbevolen om gewoon $_GET en $_POST te gebruiken.

XSS Protectie

Als je invoer van gebruikers wilt filteren op XSS kan je [Security::xss_clean] gebruiken om:

$_POST['description'] = security::xss_clean($_POST['description']);

Je kan ook altijd [Security::xss_clean] gebruiken als filter met de [Validate] library:

$validation = new Validate($_POST);

$validate->filter('description', 'Security::xss_clean');

POST & GET

Eén van de grootste functies van de Input Library was als je probeerde een waarde uit een superglobale array te halen en deze bestond bestond niet, dan zou de Input Library een standaard waarde teruggeven dat je kon instellen:

$_GET = array();

// $id heeft de waarde 1 gekregen
$id = Input::instance()->get('id', 1);

$_GET['id'] = 25;

// $id heeft de waarde 25 gekregen
$id = Input::instance()->get('id', 1);

In 3.0 kan je deze functionaliteit nabootsen door [Arr::get] te gebruiken:

$_GET = array();

// $id heeft de waarde 1 gekregen
$id = Arr::get($_GET, 'id', 1);

$_GET['id'] = 42;

// $id heeft de waarde 42 gekregen
$id = Arr::get($_GET, 'id', 1);

ORM Library

Er zijn redelijk veel grote wijzingingen aangebracht in ORM sedert 2.3. Hier is een lijst met de meest voorkomende upgrade problemen.

Member variablen

Alle member variablen hebben nu een voorvoegsel gekregen met een underscore (_) en zijn niet langer bereikbaar via __get(). Nu moet je een functie aanroepen met de naam van de property zonder de underscore.

Bijvoorbeeld, in 2.3 had je loaded en in 3.x is dat nu _loaded en heb je nu toegang van buiten de class via $model->loaded().

Relaties

Als je in 2.3 de gerelateerde objecten van een model wilde herhalen, kon je dat zo doen:

foreach($model->{relation_name} as $relation)

Maar in 3.0 zal dit niet werken. In de 2.3 serie werden alle queries die gegenereerd werden met behulp van de Database Library gegeneeerd in een globale omgeving, wat betekent dat je niet kon proberen en maken van twee queries. Bijvoorbeeld:

TODO: GOED VOORBEELD!!!!

Deze query zou mislukken doordat de tweede, inner query alle voorwaarden zou overerven van de eerste, wat zou leiden tot het mislukken. In 3.0 is dit aangepast door iedere query te laten genereren in zijn eigen omgeving. Let wel dat sommige dingen hierdoor niet gaan werken zoals je verwacht. Bijvoorbeeld:

foreach(ORM::factory('user', 3)->where('post_date', '>', time() - (3600 * 24))->posts as $post)
{
	echo $post->title;
}

[!!] (Zie de Database tutorial voor de nieuwe query syntax)

In 2.3 zou je verwachten dat dit iterator teruggeeft van alle berichten van een gebruiker met id 3 met een post_date binnenin de 24 uren, maar in de plaats daarvan zal de WHERE conditie toegepast worden op het user-model en een Model_Post worden teruggevens met de joining conditities gespecifieerd.

Om hetzelfde effect te verkrijgen zoals in 2.3, moet je de structuur iets aanpassen:

foreach(ORM::factory('user', 3)->posts->where('post_date', '>', time() - (36000 * 24))->find_all() as $post)
{
	echo $post->title;
}

Dit is ook van toepassing op de has_one relaties:

// Niet correct
$user = ORM::factory('post', 42)->author;
// Correct
$user = ORM::factory('post', 42)->author->find();

Has and belongs to many relaties

In 2.3 kon je has_and_belongs_to_many relaties specifieren. In 3.0 is deze functionaliteit herschreven naar has_many through.

In het model definieer je een has_many relatie met een ander model maar dan voeg je nog een 'through' => 'table' attribuut aan toe, waar 'table' de naam is van de trough tabel. Bijvoorbeeld (in de context van posts<>categories):

$_has_many = array
(
	'categories' => 	array
						(
							'model' 	=> 'category', // The foreign model
							'through'	=> 'post_categories' // The joining table
						),
);

Als je Kohana hebt opgezet om een tabel voorvoegsel te gebruiken, dan hoef je geen zorgen te maken om dit voorvoegsel hier te gebruiken bij de tabelnaam.

Foreign keys

Als je in Kohana 2.x's ORM een foreign key wilde overschrijven moest je de relatie specificeren waaraan het toebehoorde, en de nieuwe foreign key instellen in de member variabele $foreign_keys.

In 3.0 moet je nu een foreign_key definiëren in de relatie-definitie, zoals hier:

Class Model_Post extends ORM
{
	$_belongs_to = 	array
					(
						'author' => array
									(
										'model' 		=> 'user',
										'foreign_key' 	=> 'user_id',
									),
					);
}

In dit voorbeeld zouden we een user_id veld moeten hebben in de tabel posts.

In has_many relaties is de far_key het veld in de trough tabel die linkt naar de foreign tabel en is de foreign key het veld in de trough tabel die "this" model's tabel linkt naar de trough table.

Stel je de volgende opstelleing voor: "Posts" hebben en behoren tot vele "Categories" via posts_sections ("Posts" have and belong to many "Categories" through posts_sections)

categories posts_sections posts
id section_id id
name post_id title
content
	Class Model_Post extends ORM
	{
		protected $_has_many = 	array(
									'sections' =>	array(
														'model' 	=> 'category',
														'through'	=> 'posts_sections',
														'far_key'	=> 'section_id',
													),
								);
	}
	
	Class Model_Category extends ORM
	{
		protected $_has_many = 	array (
									'posts'		=>	array(
														'model'			=> 'post',
														'through'		=> 'posts_sections',
														'foreign_key'	=> 'section_id',
													),
								);
	}

Uiteraard is de aliasing setup hier een beetje gek, onnodig, maar het is een goed voorbeeld om te tonen hoe het foreign/far key systeem werkt.

ORM Iterator

Het is ook best te melden dat ORM_Iterator nu herschreven is naar Database_Result.

Als je een array van ORM objecten met hun keys als index van de array wilt verkrijgen, moet je [Database_Result::as_array] gebruiken, bijvoorbeeld:

	$objects = ORM::factory('user')->find_all()->as_array('id');

Waar id de primary key is in de user tabel.

Router Library

In versie 2 was er een Router library die de main request afhandelde. Het liet je de basisroutes instellen in het config/routes.php bestand en het liet je toe om zelfgeschreven regex te gebruiken voor routes, maar het was niet echt flexibel als je iets radicaal wou veranderen.

Routes

Het routing systeem (nu wordt verwezen naar het request systeem) is een stuk flexibeler in 3.0. Routes zijn nu gedefinieerd in het boostrap bestand (application/bootstrap.php) en de de module's init.php (modules/module_name/init.php). Het is ook interessant te weten dat routes worden geëvalueerd in de volgorde dat ze worden gedefinieerd. In plaats daarvan specifieer je een patroon voor elke uri, je kan variabelen gebruiken om segmenten aan te duiden (zoals een controller, methode, id).

Bijvoorbeeld, in 2.x zouden deze regexes:

$config['([a-z]+)/?(\d+)/?([a-z]*)'] = '$1/$3/$1';

de uri controller/id/method linken aan controller/method/id. In 3.0 gebruik je dit:

Route::set('reversed','(<controller>(/<id>(/<action>)))')
		->defaults(array('controller' => 'posts', 'action' => 'index'));

[!!] Iedere uri moet een unieke naam hebben (in dit geval reversed), de reden hiervoor wordt nader uitgelegd in de url tutorial.

Slashes geven dynamische secties weer die zouden moeten worden ontleed in variabelen. Haakjes geven optionele secties aan die niet vereist zijn. Als je met een route enkel uris die beginnen met admin wilt aanspreken kan je dit gebruiken:

Rouse::set('admin', 'admin(/<controller>(/<id>(/<action>)))');

En als je wilt een dat een gebruiker een controller specificeert:

Route::set('admin', 'admin/<controller>(/<id>(/<action>))');

Kohana maakt geen gebruik van default defaults. Als je wilt dat Kohana ervan uit gaat dat de standaard actie 'index' is, dan moet je dat ook zo instellen! Dit kan je doen via [Route::defaults]. Als je zelfgeschreven regex wilt gebruiken voor uri segmenten dan moet je ene array met segment => regex meegeven, bijvoorbeeld:

Route::set('reversed', '(<controller>(/<id>(/<action>)))', array('id' => '[a-z_]+'))
		->defaults(array('controller' => 'posts', 'action' => 'index'))

Dit zou de id waarde forceren om te bestaan uit kleine letters van a tot z en underscores.

Actions

Nog één ding dat belangrijk is om te melden, is dat methoden in een controller die toegankelijk moeten zijn via een url nu "actions" worden genoemd. Ze krijgen een voorvoegsel 'action_'. Bijvoorbeeld in het bovenstaande voorbeeld, als de user de url admin/posts/1/edit aanroept dan is de actie edit maar is de methode die wordt aangeroepen in de controller action_edit. Zie de url tutorial voor meer informatie.

Sessies

De volgende methoden worden niet meer ondersteund: Session::set_flash(), Session::keep_flash() or Session::expire_flash(), inde plaats daarvan gebruik je nu [Session::get_once].

URL Helper

Er zijn maar een aantal kleinere dingen veranderd in de url helper. url::redirect() werd vervangen door $this->request->redirect() (binnenin controllers) en Request::instance()->redirect().

url::current werd nu vervangen door $this->request->uri()

Valid / Validation

Deze twee classes zijn nu samengevoegd in één enkele class met de naam Validate.

De syntax om arrays te valideren is een klein beetje gewijzigd:

$validate = new Validate($_POST);

// Pas een filter toe op alle waarden in de array
$validate->filter(TRUE, 'trim');

// Om enkel rules te definiëren gebruik je rule()
$validate
	->rule('field', 'not_empty')
	->rule('field', 'matches', array('another_field'));

// Om meerdere rules te definiëren voor een veld gebruik je rules(), je geeft een array mee met `passing an array of rules => params als tweede argument
$validate->rules('field', 	array(
								'not_empty' => NULL,
								'matches'	=> array('another_field')
							));

De 'required' rule is ook verandert van naam. Nu wordt voor de duidelijkheid 'not_empty' gebruikt.

View Library

Er zijn enkele kleine wijzigingen aangebracht aan de View library die de moeite zijn om even te melden.

In 2.3 werden views gegenereerd binnenin de scope van de controller, dit liet je toe om $this te gebruiken als referentie naar de controller vanuit je view, dit is verandert in 3.0. Views worden nu gegenereerd in een lege scope. Als je nog $this wilt gebruiken in je view, moet je een referentie leggen via [View::bind]: $view->bind('this', $this).

Het moet wel gezegd worden dat dit een erg slechte manier van werken is omdat het je view koppelt aan de controller wat tegenhoud om deze view opnieuw te gebruiken. Het is aan te raden om de noodzakelijke variabelen voor je view als volgt door te sturen:

$view = View::factory('my/view');

$view->variable = $this->property;

// OF als je dit wilt "chainen"

$view
	->set('variable', $this->property)
	->set('another_variable', 42);
	
// NIET aangeraden
$view->bind('this', $this);

Omdat de view gegenereerd wordt in een lege scope, is Controller::_kohana_load_view nu overtollig. Als je de view moet aanpassen vooraleer het word gegenereerd (bijvoorbeeld om een menu te gereneren over de gehele site) kan je [Controller::after] gebruiken.

Class Controller_Hello extends Controller_Template
{
	function after()
	{
		$this->template->menu = '...';
		
		return parent::after();
	}
}