CodeIgniter is een eenvoudig en krachtig open source framework voor webtoepassingen voor PHP. Vandaag zullen we enkele kernhacks doen om dit framework te veranderen en de functionaliteit ervan te verbeteren. Tijdens dit proces krijgt u een beter begrip van de fijne kneepjes van CodeIgniter.
Aan de linkerkant ziet u de normale manier om een model in CodeIgniter te laden vanuit een controller. Na deze hack kunnen we objecten direct maken. De code is schoner en uw IDE kan de objecttypen herkennen. Hierdoor kunnen IDE-functies zoals automatisch aanvullen of een voorbeeld van de documentatie worden gebruikt.
Er zijn nog twee neveneffecten van deze hack. Ten eerste hoeft u de Model-klasse niet langer uit te breiden:
En u hoeft niet langer een require_once-oproep toe te voegen voordat u de overerving van de modelklasse uitvoert.
Het enige wat we moeten doen is een autoloader-functie in PHP 5-stijl toevoegen.
Voeg deze code toe aan de onderkant van system / application / config / config.php:
Als u deze hack ook voor controllers wilt toepassen, kunt u in plaats daarvan deze code gebruiken:
Telkens wanneer u probeert een klasse te gebruiken die niet is gedefinieerd, wordt deze __autoloadfunctie eerst aangeroepen. Het zorgt voor het laden van het klassenbestand.
Normaal gesproken kunt u niet dezelfde klassenaam hebben voor een model en een controller. Laten we zeggen dat je een modelnaam hebt gemaakt Post:
class Post breidt Model // ... uit
U kunt nu geen URL zoals deze hebben:
http://www.mysite.com/post/display/13
De reden is dat je ook een klasse Controller moet hebben met de naam 'Plaatsen'. Het maken van een dergelijke klasse zou resulteren in een fatale PHP-fout.
Maar met deze hack wordt het mogelijk. En de controller voor die URL ziet er als volgt uit:
// application / controllers / post.php class Post_controller verlengt Controller // ...
Let op het achtervoegsel '_controller'.
Om dit probleem te omzeilen, voegen de meeste mensen normaal het suffix '_model' toe aan de klassennamen Model (bijvoorbeeld Post_model). Modelobjecten worden overal in de applicatie gemaakt en ernaar verwezen, dus het lijkt misschien een beetje gek om al deze namen met '_model' rond te laten zweven. Ik denk dat het beter is om een achtervoegsel aan de controllers toe te voegen, omdat ze bijna nooit worden verwezen door hun klassenamen in je code.
Eerst moeten we de klasse Router uitbreiden. Maak dit bestand aan: "application / libraries / MY_Router.php"
class MY_Router verlengt CI_Router var $ suffix = '_controller'; function MY_Router () parent :: CI_Router (); functie set_class ($ class) $ this-> class = $ class. $ This-> achtervoegsel; function controller_name () if (strstr ($ this-> class, $ this-> suffix)) return str_replace ($ this-> suffix, ", $ this-> class); else return $ this-> klasse;
Bewerk nu "system / codeigniter / CodeIgniter.php" regel 153:
if (! file_exists (APPPATH.'controllers /'.$ RTR-> fetch_directory (). $ RTR-> controller_name (). EXT))
Hetzelfde bestand, regel 158:
omvatten (APPPATH.'controllers /'.$ RTR-> fetch_directory () $ RTR-> controller_name () EXT..);
Bewerk vervolgens: "system / libraries / Profiler.php", regel 323:
$ output. = ""$ This-> CI-> router-> controller_name (). "/". $ This-> CI-> router-> fetch_method ()."";
Dat is alles. Houd er rekening mee dat je met deze hack het achtervoegsel '_controller' op alle klassennamen van je controller moet zetten. Maar niet in de bestandsnamen of de URL's.
CodeIgniter heeft een mooie Form_validation-klasse. Het wordt geleverd met verschillende validatieregels:
Deze zijn handig, maar er ontbreekt een belangrijke in deze lijst: om te controleren op unieke waarden. De meeste gebruikersregistratieformulieren moeten bijvoorbeeld controleren of de gebruikersnaam nog niet is gebruikt, of dat het e-mailadres zich nog niet in het systeem bevindt.
Met deze hack kunt u deze validatieregel eenvoudig toevoegen aan uw handler voor het indienen van formulieren:
$ this-> form_validation-> set_rules ('gebruikersnaam', 'Username', 'required | alpha_numeric | min_length [6] | unique [User.username]');
Let op het laatste deel dat zegt: "unique [User.username]." Deze nieuwe validatieregel wordt gewoon "uniek" genoemd en neemt een parameter tussen de vierkante haken, "tablename.fieldname". Dus zal het de "gebruikersnaam" kolom van de "Gebruiker" tabel controleren om er zeker van te zijn dat de ingediende waarde nog niet bestaat.
Op dezelfde manier kunt u controleren op dubbele e-mails:
$ this-> form_validation-> set_rules ('email', 'E-mail', 'required | valid_email | unique [User.email]');
En uw applicatie kan reageren met de juiste foutmeldingen:
Dit kan meer als een extensie worden beschouwd dan als een hack. Desondanks gaan we een belangrijke CodeIgniter-bibliotheek innemen en verbeteren.
Maken: "application / libraries / MY_Form_validation.php"
class MY_Form_validation breidt CI_Form_validation uit function unique ($ value, $ params) $ CI = & get_instance (); $ CI-> load-> databank (); $ CI-> form_validation-> set_message ('unique', 'De% s is al in gebruik.'); lijst ($ tabel, $ veld) = ontploffen (".", $ params, 2); $ query = $ CI-> db-> selecteer ($ field) -> from ($ table) -> where ($ field, $ value) -> limit (1) -> get (); if ($ query-> row ()) return false; else return true;
Nu kunt u de unieke validatieregel gebruiken.
Zoals de titel al aangeeft, is ons doel om CodeIgniter-toepassingen vanaf de opdrachtregel te kunnen uitvoeren. Dit is nodig voor het bouwen van cron-taken of voor het uitvoeren van meer intensieve bewerkingen, zodat u niet over de resourcebeperkingen van een webscript beschikt, zoals de maximale uitvoeringstijd.
Zo ziet het eruit op mijn lokale Windows-computer:
De bovenstaande code zou hetzelfde zijn als het aanroepen van deze URL:
http://www.mysite.com/hello/world/foo
Maak een "cli.php" -bestand aan de hoofdmap van uw CodeIgniter-map:
if (isset ($ _ SERVER ['REMOTE_ADDR'])) die ('Alleen commandoregel!'); set_time_limit (0); $ _SERVER ['PATH_INFO'] = $ _SERVER ['REQUEST_URI'] = $ argv [1]; vereisen dirname (__ FILE__). '/Index.php';
Als u in een Linux-omgeving bent en dit script zelf uitvoerbaar wilt maken, kunt u dit als de eerste regel in cli.php toevoegen:
#! / Usr / bin / php
Als u wilt dat een specifieke controller alleen een opdrachtregel is, kunt u weboproepen blokkeren bij de constructor van de controller:
class Hello breidt Controller uit function __construct () if (isset ($ _ SERVER ['REMOTE_ADDR'])) die ('Command Line Only!'); parent :: Controller (); // ...
Doctrine is een populaire Object Relational Mapper voor PHP. Door het toe te voegen aan CodeIgniter, kunt u een zeer krachtige modellaag in uw raamwerk hebben.
Het installeren van Doctrine is niet per se "hacky", omdat we het gewoon als een plug-in kunnen toevoegen. Als uw modellessen echter eenmaal zijn toegevoegd, moeten ze de basisklassen van de Doctrine uitbreiden in plaats van de klasse CodeIgniter Model. Dit zal de manier waarop de Model-laag werkt in het raamwerk volledig veranderen. De objecten die u maakt, hebben databasepersistentie en kunnen ook databaserelaties hebben met andere objecten.
Volg deze stappen:
// system / application / plugins / doctrine_pi.php // laad Doctrine library require_once APPPATH. '/ plugins / doctrine / lib / Doctrine.php'; // laad databaseconfiguratie vanuit CodeIgniter vereist_op APPPATH. '/ config / database.php'; // hierdoor kan Doctrine Modellessen automatisch laden spl_autoload_register (array ('Doctrine', 'autoload')); // we laden onze databaseverbindingen in Doctrine_Manager // deze lus laat ons toe om meerdere verbindingen later te gebruiken voor elk ($ db als $ connection_name => $ db_values) // eerst moeten we converteren naar dsn format $ dsn = $ db [$ connection_name] ['dbdriver']. ': //'. $ db [$ connection_name] ['gebruikersnaam']. ':'. $ Db [$ connection_name] [ 'password']. '@'. $ db [$ connection_name] ['hostname']. '/'. $ Db [$ connection_name] [ 'databank']; Doctrine_Manager :: aansluiting ($ dsn, $ connection_name); // CodeIgniter's Modelklasse moet worden geladen require_once BASEPATH. '/ Libraries / Model.php'; // vertellen van Doctrine waar onze modellen zich bevinden Doctrine :: loadModels (APPPATH. '/ models');
Bewerk vervolgens "application / config / autoload.php" om deze Doctrine-plug-in te autoload
$ autoload ['plugin'] = array ('doctrine');
Zorg er ook voor dat u uw databaseconfiguratie hebt in "application / config / database.php".
Dat is alles. U kunt nu Doctrine Modellen maken binnen uw CodeIgniter-toepassing. Lees mijn tutorials over dit onderwerp voor meer informatie.
Met deze hack kunt u meerdere sites uitvoeren vanaf één installatie van CodeIgniter. Elke website heeft zijn eigen toepassingsmap, maar ze zullen allemaal dezelfde systeemmap delen.
Installeer CodeIgniter overal op de server. Het hoeft niet onder een websitemap te staan. Haal de applicatiemap vervolgens uit de systeemmap. En maak er extra kopieën van, zoals te zien is in bovenstaande afbeelding, voor elke website die u wilt gebruiken. U kunt die toepassingsmappen overal plaatsen, zoals onder elke afzonderlijke websitemappen.
Kopieer nu het index.php-bestand naar de hoofdmap van elke websitemap en bewerk het als volgt:
Zet op regel 26 het volledige pad naar de systeemmap:
$ system_folder = dirname (__ FILE__). '... / codeigniter / system';
Zet bij regel 43 het volledige pad naar de applicatiemap:
$ application_folder = dirname (__ FILE__). '... / application_site1';
U kunt nu onafhankelijke websites gebruiken met afzonderlijke toepassingsmappen, maar dezelfde systeemmap delen.
Er is een vergelijkbare implementatie in de gebruikershandleiding van CodeIgniter die u ook kunt lezen.
Wanneer u de Upload-bibliotheek in CodeIgniter gebruikt, moet u opgeven welke bestandstypes zijn toegestaan.
$ This-> load-> library ( 'uploaden'); $ This-> upload-> set_allowed_types ( 'jpg | jpeg | gif | png | zip');
Als u geen bestandstypes opgeeft, ontvangt u een foutmelding van CodeIgniter: "U hebt geen toegestane bestandstypen opgegeven."
Standaard is het dus niet mogelijk om alle bestandstypen te uploaden. We moeten een kleine hack doen om deze beperking te omzeilen. Daarna kunnen we alle bestandstypen toestaan door deze in te stellen op '*'.
$ This-> load-> library ( 'uploaden'); $ This-> upload-> set_allowed_types ( '*');
Voor deze hack gaan we het gedrag van de Upload-klasse aanpassen.
Maak een bestand aan: application / libraries / My_Upload.php
klasse MY_Upload breidt CI_Upload uit function is_allowed_filetype () if (count ($ this-> allowed_types) == 0 OF! is_array ($ this-> allowed_types)) $ this-> set_error ('upload_no_file_types'); keer terug FALSE; if (in_array ("*", $ this-> allowed_types)) return TRUE; $ image_types = array ('gif', 'jpg', 'jpeg', 'png', 'jpe'); foreach ($ this-> allowed_types as $ val) $ mime = $ this-> mimes_types (strtolower ($ val)); // Afbeeldingen krijgen wat extra controles als (in_array ($ val, $ image_types)) if (getimagesize ($ this-> file_temp) === FALSE) return FALSE; if (is_array ($ mime)) if (in_array ($ this-> file_type, $ mime, TRUE)) return TRUE; else if ($ mime == $ this-> file_type) return TRUE; return FALSE;
Ik hoop dat sommige hiervan nuttig voor je zijn. Als dat niet het geval is, zijn ze nog steeds interessant om te weten en kunnen ze u helpen meer te weten te komen over de interne werking van een framework en enkele kernwoorden van PHP..
Als je andere coole hacks of aanpassingen kent, laat het ons dan weten in de comments. Dank je!
Klaar om je vaardigheden naar een hoger niveau te tillen, en te profiteren van je scripts en componenten? Bekijk onze zustermarktplaats, CodeCanyon.