Tobias Ratschiller. Till Gerken. With contributions by. Zend Technologies, LTD. Zeev Suraski. Andi Gutmans. Web Application. Development with PHP PDF | 35+ minutes read | Quality of Web-applications plays major role in its success. And the high quality Web-application is really possible by following high . Title Introduction to Web Applications Development; Author(s) Carles Mateu la Universitat Oberta de Catalunya (February, ); eBook PDF, Pages,
|Language:||English, Spanish, Indonesian|
|Genre:||Politics & Laws|
|Distribution:||Free* [*Sign up for free]|
This page eBook "Introduction to Web Applications Development", starts with an introduction to the internet, including a brief history of the. This book is for the professional web developer who already understands HTML, CSS, and CMS other WordPre Learning Web Development with Bootstrap. lightorevanmo.gq Simply put, Web Applications are dynamic web sites combined with server side.
Sign up to our emails for regular updates, bespoke offers, exclusive discounts and great free content. Log in. My Account. Log in to your account. Not yet a member? Register for an account and access leading-edge content on emerging technologies. Register now. Packt Logo. My Collection. Deal of the Day Understand the fundamentals of C programming and get started with coding from ground up in an engaging and practical manner.
Sign up here to get these deals straight to your inbox. Find Ebooks and Videos by Technology Android. Packt Hub Technology news, analysis, and tutorials from Packt. Insights Tutorials. News Become a contributor. Categories Web development Programming Data Security. Subscription Go to Subscription.
Subtotal 0. Title added to cart. Subscription About Subscription Pricing Login. Features Free Trial. Search for eBooks and Videos. Download your FREE copy of 'Practical Web Development' Web development has grown to become vital in shaping how humans interact, work, learn, and consume. When you sign up you'll get offers relevant to you, exclusive discounts on our hottest titles, and leading edge free content.
All Rights Reserved. Contact Us. The ile, assuming you did not modify anything else and nothing has changed in the default Codeception installation since this chapter was written, should look like the following: AcceptanceTester modules: As we change the coniguration, we should rebuild the Codeception harness.
Here is the command to do it: The real executable is in the. If you run the tests now: It'll either be a error or error, depending on the version of Apache used, or maybe something else if you are using a different web server. Anyway, the root of the problem is simple, that is, we need an index.
For example, if your web server is Apache, it'll be the web folder's path that you put into the DocumentRoot directory. Given that, just put the following content as the index. Our CRM Yes, just a seven-character text ile.
After all, that's everything our acceptance test expected, right? Then we run the tests: Now we need to allow ourselves to use Yii 2 in our project. An easy way to do this is just to write the full, end-to-end test, which describes our desired functionality. Introducing the Yii framework into our application Now that we have the entire supporting infrastructure we need to begin working with, let's return to our irst feature we deined at the design stage and deine the acceptance test for it.
We don't have any way of direct access to the database or, worse, ilesystem around the application. So, to test a query for some data in the database, this data should be inserted into the database irst. And it should be done using the UI. Here are the resulting test steps: Open the UI for adding customer data to the database.
Add customer 1 to the database. You should see the Customer List UI with one record. Add customer 2 to the database. You should see the Customer List UI with two records now. Open the UI to query customer data by the phone number.
Query using the phone number of customer 1. You should see the query results UI with data for customer 1 but not for customer 2. So, this test forces us to have three user-interface pages: That's part of why it's called "end-to-end" testing.
Translated to the Codeception acceptance test suite, the procedure just described will look like this: This is our goal for the current chapter. Let's go over the not-so-obvious things in this test script. First, we broke down the scenario into two logical parts and made two different subclasses of AcceptanceTester to stress this distinction.
Just hit Enter there without writing anything to tell it that you want to start afresh. This helper is used to support the StepObject pattern see http: Of course, it's a lot more natural to reason about the subclasses of AcceptanceTester as having different roles than having some abstract containers of steps. However, if we forcefully rename the generated classes, removing the unnecessary sufix, we would lose the auto-loading ability that Codeception automatically provides us with, so we'll just tolerate it.
Now, let's deine the steps mentioned in the test scenario. Almost all of these high-level steps will just be the containers of the more low-level steps built-in with the acceptance tester shipped with Codeception.
First, we will see the CRM operator steps.
Such placeholder data can be generated in any way. We'll be using the amazing Faker library https: However, we'll look into that a bit later. But what ields should be there?
Let's return to our Customer aggregate and see what parts of it we crucially need to fulill our test scenario: Of course, we don't take into account the Contract aggregate at all.
For the task to be any "interesting", we include all the unique parts of the customer: Name, Birthday, and Notes. Do remember that Name is a structure and not just a line of text like Notes. Please pay attention to the naming of form ields; it's not arbitrary and corresponds to our future database schema and the Yii 2 model's coniguration. Have a look at the following table: We cannot implement features until we have a basic test done for it, and our test does not explicitly check the ability to enter several phone numbers yet.
First of all, let's bring the Faker library into our project: With all these methods deined in the CRMOperatorSteps class, we now have the irst half of our test case completed which means runnable. Let's get done with the test steps for a CRM user, who'll do the querying. First, the obvious one is as follows: Lastly, here are our assertions: Quite an important question is why we don't check for the customer data being shown in the Customer List UI after each addition of a new customer.
After we query for the phone number, we end up in the same Customer List UI after all. Well, for now, the reasoning is dead simple: Also, the existence of some assertions halfway through the test case would violate the Single Assertion principle explained in detail in Clean Code, Robert Martin, Prentice Hall.
However, as this is the end-to- end acceptance test, doing this is probably not such a bad thing. Anyway, nothing prevents us from extending this test further again, it's an acceptance test imitating the behavior of a real user , but for now, let's stick with this simple scenario.
If you run the completed test scenario now, you should get the following error message: Scenario Steps: We have inally arrived at the Yii 2 installation procedure. First of all, you need to declare Yii 2 as a dependency of your application. Either add the required require line for Yii 2 manually in the composer. Checking the requirements Yii 2 includes an important feature, which is a built-in requirement checker.
When you install one of the application templates discussed in Chapter 1, Getting Started, you get a script named requirements. It's very useful, so make a copy and place it into the web subfolder. You can download this ile from the Yii 2 repository at https: After you get the ile, you can run it from the command line by calling the following: An introduction to Yii conventions A really high-level explanation of things is as follows.
This object uses Yii's interpretation the of Model View Controller MVC composite pattern to process the request and display the result back to the sender. If you forgot or were unaware of the MVC before, then you probably want to read at least the oficial documentation for Yii for an in-depth explanation.
Depending on the interpretations, a model is either what the controller uses to get data to put into a view or actually is what the controller puts into a view. Yii 2 does not enforce any approach, but its implementation of models assumes that the model is a container for some data, either transient in-memory only or persistent with the support of the active record pattern. So, a request passes through the following steps: The web server receives the request and passes it to the index.
A Yii Application object is created. It decides which Controller class should be used to handle this request. A Controller object is created. It decides what Action it should run they can be either methods of Controller or separate classes , and run it, passing the request details there.
An action is performed, and, if it were properly constructed by the programmer, it returns something rendered by the view. It's not enforced by the framework in any way; you can have controller actions that do not render anything. A special application component is responsible for formatting data before sending it back to the user. Knowing these steps, let's modify our current entry script, so it'll render the same thing, but using the Yii framework instead of displaying a raw text output.
We'll look at a nice lowchart with all the details in Chapter 12, Route Management. We will start by introducing Yii 2 from the entry point script.
At a reasonable minimum, the index. At 2 in the code, we get the coniguration tree for the application. Yii application conig is a massive PHP array describing the initial values of attributes of the application itself as well as its various components.
At 3 in the code, we make a new instance of the Application subclass representing web applications and immediately call the method called run on it. Let's make it: This is a mandatory identiier for our application. It is required because later we can split our application into different so-called modules, which we refer to using these IDs, and the top-level application obeys the same rules as a common module.
This is mandatory because it's basically the way for Yii to understand where it exists in the host ilesystem. All relative paths allowed in other settings should start from here. This is a leak from the user authentication subsystem, which we will discuss in Chapter 5, User Authentication.
This setting is the private key for validating users using the remember me feature, which relies on cookies. In earlier beta versions of Yii 2, this key was generated automatically. It was made visible by the 4e4e76e8 commit https: Apart from this setting, you can set components. This will get your application working, too. Next, we'll add some mandatory folders, because Yii just throws exceptions in case they are not there, and doesn't create them itself: These folders are used by the framework when the application is running.
Adding a controller Each controller class should have three distinct qualities: In addition, it's important to understand how Yii 2 will actually search for controller classes. Yii 2, in general, utilizes the autoloader compatible with the PSR-4 standard http: To put it simply, such an autoloader treats namespaces as paths in the ilesystem, given that there is a special root namespace deined, which maps to the root folder of the code base.
Also, each class to be available through the Yii 2 autoloader has to be put into its own ile named exactly like the class itself. So, let's create our irst controller to satisfy the smoke test. The most basic and straightforward way to deine controller actions is to deine them as public methods of the controllers having the name preixed by action. To get into the SiteController.
So, we have our smoke test passing with the Yii-based routing. Let's add some helpers for ease of debugging. Handling possible errors You can get a lot of strange errors at this stage of development.
Let's look at the ways you can use to set up your application quickly and gather as much feedback as possible.
First of all, when you make a really dire mistake, such as not deining id or basePath in the application conig, you basically get a blank page as a response from the Yii application. The only place you can look at is the logs of your web server. Of course, any other application error will end there, regardless of whether it was rendered in the browser. It's extremely important to deine it before you require the Yii library, because the Yii library will deine it in the event that you don't deine it yourself.
That's it. Here's how you do it: Lastly, you can add a custom logger to your application, which will log the errors happening within the application to a ile. Chapter 8, Overall Behavior, explains this in great detail. Making the data and application layers Now, let's get started on the real work. To satisfy our end-to-end test, we can start from many different levels of our application. But as we already know we will work with Yii, let's igure out what we should do in the controller.
We need to provide two routes: Here is the controller declaration we need for them: We need to provide the method named actionIndex to enable this route. Our intention is to provide a list of customers recorded in the database. If this parameter is set, we ilter the customer list. Otherwise, we display all customers from the database. Here is the high-level representation of the actionIndex method: There are a lot of places where you should pass associative arrays to some functions, and the variables will have the same names as the keys of these arrays.
If you did not know about this function already, we suggest that you consult the PHP function reference and learn about it. Now we just need to igure out getRecordsAccordingToQuery. To get to this, we need to have our database irst. But before that, let's settle on the customer aggregate deinition. Deining the customer model at the data layer Why do we need the customer domain model separate from the handy ORM at all?
For a simple reason: Some parts of the customer domain model will be stuffed into a single database table. Some parts will be separated out to different tables, and maybe there'll be some additional tables to represent many-to-many relations. More than that, we deinitely don't want the ORM details to leak to the layer where the controller is, because the very moment we do this, we'll bind ourselves to this ORM forever with no chance to replace it with anything modern.
A customer model is just a data holder class for now , so it doesn't need any tests for it. Here's how we'll deine it: We imagined one additional domain object: Here's how it is deined: To create a Customer object, we must provide the name and birthdate, but apart from that, all ields are public, so anyone can do anything with the aggregate. Now let's think about how we'll store this model in the database.
As we certainly don't want to set up this database schema manually on each deploy, we need some kind of automated way of doing this. Yii supports the concept of migrations exactly for this purpose. But to be able to use it, we need two things. First, we need our own version of the console runner from Yii. With this, we'll be able to make our own console commands to automate things, but for now, all we need is the built-in migrate command.
The script named yii should be placed in the root of the code base with the following content in it: You can see both the differences and similarities with index. Don't forget to make this ile executable! Let's make it as follows: That's where our database is being introduced at last. Settings for the db component are in a separate coniguration snippet because we'll use exactly the same settings for our web application.
Here's how the db. A database with that name should also exist in MySQL at this time. Having all these three elements in place: To keep it short, a Yii-style migration script is a class with two methods: In the up method, you describe the change you want to make in the database. In the down method, you describe how to revert the changes in the up method or specify by returning false that you give up; it's impossible, and you cannot revert from this particular migration.
With the migration scripts, you can just add the line yii migrate to your deploy script and can be sure that all changes you want to be done in the database will be there.
Here's the content of the up method, which we set up for the customer table: We wrote so much of the untested code already that it's giving me chills. Don't forget to actually run these migrations you just created by this command: A developer declares the class of objects corresponding to the tables so, you have one active record class deinition per table , and then you have quite a lot of functionality already done for him.
Yii implementation of this pattern helps to: Let's begin with the customer table. As we already have the customer name reserved for the domain model, we'll name the active record CustomerRecord, which is logical. Well, honestly, that's all you need to deine right now.
If you worked with Yii 1. We're lacking the validation rules, though. As we already have our database schema deined and loaded, nothing stops us from deining some validation rules: Right now, it's suficient to know that this rule means that we can assign anything to this ield.
By default, if an attribute is not constrained by some validation rule and not marked as safe by the safe rule, it'll be ignored by this method. You can read the full list of built-in validators in the Yii documentation: The PhoneRecord class is a lot simpler: Later, we'll probably invent our own validator for this. The CustomerRecord. Now, we've done everything related to the database preparation. Let's use it. Decoupling from ORM We need two pieces of functionality to satisfy our end-to-end test: Get the customer record from the database that has the given phone number.
Store a new customer record in the database. We don't even need to fetch the full list of customers, because we don't check it. As we have our tiny domain model layer consisting of the Customer and Phone models, it would be wise to keep it isolated from the framework, so we need a translation layer between ORM from Yii 2 and the domain models.
However, it would take a lot of pages to describe a proper setup of the repository pattern, and it's not really one of the topics of this book. In real-world, large-scale applications, you will surely need a proper translation layer for three reasons: At some point, you'll want to replace your usage of active records in some places to something at a lower level, such as Yii DAO https: Without the repository, it's possible that your only option will be full text search for names of your ActiveRecord-based classes through the whole code base.
Again, to make this change you'll need to do a lot of changes in various places. Without the decoupling from the framework, at least its most invasive part, which is the database access layer, you'll get almost no possibility to upgrade.
To not bloat this chapter too much, let's make the following methods in CustomersController. The irst one is the method to store the customer model in the database as follows: Note that the new instance of CustomerRecord magically gets the id ield value after it was saved by the save method. The following is the method to convert from ActiveRecord instances to Customer: This method needs to be changed when there'll be a need to support several phones per customer. These two methods are essentially the translation layer between Yii and our domain model.
Now, we will build the actual user interface and implement querying by phone number along the way. Creating the user interface With the CustomersController able to convert between domain models and active records, we move to the actual user interface pages at last.
Well, it should just render the UI for us: This code relies on the important convention of Yii describing from where the controller should get its views. Let's create it. What do we want on this page? According to our end-to-end test, there should be just the form to enter the customer information, along with their phone number and a Submit button.
Yii has a very extensive set of helpers to implement the web forms quickly and easily. The core concept behind them is the ActiveForm, which is the abstraction of the web form corresponding to some model from the Yii MVC interpretation. We initialize the ActiveForm and then use its methods to generate the HTML for ields corresponding to the model's attributes.
This is the only verbatim example of the view ile in this book. We won't present the use clauses and documentation blocks again to save space. The method called errorSummary is a nice shorthand, which will show all validation errors from the models in question in the event that the input is invalid according to the declared validation rules.
This is done using the special mechanism of passing data to View from Controller via the second argument of the render method. Basically, we at least need the following in the actionAdd method for the form to get correctly rendered: Routing Default routing in Yii looks like this: You need to add the following to the components section of your application coniguration: For your web application to be able to parse such URLs, you should conigure the corresponding URL rewriting in your web server.
For example, Yii developers routinely hack Apache with the following lines in the. With rewriting a set correctly, you'll be able to use URLs such as http: This is, of course, the best way to do it.
For now, it's enough to know that by default, when you do render in the controller, it assumes that the view you're rendering is just a snippet wrapped by a particular script called the layout. Apart from that, layout is just another view script. It's expected that you have some parts of the web application UI common to all pages, and a layout is exactly the place to hold them. Did you expect some fancy CSS stuff at this stage of development?
Our goal right now is to implement the bare functionality, so this basic HTML is more than enough. We'll utilize the same approach; thus, in the actionAdd method, we need to process possible input data.
We will do it like this: When and if we successfully load the new data submitted to us via a POST request, we store the resulting customer model in the database using methods deined in our translation layer. A method called load is shorthand for the following four checks: Note how we can validate only a select few attributes instead of all of them.
This is what allows us to utilize the errorSummary method on ActiveForm, because it will check the error messages one by one and print them nicely. It's probably the most interesting controller action so far.
Now, we are ready to really get records according to the query. A special Application component called Request manages the query parameters and exports the method called get. To understand why we need to wrap the records fetched by the query to the data provider, we need to know how we are going to render the results. Widgets As themselves, data providers are not important. Their importance is that almost all widgets built in Yii use them as a source of models to render.
Widget can be seen just as the encapsulated view along with some supplementary logic. Typical widgets are: Widgets are used in views like this: Given the amount of self-documentation on all Yii classes, even without any documentation and code examples, you can just open the class deinition of the widget and igure out how to conigure it.
So, we need data providers because they encapsulate the act of inding the set of models appropriate to render right now. They do sorting, pagination, and iltering for you. They are most useful when you use the active records as a domain model in your application that is, when you map tables to domain objects exactly.
In our case, when we try our best to decouple from the ORM, we need data providers just as wrappers around our data to satisfy the widget's requirements. The List Customers UI The perfect data provider for our cause is ArrayDataProvider, which just gets the list of ready-made models and wraps them, allowing us to feed them to widgets.
So, here's what we do in wrapIntoDataProvider: The actual data to wrap into DataProvider and send to render is found like this: Here, we meet the query methods of the ActiveRecord class for the irst time. They are so numerous and the API in general is so vast, that it is probably better if you turn to the oficial documentation here: This is how you can conigure it in our case: We need to set the id HTML attribute for the widget because we assume our search results are?
The itemView element holds the name of a separate view, which will actually render each individual model from a given DataProvider. It's reasonable to deine it in terms of the DetailView widget. However, even the array attributes can be referenced in the widget, which is just amazing, honestly.
In general, the Html helper class makes writing view iles really easy and declarative, because, as you probably noticed, we did not write any of the bare HTML code in any of our views except for the layout ile. Using the application Now, we can look back at our end-to-end test.
Let's assume you've done it already for simplicity.
Let's walk through the UI manually, though. For exactness, let's assume your deploy machine is reachable at http: Remember the phone number you entered.
Then you click on the Submit button and end up at the List Customers UI, which tells you that no results were found. Have a look at the following screenshot: Manually move to the http: Paste the remembered phone number in the query ield and hit Search. You should end up on the List Customers UI, which tells you that only one record is found and lists the details about this record. In fact, even if there are several customers with the same phone, we know right from the source code that the system will return only one record to us anyway.
That's another feature missing for us. Not mentioning that, we allow only one phone number per customer. Let's end the session now and get out to conclude this chapter. Summary We covered a lot of ground in this chapter while delivering just a single feature. We did not bother with the graphic part of the web application, concentrating only on the functionality provided. A full stack of basic Yii technologies was used here, from the bottom with active records and data providers to the top with controllers, widgets, and active forms.
This chapter was expected to be an example of what is being used when developing the application with Yii. We glossed over the important part of the rendering process—the assets—but that's for the chapters to come.
Next, we'll see what else Yii has up its sleeve to reduce the coding effort of the developer: We hope that after this coding session you got a good grasp of them.
Also note that while we're not really going to follow the Yii conventions for structuring the iles in our project, we ended up with a structure surprisingly similar to the basic application template. This came up naturally, and part of the answer to this is in Chapter 7, Modules, where we'll ind out more about the internals of MVC implementation in Yii. Using active records that are mapped to database tables in a ratio of 1: Unfortunately, when you have many similar tables to manipulate, you end up with highly repetitive code, which is also quite boring to write.
To overcome this issue, Yii has a tool called Gii to automatically generate standard code for you. In this chapter, we will see how Gii can help you while developing a Yii-based application. Deinition of the model to work with We'll continue with the example deined in Chapter 2, Making a Custom Application with Yii 2. Let's pretend we need to manage a list of services in our database. It will just be a lookup table, deining the most important properties of a service we need: First, we generate a new migration by calling the following command from the command line: Then, we write the following up and down methods: Finally, we run the migration we created: Our strategy from now on will be to use Gii to perform the following: Installing Gii into the application Run the following command to fetch the required iles to use Gii: Now we need to wire Gii into our application: First, as we're going to use something installed by Composer in our application, we need the autoloader from Composer.
It's located as a ile called autoload. Then, we need to add the Gii user interface to our application. The allowedIPs section is needed if you're working with an application that is deployed remotely which you expected to do. By default, Gii allows access only from the localhost Also, it's pretty important that you add another wiring to Yii 2 internals—this time not where they should be, but inside the application conig.
Your real path can be different, but it should ultimately point at the extensions. We'll explore the real meaning of this ile in Chapter 9, Making an Extension. Generating the code for the Model class From the main menu of Gii, select the Model item and end up in Model Generator. It'll make the active record deinition for you based on the table in the database. So, note that all the ields in the generator's UI are quite easy to understand, especially with all the tooltips.
You should ill in the available ields as shown in the following table and hit the Preview button: We named the model ServiceRecord to follow the convention set in the previous chapter.
To be totally clear, this is not a standard naming convention and Yii 2 does not impose any on you. The sufix Record is added to explicitly state that the class in question is a descendant of ActiveRecord and has nothing to do with the domain model of our application. This generator exclusively creates the descendants of the ActiveRecord class. We declared the desired namespace for the same reason.
This is a standard two-step behavior of Gii that allows you to see exactly what will be automatically generated and where. Hit Generate and we're done. You will see the following page: The controller being generated will have ive actions already prepared for you: This action will list the models recorded in the database.
This will correspond to our Services List UI. This action allows us to see the detailed view of a single model. This action allows us to record new models in the database. This action allows us to change a single model's details and update them in the database. This action allows us to remove a single model's record from the database. In the index route, the controller will render not just a list of records, but the search functionality as well. To support this, Gii generates an additional class called Search Model, which encapsulates the mechanics of searching models by their ield values.
The create and update routes are so similar in their functionality that they even use the same script to generate a web form to ill the ield values of a model. The only difference between those actions is that in create, the controller will add a new record to the database, and in update, it will change the existing record. One special route in here is the delete route because of its potentially dangerous nature.
First of all, it's extremely simple and designed to just do its job and redirect the visitor back to the index, making it an ideal target for an AJAX call. Second, Gii generates the controller in such a way that the delete route is accessible only by the POST request, essentially making AJAX the only way to activate this action. Let's create the CRUD at last. Fill in the ields as described in the following table: In other ields, there are names we created that conform to our Yii project's structure.
Once you click on the Preview button, you should see the result shown in the following screenshot: You are encouraged to read through the code that Gii will generate. You may use a decent IDE that has a feature similar to Go to deinition to easily navigate between the generated code and base classes in the Yii framework. We will not discuss the default boilerplate code in Yii applications in much detail, or this book will become a code-only book and will probably be three times as large.
Click on Generate and then we'll turn to some inishing touches we need to make. Creating a new layout to support pages generated by Gii Here is how our UI looks right now, given that one record is already inserted into the services table: Given our spartan visuals from Chapter 2, Making a Custom Application with Yii 2, you most probably did not expect much from the UI generated by Gii anyway; however, this obviously has some serious layout problems.
The issue is that we jumped too far with this step, as we have not bothered with the looks of our application until now. Chapter 4, The Renderer, talks about rendering a system in Yii 2. However, we can take a glimpse into the future and prepare a bare minimum of the view code to enable the standard Yii 2 project design, as you may have seen in the basic application template already. Our only issue, really, is the too-limited layout ile.
To not delve into much detail, which will be given in Chapter 4, The Renderer, we'll just replace this layout with the one copied directly from the basic application template: Except various useful calls such as inserting an HTML language attribute, inserting a metatag with a charset, and HTML encoding the title of the page, pay attention to the highlighted lines.
They are the framework of the Yii 2 renderer. We will explore it in Chapter 4, The Renderer. Inside the code bundle that comes with this book, you will ind the acceptance test deinitions for the CRUD UI we have been building in this chapter. This was not included in the text for brevity. Note that we haven't manually written a single line of production code to make these tests pass with the exception of the layout.
Also, given that all the possible preparations were done already, the next time we need to make such a CRUD UI, we will just need to ill in six ields and click on two buttons, and we'll have it.
Each record is represented by a row in the table. This tabular UI has pagination with the default page size of 20 lines this can be a problem if you run acceptance tests too many times without cleaning the database upon deploying or redeploying a target. Also, it has ields at the top of the table to ilter rows by the ield values, as shown in the following screenshot: They correspond to the view, update, and delete actions, respectively.
The view action renders a nice list of ields and their values for the selected record. In there, you'll see the Update and Delete buttons too. If you click on the Update button either from the list UI or from the view UI, you get a form to edit the ields of the selected record.
This form is absolutely identical to the form where we create a new record, which we will see in the following chapters. If you accept the deletion, the table will be reilled via AJAX. If you click on the big green Create Service Record button, you'll get a form to enter data for a new ServiceRecord model.
This form has built-in client-side validation.
It won't allow you to submit the form if there are errors in the input data. So, when you automatically generate the controller actions, it'll be dificult for you to understand how they work, especially if you are new to the framework. This is a common issue with all automatic code generators; they are useful only for people who already know what code they need to write and just don't want to write it themselves.
In this case, code repetition induced by Gii in the generated controllers will be completely unnecessary. In Chapter 11, The Grid, we will show you how three controllers generated by Gii can be reduced to one base Controller class and three speciic controllers trimmed down to virtually two lines of custom code each. To sum up, the automatic generation of a CRUD UI in Gii is especially usable only when you need some generic baseline for your actual work, and the changes in index, create, edit, and delete actions are expected.
In other cases, maybe it'll be easier to just write controllers from scratch, which is not so hard anyway. Its model generator is virtually priceless, because you certainly do not need to write boilerplate code for your active records, and Gii can infer a lot of information from the table schema for you.
Also, it has several other generators, including an Extension generator; we will not be using it in Chapter 9, Making an Extension, though, because it will hinder your ability to understand how things work inside Yii 2. Summary In this chapter, we learned how to integrate Gii into an existing project and wire it to the code base.
Also, we discussed the bare minimum of view code that the Yii framework expects from us to have if we are building everything from scratch. We have used quite a lot of code related to the view part of the MVC ideology in this and the preceding chapters, and the necessity of layouts has been especially obscure so far.
In the next chapter, we'll talk about how Yii 2 actually performs rendering of a view. This chapter will basically be an explanation of what we really did then. Despite the name of this chapter, there's no such thing as a separate Renderer object in Yii. Being an MVC-based framework, Yii employs an entire set of processes that perform the rendering.
These processes are spread through the whole code base. Anatomy of Yii rendering When a web application visitor's request is being handled, there are a few processing steps your data goes through before it is sent to the visitor's browser: A controller action is run.
It will use the render method to process a PHP script sending it some parameters if necessary and get HTML form from it to send to the client browser. Please note that this action is voluntary, not mandatory. You can have controller actions that do not call the render method at all. The View component checks whether it has any view renderers associated with the ilename extension of the view ile it has just found.
If there's no such view renderer, the view ile is processed using the traditional PHP require method mechanics. The Renderer 7. The instance of Response looks at the value of its format attribute and checks whether it has custom ResponseFormatterInterface implementers associated with this value. The value of the format attribute can also be one of the built-in formats, which can be handled by the Response instance itself.
If indeed there is such a response formatter, its format method is called, and the whole Response instance is passed to it so that format can properly set the headers and content of the Response instance. If the Response instance can process the given format itself, it does so by modifying its headers and content. Finally, the headers are sent using the standard PHP header mechanics, and the content is just lushed down the pipe to the client's browser.
In the most rudimentary case, where you don't have any themes, tweak the view renderers or response formatters, and execute the following in your controller: The index. The Content-Type: Finally, the return value of the render method is sent to the client verbatim.
What we are really interested in are four simple questions: JSON being the most obvious example. Before we talk about the answers to these questions, an explanation about the concept of Yii application components will be useful.
The Yii application components Let's take a look at the application initialization happening in the index. Set up the Yii class deinition. In step 3, the components are created using the following rule: This rule is recursive. There are some special components for which the application knows the default classes beforehand. Their IDs, by which they are mentioned in the coniguration, are already known, so Yii 2 knows which classes to use for these components even if you don't specify them.
Also, basically, each array that has a key named class and a valid class name as the value of this key will be treated as the coniguration for the instance of that class. These rules are encapsulated in the Yii:: You can always consult the source code for an enthralling adventure into the Dependency Injection Containers implementation, which we will skip in this book both because these implementation details are irrelevant to us and to save our sanity overall.
As soon as the log component is generated, it is attached to the application as the log property. In case Yii 2 updates itself in some way or another, you can always see the actual list of the built-in components inside the deinition of the Application. The most important point of this system of components is that nothing prevents you from creating and registering your own component. It is indistinguishable from the built-in components.
View, being an application component, allows you to execute the following: It also renders the special view ile, which in Yii terms is called layout, and then passes the view ile to be rendered into this layout ile. Algorithm to ind the view iles The concept of modules, in some ways being core to Yii as a whole, complicates things a bit.
We'll discuss modules later in Chapter 7, Modules, where we'll go into more theoretic detail in an attempt to bring you an insight into how Yii is really constructed. Until then, let's pretend we're dealing with a plain application that doesn't have submodules.
An application, as you remember from Chapter 2, Making a Custom Application with Yii 2, must have its basePath property deined. The base path is the path to the root of the application's code base.
In fact, an application has another property called viewPath. It points to the folder in which all of the views of that application should reside. By default, viewPath contains a relative path to the folder named view. Being relative, this path resolves to the view folder under the application's basePath. The viewPath, in turn, acts as the base to determine the relative path you mention as the irst argument of the Controller.
This viewPath is appended with the ID of the controller we call render on. When you call the following actionIndex method the one we used to search customers when developing the UI , all the settings of the Yii application are set to their default values: Yii 2 creates a controller ID in a very simple way.
The name of the Controller class is stripped off the Controller sufix, and then the leftover name in the uppercase is replaced with the dash-separated one. Previously, we mentioned that the default extension expected from the view ile is php. However, fully relative paths are not all that you can use. If you start a path with the " " symbol, it'll be treated as the Yii path alias. Path aliases were in Yii 1. Now, only the irst token will be expanded. This works as shown in the following code no need for a dedicated chapter speciically for path aliases: Yii 2 is so nice that it deines the ive most important alias tokens for you: As a result, in the default application setup for example, in the basic application template , webroot equals the document root set in the web server host setup, and web is empty.
You can use aliases when specifying the path to the view ile. Almost any setting of the base Yii components, which accepts some sort of path, accepts aliases as well. Apart from aliases, you can specify the absolute path for the view iles.
Absolute means not in terms of a ilesystem, but in terms of the application code base. In this case, Yii will start from viewPath of the current module. In case an application lacks any modules, it will work as the only module, so a single slash is equivalent to two slashes.
In fact, in the case of a fully relative view ile path, the path expands relative to the current module, and not just from the application's viewPath. Algorithm to search the layout ile to be used The Controller. An actual implementation of this mechanics is as follows: A method called getView grabs the View component from the current application instance, which is identical to the Yii:: The View.
Layout is just another view ile and it's processed as any other view ile. It's the text string that contains the result of rendering the view ile we really want to render. The controller has to ind the Layout ile in some way. In this way, it does not depend on the view ile alias that we pass to the render method. In fact, Controller has the layout property that holds the path alias to the Layout ile render has to use.
If for some reason you set the layout property to false, the layout system will be disabled and the controller will render just the view ile requested. If the layout property is set to null, the value of the layout property of the parent module will be used. As mentioned in Chapter 2, Making a Custom Application with Yii 2, the top-level module, which is a parent to all the other ones, is the application itself.
After the value of the layout property is fetched, and it's neither null nor empty nor false, the rules summarized in the following table are applied: Specification Meaning " alias" Yii:: By default, layoutPath contains the folder named layout inside the folder pointed by the viewPath property.
By using path aliases with the symbol, you can point to any folder in the application code base. By default, Controller. This means that Yii should use the layout property of the module containing that controller. Even if you use the system of modules, by default, each module starts with the layout property equal to null anyway. This means that the application's global layout value will be used, which is usually set in the application conig.
The default value of this property is main, which is the main. If you specify the ile extension, the php extension will not be appended automatically. The internal workings of rendering the view ile While we certainly don't want to go too deep into the internal workings of the View component, Yii forces us to do so by the conventions of structuring the layout iles. We will look at the custom renderers in the very next section. We have used the following methods of the View component there: Method Explanation beginPage This starts buffering the content that follows it.
Everything after this call is buffered until the endPage call is expected to be postprocessed. It also triggers the View:: It also puts an end to buffering. It actually inserts the registered meta, link, style, and script elements into the resulting HTML page. So if you're absolutely crazy, you can even start the second sequence of the HTML page rendering afterwards.
The goal of this elaborate structure of the conventional methods is to help you have total control on the semantics of the different View:: Moreover, everything around the beginPage Custom renderers With all this, you now probably know the most contrived part of the Yii conventions.
Let's now talk about the custom renderers. Yii uses renderers to process the view ile you referenced in the render method, based on its ile extension. If the View component of Yii is unable to ind any renderer for the given view ile, it treats this view ile as a PHP script, and executes the renderPhpFile method: An important effect of custom renderers is that you can do anything inside your view iles, which will be dangerous if you really do anything. You should ideally treat PHP view iles as being in some template system's format, only allowing them to paste data passed to them as associative arrays or plain data structures.
Let's think about how we can utilize this feature for our convenience. The original design goal of the developers, obviously, was that you'll write the parser for some template system format, and then you'll be able to write view iles not as raw PHP, but as these supposedly, more restricted, and domain-speciic templates. By giving the templates a new format with a distinct extension, you'll force Yii to use your custom parser on them, which will supposedly convert the given template to, say, HTML, which you'll send to the client.
Let's employ a simple solution here, which is using Markdown http: Let's say we want the set of user-level documentation pages, which will be handcrafted by a skilled tech writer. Markdown will be a simple middle ground for this task. Employing a custom renderer to render static Markdown iles is pretty simple. We assume that you have the same CRM application we have been building in the previous two chapters. First, let's declare what we want: Don't forget to run. Now, run the test and watch it fail: I see "Documentation","h1" 1.