title
Yii2 PHP Framework - Full Course (Build a YouTube Clone)
description
Yii is a fast, secure, and efficient PHP framework used to create all kinds of web apps. Learn how to use Yii2 in this full tutorial for beginners by building a YouTube clone.
🎥This course was developed by
Zura Sekhniashvili. Check out his YouTube channel: https://www.youtube.com/channel/UC_UMEcP_kF0z4E6KbxCpV1w
💻Code: https://github.com/thecodeholic/Yii2-Youtube-Clone
⭐️ Course Contents ⭐️
⌨️ (0:00:00) Introduction
⌨️ (0:03:08) Demo
⌨️ (0:06:27) Install necessary tools
⌨️ (0:09:28) Project setup
⌨️ (0:25:02) Create Database and run migrations
⌨️ (0:28:48) Signup, activate account and test login
⌨️ (0:33:00) Change Url format
⌨️ (0:34:46) Explore project structure & entry script
⌨️ (0:36:41) Config files
⌨️ (0:38:12) Controllers & actions
⌨️ (0:42:30) Views
⌨️ (0:44:59) Install Bootstrap 4
⌨️ (0:48:20) Asset bundles
⌨️ (0:50:11) Layouts
⌨️ (0:54:14) Application properties
⌨️ (0:56:25) Navbar widget
⌨️ (0:57:28) Components
⌨️ (1:04:07) Nav widget
⌨️ (1:05:19) Identity Class
⌨️ (1:06:02) Active Record class
⌨️ (1:10:45) Behaviors
⌨️ (1:12:19) Finish studio layout
⌨️ (1:14:48) Url creation
⌨️ (1:17:31) More on layouts
⌨️ (1:19:32) Finish studio layout
⌨️ (1:30:25) Create auth layout (Nested layouts)
⌨️ (1:35:16) Aliases
⌨️ (1:37:11) Video table migration
⌨️ (1:48:05) Generate Video model using Gii
⌨️ (1:49:48) Active Record & Models
⌨️ (1:50:34) Model rules
⌨️ (1:52:44) Generate Video CRUD using Gii
⌨️ (1:57:42) Video create page (Working with forms)
⌨️ (2:07:15) Video upload
⌨️ (2:25:42) Video page
⌨️ (2:43:39) Video status change
⌨️ (2:46:25) Thumbnail upload
⌨️ (2:55:31) Thumbnail resize
⌨️ (3:01:27) Handle upload errors
⌨️ (3:04:39) Save video tags
⌨️ (3:09:20) Video listing page (Gridview & Data providers)
⌨️ (3:20:09) Restrict upload for authorized users only
⌨️ (3:22:59) Implement frontend layout
⌨️ (3:39:23) Video delete
⌨️ (3:47:18) Output published videos on frontend
⌨️ (4:00:31) Video view page
⌨️ (4:12:53) Count video views
⌨️ (4:23:08) Implement Like/Dislike
⌨️ (4:56:50) Channel page
⌨️ (5:08:05) Subscribe/Unsubscribe
⌨️ (5:21:16) Many to Many relations
⌨️ (5:24:56) Output videos on channel page
⌨️ (5:31:33) Email send using mailtrap
⌨️ (5:44:25) Search
⌨️ (6:00:07) Similar videos
⌨️ (6:11:05) History page
⌨️ (6:23:08) Implement dashboard
⌨️ (6:39:39) Debug bar
⌨️ (6:42:13) Relation eager loading
⌨️ (6:45:08) Caching
⌨️ (6:50:12) Overview, code cleanup and improvements
--
Learn to code for free and get a developer job: https://www.freecodecamp.org
Read hundreds of articles on programming: https://freecodecamp.org/news
detail
{'title': 'Yii2 PHP Framework - Full Course (Build a YouTube Clone)', 'heatmap': [{'end': 2042.041, 'start': 1525.156, 'weight': 0.767}, {'end': 2811.622, 'start': 2290.365, 'weight': 0.704}, {'end': 3564.993, 'start': 3309.887, 'weight': 0.764}, {'end': 5604.37, 'start': 4833.631, 'weight': 1}, {'end': 6623.536, 'start': 6362.634, 'weight': 0.89}, {'end': 8152.749, 'start': 7889.202, 'weight': 0.875}], 'summary': 'This yii2 php framework full course covers e2 framework benefits, setting up advanced project template, web application development, backend video controller overview, video file management, video management and display, implementing video features, video functionality implementation, implementing like and dislike functionality, implementing channel features, implementation of channel page features, video publishing and search optimization, video history and analytics implementation, database query optimization and web development, with topics including speed, customizability, support for various databases, restful api support, role-based access control system, and optimization of database queries.', 'chapters': [{'end': 625.972, 'segs': [{'end': 61.876, 'src': 'embed', 'start': 35.229, 'weight': 3, 'content': [{'end': 42.395, 'text': "people love building awesome things and for this video I wanted to build something very awesome, which I haven't done before on my channel.", 'start': 35.229, 'duration': 7.166}, {'end': 45.919, 'text': 'So I decided to build YouTube clone application.', 'start': 42.896, 'duration': 3.023}, {'end': 48.621, 'text': "We're going to build backend and frontend side.", 'start': 46.519, 'duration': 2.102}, {'end': 49.923, 'text': 'On the backend.', 'start': 49.102, 'duration': 0.821}, {'end': 58.011, 'text': 'users will upload videos, provide thumbnail title description tags and they can optionally mark the status to published,', 'start': 49.923, 'duration': 8.088}, {'end': 61.876, 'text': 'to display the video on the frontend side or leave it unlisted.', 'start': 58.011, 'duration': 3.865}], 'summary': 'Building a youtube clone application with backend and frontend, allowing users to upload videos and mark their status as published or unlisted.', 'duration': 26.647, 'max_score': 35.229, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug35229.jpg'}, {'end': 200.4, 'src': 'embed', 'start': 173.994, 'weight': 4, 'content': [{'end': 182.74, 'text': 'It has powerful routing, validation, powerful RESTful API support, airbag role-based access control system, and much more.', 'start': 173.994, 'duration': 8.746}, {'end': 188.264, 'text': "Okay, enough talking, let's have a look at the working demo, and then we can start building this awesome application.", 'start': 183.16, 'duration': 5.104}, {'end': 191.772, 'text': "First of all, let's have a look at the working demo.", 'start': 189.229, 'duration': 2.543}, {'end': 194.775, 'text': 'On the front-end side, we see all published videos.', 'start': 192.132, 'duration': 2.643}, {'end': 200.4, 'text': 'If we click on the history, this will open our My Visited Videos page.', 'start': 195.415, 'duration': 4.985}], 'summary': 'A powerful platform with restful api support and role-based access control. includes a demo showcasing video features.', 'duration': 26.406, 'max_score': 173.994, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug173994.jpg'}, {'end': 247.999, 'src': 'embed', 'start': 219.092, 'weight': 9, 'content': [{'end': 226.593, 'text': 'down below we see number of views, the date when the video is uploaded, some description and the channel link.', 'start': 219.092, 'duration': 7.501}, {'end': 236.056, 'text': "We see like and dislike buttons as well, which works using Ajax, so that if you play the video, this won't disturb you playing.", 'start': 227.233, 'duration': 8.823}, {'end': 240.157, 'text': 'When we click on the channel link, this one opens the channel page.', 'start': 236.536, 'duration': 3.621}, {'end': 247.999, 'text': 'Right here we see channel name, subscribe button, number of subscribers and the videos uploaded from this channel only.', 'start': 240.517, 'duration': 7.482}], 'summary': 'The video page displays views, upload date, description, and channel link. it features like/dislike buttons using ajax for uninterrupted video playback. clicking the channel link opens the channel page, showing channel name, subscribe button, and video count.', 'duration': 28.907, 'max_score': 219.092, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug219092.jpg'}, {'end': 328.302, 'src': 'embed', 'start': 301.755, 'weight': 2, 'content': [{'end': 307.736, 'text': 'When I create an account, I see the following message that I need to check the inbox and verify my email.', 'start': 301.755, 'duration': 5.981}, {'end': 309.517, 'text': "Let's open Mailtrap.", 'start': 308.157, 'duration': 1.36}, {'end': 312.478, 'text': 'Right here, I see this email.', 'start': 310.697, 'duration': 1.781}, {'end': 316.579, 'text': 'I just click on the link and my email has been confirmed.', 'start': 312.858, 'duration': 3.721}, {'end': 320.58, 'text': 'Now I am actually able to log in on the front-end side.', 'start': 317.059, 'duration': 3.521}, {'end': 323.44, 'text': "And even more, I'm already logged in.", 'start': 321.22, 'duration': 2.22}, {'end': 325.841, 'text': "Let's go to the back-end side.", 'start': 324.241, 'duration': 1.6}, {'end': 328.302, 'text': 'My dashboard is of course empty.', 'start': 326.401, 'duration': 1.901}], 'summary': 'Email verification completed, logged in on front-end, empty dashboard on back-end.', 'duration': 26.547, 'max_score': 301.755, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug301755.jpg'}, {'end': 471.191, 'src': 'embed', 'start': 435.665, 'weight': 0, 'content': [{'end': 439.946, 'text': 'Scroll down at the bottom and right here we have XAMPP control.', 'start': 435.665, 'duration': 4.281}, {'end': 445.489, 'text': 'Just double click on this XAMPP control and this will open control panel.', 'start': 440.467, 'duration': 5.022}, {'end': 460.197, 'text': 'click right here you will see probably start buttons on Apache and MySQL and click these start buttons on both of them and you have successfully installed and Apache is running.', 'start': 446.309, 'duration': 13.888}, {'end': 471.191, 'text': "so let's just type right here in the browser localhost to make sure it's up and running, and you should see screen like this okay,", 'start': 460.197, 'duration': 10.994}], 'summary': 'Use xampp control to start apache and mysql, then type localhost in the browser to confirm installation.', 'duration': 35.526, 'max_score': 435.665, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug435665.jpg'}], 'start': 0.449, 'title': 'E2 framework for youtube clone', 'summary': "Introduces thecodeholic's e-framework course on freecodecamp, emphasizing the benefits of e2 framework and the creator's 5+ years experience. it also highlights the e2 framework's speed, customizability, support for various databases, restful api support, and role-based access control system. the chapter provides details on setting up apache, mysql, php, composer, and e2 framework for building a youtube clone with front-end and back-end functionalities.", 'chapters': [{'end': 121.933, 'start': 0.449, 'title': 'E2 framework youtube clone course', 'summary': "Introduces thecodeholic's e-framework course on freecodecamp, detailing the plan to build a youtube clone application with backend and frontend functionalities while emphasizing the benefits of e2 framework and the creator's experience of 5+ years.", 'duration': 121.484, 'highlights': ["TheCodeHolic introduces an E-Framework course on FreeCodeCamp to build a YouTube clone application with backend and frontend functionalities, showing a working demo and emphasizing the benefits of E2 framework and the creator's experience of 5+ years.", "The YouTube clone application's backend allows users to upload videos with details like title, description, tags, and status, while the frontend enables viewing, liking/disliking, finding similar videos, channel subscription, global search, and viewing history.", "E2 framework is highlighted as one of the best PHP frameworks, offering the ability to build various projects like CRM, e-commerce systems, CMSs, RESTful APIs, and simple websites, backed by the creator's 5+ years of experience.", "TheCodeHolic expresses excitement about the FreeCodeCamp community and extends gratitude to Bo for publishing the video, indicating the community's massive impact on helping millions of people learn programming."]}, {'end': 408.744, 'start': 122.354, 'title': 'E2 framework overview', 'summary': 'Introduces the e2 framework, highlighting its advantages such as speed, customizability, support for various databases, powerful code generation tool, restful api support, role-based access control system, and a demonstration of its functionalities including frontend navigation, email sending, search functionality, backend dashboard, video upload, and engagement tracking.', 'duration': 286.39, 'highlights': ['The E2 framework offers advantages such as speed, customizability, and support for relational and NoSQL databases, with a powerful code generation tool called GII allowing the generation of models, controllers, forms, extensions, modules, and CRUD applications within 5 seconds.', 'The demonstration showcases frontend functionalities including video navigation, user authorization, engagement tracking, email sending, and search functionality based on video title, description, and tags.', 'The backend dashboard provides information on the latest video, total views, total subscribers, and latest subscribers, as well as the ability to upload, publish, and track engagement of videos.', 'The setup process for building an E2 application involves installing apache, mysql, and php, for which the XAMPP package from apachefriends.org is recommended.']}, {'end': 625.972, 'start': 408.744, 'title': 'Setting up apache, mysql, php, composer, and e2 framework', 'summary': 'Details the installation of apache, mysql, and php using xampp on windows, checks php availability through the command line, introduces composer as a dependency manager for php, and outlines the installation of the e2 framework for building a youtube clone with front-end and back-end functionalities.', 'duration': 217.228, 'highlights': ['The chapter guides the installation of Apache, MySQL, and PHP using XAMPP on Windows, ensuring successful installation and running of Apache (quantifiable data: successful installation and running of Apache).', "It emphasizes checking the availability of PHP through the command line on Windows, providing the command 'php -v' to verify the PHP version (quantifiable data: verification of PHP version).", 'The chapter introduces Composer as a dependency manager for PHP, highlighting its function to declare and install dependencies of packages (quantifiable data: introduction of Composer as a dependency manager for PHP).', 'It outlines the installation process of the E2 framework, emphasizing the basic and advanced versions, with a specific focus on the need for the advanced version for building a YouTube clone with front-end and back-end functionalities (quantifiable data: emphasis on the need for the advanced version for building a YouTube clone).']}], 'duration': 625.523, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug449.jpg', 'highlights': ['E2 framework offers speed, customizability, and support for databases, with GII generating applications in 5 seconds.', 'TheCodeHolic introduces E-Framework course on FreeCodeCamp for building YouTube clone with backend and frontend functionalities.', "E2 framework is highlighted as one of the best PHP frameworks, backed by creator's 5+ years of experience.", 'The backend dashboard provides information on latest video, total views, subscribers, and upload/publish functionalities.', "The YouTube clone's backend allows users to upload videos with details like title, description, tags, and status.", 'The frontend enables viewing, liking/disliking, finding similar videos, channel subscription, global search, and viewing history.', 'The chapter guides the installation of Apache, MySQL, and PHP using XAMPP on Windows.', 'Composer is introduced as a dependency manager for PHP, highlighting its function to declare and install dependencies of packages.', 'The setup process for building an E2 application involves installing apache, mysql, and php using XAMPP package.', 'The chapter introduces the need for the advanced version of E2 framework for building a YouTube clone with front-end and back-end functionalities.']}, {'end': 2455.331, 'segs': [{'end': 2042.041, 'src': 'heatmap', 'start': 1525.156, 'weight': 0.767, 'content': [{'end': 1532.54, 'text': "so i'm gonna go with mostly used tool on windows, which is phpMyAdmin.", 'start': 1525.156, 'duration': 7.384}, {'end': 1535.661, 'text': 'okay, I just type this and opens this interface.', 'start': 1532.54, 'duration': 3.121}, {'end': 1541.543, 'text': "Let's right here on the left side, click this new button and type the database name.", 'start': 1536.081, 'duration': 5.462}, {'end': 1544.305, 'text': "That's going to be FreeCode2.", 'start': 1541.864, 'duration': 2.441}, {'end': 1547.406, 'text': "That will be the database name I'm going to give.", 'start': 1544.505, 'duration': 2.901}, {'end': 1552.708, 'text': "For encoding, I'm going to choose UTF-8MB for Unicode CI.", 'start': 1548.366, 'duration': 4.342}, {'end': 1555.009, 'text': "That's the encoding which works best for me.", 'start': 1552.748, 'duration': 2.261}, {'end': 1559.671, 'text': "I'm going to click Create button and the database was successfully created.", 'start': 1555.469, 'duration': 4.202}, {'end': 1562.772, 'text': 'Now we need to open PHPStorm.', 'start': 1560.351, 'duration': 2.421}, {'end': 1572.811, 'text': 'okay, go to the common folder config and right here we have main local php.', 'start': 1563.268, 'duration': 9.543}, {'end': 1584.835, 'text': "so let's open this main local php and we see here components db, and that's exactly what the installation guide tells us right here.", 'start': 1572.811, 'duration': 12.024}, {'end': 1592.719, 'text': "on step number two create new database and adjust components db configuration okay, so that's what we need to do.", 'start': 1584.835, 'duration': 7.884}, {'end': 1593.76, 'text': 'components db.', 'start': 1592.719, 'duration': 1.041}, {'end': 1597.101, 'text': 'and right here we have dsn and e2 up.', 'start': 1593.76, 'duration': 3.341}, {'end': 1599.202, 'text': 'advanced is the database name.', 'start': 1597.101, 'duration': 2.101}, {'end': 1603.324, 'text': "so let's just replace this with free code tube.", 'start': 1599.202, 'duration': 4.122}, {'end': 1605.585, 'text': "okay, let's save this now.", 'start': 1603.324, 'duration': 2.261}, {'end': 1615.611, 'text': 'the next thing, according to installation, is to open console terminal again and apply migrations with command php emigrate.', 'start': 1605.585, 'duration': 10.026}, {'end': 1619.193, 'text': "okay, so let's open terminal again.", 'start': 1615.611, 'duration': 3.582}, {'end': 1621.435, 'text': 'okay, so we are in the project folder.', 'start': 1619.193, 'duration': 2.242}, {'end': 1630.362, 'text': 'make sure you are in the project folder and from here we need to call php executable, either php, if it exists on your operating system,', 'start': 1621.435, 'duration': 8.927}, {'end': 1633.805, 'text': 'or see exam php, php.', 'start': 1630.362, 'duration': 3.443}, {'end': 1637.028, 'text': 'and right here we need to specify e migrate.', 'start': 1633.805, 'duration': 3.223}, {'end': 1641.971, 'text': 'okay, this e basically is a file in the project.', 'start': 1637.688, 'duration': 4.283}, {'end': 1646.235, 'text': 'right here, when we just run php and it generated this e file.', 'start': 1641.971, 'duration': 4.264}, {'end': 1653.08, 'text': "okay, and that's php file and we're basically calling gen migrate command of this e file.", 'start': 1646.235, 'duration': 6.845}, {'end': 1656.943, 'text': "so let's hit enter and it asks the confirmation.", 'start': 1653.08, 'duration': 3.863}, {'end': 1666.85, 'text': "there are about two migrations to be applied, whether we want to go or not, and i'm going to type yes, Okay, migrations were applied.", 'start': 1656.943, 'duration': 9.907}, {'end': 1674.652, 'text': 'What are migrations in general? Migration is a special file which contains some kind of change in database.', 'start': 1667.17, 'duration': 7.482}, {'end': 1681.494, 'text': 'In this case, the following migrations, migration created users table in the database.', 'start': 1674.992, 'duration': 6.502}, {'end': 1689.276, 'text': 'So if we just open phpMyAdmin, go to the free code tool, and right here we see migration table and user table.', 'start': 1681.694, 'duration': 7.582}, {'end': 1693.477, 'text': 'The user table creation script was written in the migration file.', 'start': 1689.696, 'duration': 3.781}, {'end': 1700.54, 'text': 'However, the migration table itself was created by E-framework because we just run migration.', 'start': 1693.857, 'duration': 6.683}, {'end': 1702.52, 'text': 'Whenever we run migration.', 'start': 1700.86, 'duration': 1.66}, {'end': 1711.863, 'text': 'it creates a migration file, a migration table, and inside the migration table it saves the migrations that are applied to the system.', 'start': 1702.52, 'duration': 9.343}, {'end': 1712.824, 'text': "That's good to know.", 'start': 1712.084, 'duration': 0.74}, {'end': 1715.26, 'text': 'now we have.', 'start': 1713.76, 'duration': 1.5}, {'end': 1720.102, 'text': 'we can actually create an account and just try to log in.', 'start': 1715.26, 'duration': 4.842}, {'end': 1723.463, 'text': 'okay, so we have applied all the steps.', 'start': 1720.102, 'duration': 3.361}, {'end': 1725.383, 'text': 'we have just run immigrate.', 'start': 1723.463, 'duration': 1.92}, {'end': 1727.124, 'text': 'we have set up virtual hosts.', 'start': 1725.383, 'duration': 1.741}, {'end': 1728.044, 'text': "let's have a look.", 'start': 1727.124, 'duration': 0.92}, {'end': 1731.805, 'text': "so let's just open the login page and try to log in.", 'start': 1728.044, 'duration': 3.761}, {'end': 1736.584, 'text': "it doesn't work because the account doesn't exist.", 'start': 1733.76, 'duration': 2.824}, {'end': 1747.52, 'text': "okay, let's go to the sign up page and type right here test, test at example.com and we specify the password.", 'start': 1736.584, 'duration': 10.936}, {'end': 1752.9, 'text': 'hit submit and we see thank you for registration.', 'start': 1747.52, 'duration': 5.38}, {'end': 1756, 'text': 'please check your inbox for verification email.', 'start': 1752.9, 'duration': 3.1}, {'end': 1768.382, 'text': 'eto framework advanced template comes with built-in registration, login, password reset and even to resend your verification email.', 'start': 1756, 'duration': 12.382}, {'end': 1771.463, 'text': 'okay, so this is very awesome.', 'start': 1768.382, 'duration': 3.081}, {'end': 1780.846, 'text': "so if we go to the project right now and from now on we're gonna jump between the browser and the project, and right here we see the mailer.", 'start': 1771.463, 'duration': 9.383}, {'end': 1787.533, 'text': "okay, and that's the component which is basically responsible to send mails.", 'start': 1780.846, 'duration': 6.687}, {'end': 1790.356, 'text': 'okay, and here we see the attribute.', 'start': 1787.533, 'duration': 2.823}, {'end': 1791.557, 'text': 'use file transport.', 'start': 1790.356, 'duration': 1.201}, {'end': 1793.459, 'text': "i'm going to explain these things in more details.", 'start': 1791.557, 'duration': 1.902}, {'end': 1795.46, 'text': "just i'm going to give you a quick explanation.", 'start': 1793.459, 'duration': 2.001}, {'end': 1803.271, 'text': 'use file transport, true, which means that by default the actual email sending is not implemented.', 'start': 1796.261, 'duration': 7.01}, {'end': 1809.38, 'text': 'but instead, to simulate the email send, it saves all sent emails on file path.', 'start': 1803.271, 'duration': 6.109}, {'end': 1818.351, 'text': "so let's just go to the front end runtime mail folder and right here we see one file.", 'start': 1809.38, 'duration': 8.971}, {'end': 1821.994, 'text': 'if we just open this file, we will see we.', 'start': 1818.351, 'duration': 3.643}, {'end': 1825.816, 'text': "it seems like it's a bunch of characters, but if we observe it,", 'start': 1821.994, 'duration': 3.822}, {'end': 1833.522, 'text': 'we see that the subject is account registration from my application to tested example.com.', 'start': 1825.816, 'duration': 7.706}, {'end': 1836.564, 'text': 'and if we scroll down right here, we see hello test.', 'start': 1833.522, 'duration': 3.042}, {'end': 1839.907, 'text': 'follow the link below to verify your email.', 'start': 1836.564, 'duration': 3.343}, {'end': 1841.388, 'text': "okay, that's looking good.", 'start': 1839.907, 'duration': 1.481}, {'end': 1844.749, 'text': 'however, this link looks strange.', 'start': 1842.068, 'duration': 2.681}, {'end': 1851.33, 'text': "that's because the file, this eml file, is special format file and it moves the.", 'start': 1844.749, 'duration': 6.581}, {'end': 1855.911, 'text': 'whenever it moves the content on next line, it creates equal sign.', 'start': 1851.33, 'duration': 4.581}, {'end': 1860.412, 'text': 'so we just need to remove this equal sign and move the content on the same line.', 'start': 1855.911, 'duration': 4.501}, {'end': 1863.933, 'text': "okay, let's do the same thing right here as well.", 'start': 1860.412, 'duration': 3.521}, {'end': 1866.374, 'text': "okay, so that's good.", 'start': 1863.933, 'duration': 2.441}, {'end': 1872.697, 'text': 'however, whenever there is an actual equal equal sign right here, for example, r equals something.', 'start': 1866.374, 'duration': 6.323}, {'end': 1875.038, 'text': 'it adds this 3d.', 'start': 1872.697, 'duration': 2.341}, {'end': 1879.9, 'text': "okay, so let's just remove this 3d right here and right here.", 'start': 1875.038, 'duration': 4.862}, {'end': 1889.987, 'text': "okay, that's just for because the, the file transport is used and this is sent on the file system whenever we implement the actual email sending.", 'start': 1880.842, 'duration': 9.145}, {'end': 1892.588, 'text': 'this will be a clickable link in our email.', 'start': 1889.987, 'duration': 2.601}, {'end': 1894.509, 'text': 'we just click and it will open.', 'start': 1892.588, 'duration': 1.921}, {'end': 1900.847, 'text': "okay, so let's just copy the url, go to the browser, open a new tab,", 'start': 1894.509, 'duration': 6.338}, {'end': 1908.969, 'text': 'hit the enter and right here we see your email has been confirmed and now we are actually able to log in.', 'start': 1900.847, 'duration': 8.122}, {'end': 1911.81, 'text': 'and even more, we are actually already logged in.', 'start': 1908.969, 'duration': 2.841}, {'end': 1922.933, 'text': 'okay, whenever we confirm our email, we are already logged in, but if we just log out and click the login and we just enter our username and password,', 'start': 1911.81, 'duration': 11.123}, {'end': 1924.754, 'text': 'we are actually logged in.', 'start': 1922.933, 'duration': 1.821}, {'end': 1929.035, 'text': "however, if we don't verify our email, we are not able to log in.", 'start': 1924.754, 'duration': 4.281}, {'end': 1931.135, 'text': "Okay, so that's awesome.", 'start': 1929.975, 'duration': 1.16}, {'end': 1936.497, 'text': "Let's have a look at the backend side studio.fricoetube.test.", 'start': 1932.416, 'duration': 4.081}, {'end': 1939.757, 'text': 'hit the enter and here we see something similar.', 'start': 1936.497, 'duration': 3.26}, {'end': 1947.399, 'text': "however, we don't see anything else okay, except home and login, and we cannot access home until we log in.", 'start': 1939.757, 'duration': 7.642}, {'end': 1949.26, 'text': "Okay, that's for security.", 'start': 1947.839, 'duration': 1.421}, {'end': 1958.242, 'text': 'On frontend application, if we just reload and log out, We can actually navigate between pages and see everything right there.', 'start': 1949.7, 'duration': 8.542}, {'end': 1963.963, 'text': 'We can log in, of course, but on the backend side, we cannot do anything until we log in.', 'start': 1958.622, 'duration': 5.341}, {'end': 1965.643, 'text': "So let's just log in.", 'start': 1964.403, 'duration': 1.24}, {'end': 1970.164, 'text': 'And then we can go to the homepage.', 'start': 1968.224, 'duration': 1.94}, {'end': 1972.205, 'text': 'and we are on the homepage actually and we see this.', 'start': 1970.164, 'duration': 2.041}, {'end': 1977.106, 'text': 'congratulations, you have successfully created your e-powered application.', 'start': 1972.205, 'duration': 4.901}, {'end': 1979.476, 'text': "okay, that's awesome.", 'start': 1977.955, 'duration': 1.521}, {'end': 1984.039, 'text': "i'm going to show you one thing really quickly and we're going to explore then the project folder.", 'start': 1979.476, 'duration': 4.563}, {'end': 1985.12, 'text': 'okay, look at the url.', 'start': 1984.039, 'duration': 1.081}, {'end': 1986.881, 'text': 'the url is not looking very nice.', 'start': 1985.12, 'duration': 1.761}, {'end': 1988.462, 'text': 'so we have index.php.', 'start': 1986.881, 'duration': 1.581}, {'end': 1992.645, 'text': "question mark r equals something person to, so it's a little bit ugly.", 'start': 1988.462, 'duration': 4.183}, {'end': 1994.946, 'text': 'not really user friendly urls.', 'start': 1992.645, 'duration': 2.301}, {'end': 2000.15, 'text': 'so if we just navigate between pages, we see that the last section is changed.', 'start': 1994.946, 'duration': 5.204}, {'end': 2004.553, 'text': 'okay. so let me open now php store.', 'start': 2000.15, 'duration': 4.403}, {'end': 2007.655, 'text': 'go to the front end config.', 'start': 2004.553, 'duration': 3.102}, {'end': 2013.518, 'text': "main.php. okay, i'm going to just quickly do this and then i will explain a little bit later.", 'start': 2008.335, 'duration': 5.183}, {'end': 2021.542, 'text': "okay, scroll down and right here i'm going to uncomment the following code url manager okay, just uncomment this.", 'start': 2013.518, 'duration': 8.024}, {'end': 2027.025, 'text': 'okay, actually, the same kind of config files.', 'start': 2021.542, 'duration': 5.483}, {'end': 2030.408, 'text': 'what we have in the front-end config exists in the backend config.', 'start': 2027.025, 'duration': 3.383}, {'end': 2035.954, 'text': "okay, i'm just going to choose one folder, frontend or backend and follow its explanation.", 'start': 2030.408, 'duration': 5.546}, {'end': 2042.041, 'text': 'and there exists the same configuration system, the same project structure in second folder.', 'start': 2035.954, 'duration': 6.087}], 'summary': 'Created freecode2 database, applied migrations, and set up email verification for user registration.', 'duration': 516.885, 'max_score': 1525.156, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug1525156.jpg'}, {'end': 1756, 'src': 'embed', 'start': 1728.044, 'weight': 2, 'content': [{'end': 1731.805, 'text': "so let's just open the login page and try to log in.", 'start': 1728.044, 'duration': 3.761}, {'end': 1736.584, 'text': "it doesn't work because the account doesn't exist.", 'start': 1733.76, 'duration': 2.824}, {'end': 1747.52, 'text': "okay, let's go to the sign up page and type right here test, test at example.com and we specify the password.", 'start': 1736.584, 'duration': 10.936}, {'end': 1752.9, 'text': 'hit submit and we see thank you for registration.', 'start': 1747.52, 'duration': 5.38}, {'end': 1756, 'text': 'please check your inbox for verification email.', 'start': 1752.9, 'duration': 3.1}], 'summary': 'Login failed due to non-existing account; successful registration with verification email sent.', 'duration': 27.956, 'max_score': 1728.044, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug1728044.jpg'}, {'end': 2225.315, 'src': 'embed', 'start': 2179.103, 'weight': 0, 'content': [{'end': 2187.29, 'text': 'okay?, We can have some files right here in the common and we do have those files which are shared in between these two applications.', 'start': 2179.103, 'duration': 8.187}, {'end': 2194.296, 'text': 'And we can always override some specific configuration or class in backend or frontend application.', 'start': 2187.69, 'duration': 6.606}, {'end': 2200.461, 'text': "And that's, I think, perfect project setup for building applications which needs backend as well.", 'start': 2194.476, 'duration': 5.985}, {'end': 2204.404, 'text': "Okay, so then let's explore the config files.", 'start': 2201.742, 'duration': 2.662}, {'end': 2213.209, 'text': 'In the main PHP, we have this one basically returns an associative array, which has a couple of key value peers.', 'start': 2205.184, 'duration': 8.025}, {'end': 2216.15, 'text': 'Okay, so aliases, vendor path components.', 'start': 2213.269, 'duration': 2.881}, {'end': 2218.952, 'text': "I'm going to explain this a little bit later in details.", 'start': 2216.45, 'duration': 2.502}, {'end': 2225.315, 'text': 'Then we have main local PHP, which has the same kind of structure, returns an associative array.', 'start': 2219.452, 'duration': 5.863}], 'summary': 'Files shared between applications, allows overriding config/class, perfect setup for building backend-needed applications.', 'duration': 46.212, 'max_score': 2179.103, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug2179103.jpg'}], 'start': 625.972, 'title': 'Setting up advanced project template and virtual hosts', 'summary': 'Discusses installing an advanced project template using composer, setting up virtual hosts in vs code, initializing the application, setting up the database, applying migrations, and configuring project files and structure.', 'chapters': [{'end': 870.805, 'start': 625.972, 'title': 'Advanced project template installation', 'summary': 'Discusses installing an advanced project template using composer, including navigating to the xampp htdocs folder, running composer create project, setting up virtual hosts, and executing additional commands.', 'duration': 244.833, 'highlights': ['Installing the advanced project template involves running composer create project in the XAMPP htdocs folder, which will download the ESoft E2 app advanced package and its dependencies.', 'Setting up virtual hosts for local domains such as free code tube dot test and studio free code tube dot test requires modifying the httpd.vhosts.conf file in the apache folder of XAMPP installation.']}, {'end': 1229.432, 'start': 870.805, 'title': 'Setting up virtual hosts in vs code', 'summary': 'Covers the process of setting up virtual hosts in vs code for both frontend and backend applications, including specifying domain names, paths, and server configurations, as well as editing the hosts file to map domain names to local ip addresses.', 'duration': 358.627, 'highlights': ['The process involves creating virtual hosts for both backend and frontend applications, specifying domain names and paths for each (e.g., freecodetube.test and studio.freecodetube.test), and configuring server settings such as document roots and Apache options.', 'Explanation of how virtual hosts serve content from specified paths and handle requests, with details about the URL structure, server names, and application paths.', 'Instructions for editing the hosts file to map specified domain names to the local IP address 127.0.0.1, allowing the local system to serve content for those domains.', 'Steps for restarting Apache in the XAMPP control panel to apply the virtual host changes, and the process of specifying domain names in the hosts file to map to the local IP address 127.0.0.1 for local testing.', 'Explanation of how the hosts file mapping works, allowing specified domain names to be served from the local IP address 127.0.0.1 when accessed in a web browser.']}, {'end': 1483.478, 'start': 1229.432, 'title': 'Setting up project and initializing application', 'summary': 'Covers setting up the project by downloading dependencies, initializing the application, and generating files for backend and frontend, resulting in an application running in development mode and a database configuration.', 'duration': 254.046, 'highlights': ['The project folder contains frontend and backend directories, along with common console and environments, which are the main areas of focus for making changes and configurations.', "Running 'php init' in the project installation folder initializes the application, prompting the selection of development or production mode, generating necessary files for backend and frontend.", 'Upon completion of initialization, the application is up and running in the browser, indicating successful setup and configuration.']}, {'end': 2013.518, 'start': 1483.478, 'title': 'Setting up database and applying migrations', 'summary': 'Discusses the process of creating a database using phpmyadmin, adjusting components db configuration, and applying migrations with command php emigrate, resulting in the successful creation of the freecode2 database, application of migrations, and implementation of built-in registration and login functionalities.', 'duration': 530.04, 'highlights': ['The chapter explains the process of creating a database using phpMyAdmin and setting the database name as FreeCode2 with UTF-8MB encoding, resulting in the successful creation of the database.', "The detailed step-by-step process of adjusting components db configuration and replacing the database name to 'free code tube' in the dsn and e2 up, leading to the successful configuration of the database.", 'The process of applying migrations with command php emigrate, resulting in the successful application of migrations and the creation of the migration table and user table in the database.', 'The exploration of the built-in registration, login, and email functionalities of the application, including the verification email process and the use of the mailer component to simulate email sending, showcasing the comprehensive features of the application.']}, {'end': 2455.331, 'start': 2013.518, 'title': 'Config files and project structure', 'summary': 'Covers the configuration files in the backend and frontend applications, highlighting the similarities and differences, and explains the project structure and mvc framework in detail.', 'duration': 441.813, 'highlights': ['The project setup includes a common folder for shared files between the backend and frontend applications, allowing for specific configurations or classes to be overridden, which is ideal for building applications requiring a backend (quantifiable data: project setup with common folder).', 'The configuration files, main PHP and main local PHP, return associative arrays with key-value pairs, and the local backend config main PHP contains a larger array, including ID base path and components, providing an overview of the configuration structures (quantifiable data: differences in configuration file sizes and structures).', 'The explanation of the MVC framework includes an in-depth look at the controllers, their actions, and the rendering of view files, showcasing the process of writing logic and loading/rendering data in the framework (quantifiable data: detailed explanation of the MVC framework components and their roles).']}], 'duration': 1829.359, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug625972.jpg', 'highlights': ["Running 'php init' initializes the application, prompting mode selection. (relevance: 5)", "Applying migrations with 'php emigrate' creates migration and user tables. (relevance: 4)", 'Setting up virtual hosts involves modifying httpd.vhosts.conf in XAMPP. (relevance: 3)', 'Creating a database using phpMyAdmin and adjusting db configuration. (relevance: 2)', 'Project setup includes a common folder for shared files between apps. (relevance: 1)']}, {'end': 3725.248, 'segs': [{'end': 2490.672, 'src': 'embed', 'start': 2456.912, 'weight': 5, 'content': [{'end': 2469.402, 'text': 'Then dash appears in between multiple words, and then everything is converted into lowercase, and that is the actual controller ID, hello-world.', 'start': 2456.912, 'duration': 12.49}, {'end': 2470.303, 'text': "That's the logic.", 'start': 2469.622, 'duration': 0.681}, {'end': 2472.645, 'text': "I'm going to revert this back, of course.", 'start': 2470.763, 'duration': 1.882}, {'end': 2478.509, 'text': "We just have hello controller, okay? And let's create an action for this.", 'start': 2472.945, 'duration': 5.564}, {'end': 2485.255, 'text': "So let's remove the comment and let's create an action public function.", 'start': 2479.45, 'duration': 5.805}, {'end': 2490.672, 'text': 'action index okay, just like this.', 'start': 2487.131, 'duration': 3.541}], 'summary': "Controller id 'hello-world' converted to lowercase, creating 'hello' controller with an 'index' action.", 'duration': 33.76, 'max_score': 2456.912, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug2456912.jpg'}, {'end': 3109.053, 'src': 'embed', 'start': 3080.423, 'weight': 2, 'content': [{'end': 3083.223, 'text': 'so we have bootstrap for, uh, layout.', 'start': 3080.423, 'duration': 2.8}, {'end': 3087.045, 'text': 'okay, we have the bootstrap for inputs buttons.', 'start': 3083.223, 'duration': 3.822}, {'end': 3090.246, 'text': "however, we don't actually see the navigation.", 'start': 3087.045, 'duration': 3.201}, {'end': 3092.987, 'text': "okay, home and login, we don't see these buttons.", 'start': 3090.246, 'duration': 2.741}, {'end': 3102.87, 'text': "so that's because the code actually written in views layouts, main php, is for bootstrap 3..", 'start': 3093.687, 'duration': 9.183}, {'end': 3106.172, 'text': "so let's observe this layout file now.", 'start': 3102.87, 'duration': 3.302}, {'end': 3109.053, 'text': 'so we have a lot of use statements right here.', 'start': 3106.172, 'duration': 2.881}], 'summary': 'Transcript discusses issues with the navigation buttons due to code written for bootstrap 3.', 'duration': 28.63, 'max_score': 3080.423, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug3080423.jpg'}, {'end': 3564.993, 'src': 'heatmap', 'start': 3267.81, 'weight': 0, 'content': [{'end': 3271.094, 'text': 'we created the application, this application, okay?', 'start': 3267.81, 'duration': 3.284}, {'end': 3272.355, 'text': 'And we run this application.', 'start': 3271.194, 'duration': 1.161}, {'end': 3281.486, 'text': 'And whenever we create an application and run this, this application basically is saved inside this app static property of E class.', 'start': 3272.896, 'duration': 8.59}, {'end': 3289.315, 'text': 'Okay We can access this particular application, the application which is currently running, and there is only one application.', 'start': 3281.826, 'duration': 7.489}, {'end': 3292.798, 'text': 'Okay And the application has a couple of properties.', 'start': 3289.335, 'duration': 3.463}, {'end': 3296.901, 'text': 'Okay, language, for example, charset, for example,', 'start': 3292.979, 'duration': 3.922}, {'end': 3304.004, 'text': 'and these are the properties of the application which can be configured and changed in the configuration files, okay?', 'start': 3296.901, 'duration': 7.103}, {'end': 3309.587, 'text': 'So if we just open, for example, config right here and main.php, okay?', 'start': 3304.264, 'duration': 5.323}, {'end': 3318.691, 'text': 'So we have a lot of things going on right here and we have ID base path and we can actually add right here language, okay?', 'start': 3309.887, 'duration': 8.804}, {'end': 3328.098, 'text': 'this language, for example, in US, okay, and that is the language which will be outputted right here.', 'start': 3320.973, 'duration': 7.125}, {'end': 3333.621, 'text': 'okay, and we can even access the other properties if we need id, for example.', 'start': 3328.098, 'duration': 5.523}, {'end': 3338.344, 'text': 'so we have this id right here and phpStorm can understand this as well.', 'start': 3333.621, 'duration': 4.723}, {'end': 3341.046, 'text': 'so we have base path right here.', 'start': 3338.344, 'duration': 2.702}, {'end': 3344.328, 'text': 'okay, we have components area right here,', 'start': 3341.046, 'duration': 3.282}, {'end': 3354.96, 'text': 'because we have also components in the configuration and all of them are part of application and they can be accessed from any place where we want.', 'start': 3344.328, 'duration': 10.632}, {'end': 3362.107, 'text': "okay. so let's just, Let's just leave language right here, okay?", 'start': 3354.96, 'duration': 7.147}, {'end': 3366.73, 'text': 'And we have an update of phpStorm.', 'start': 3363.708, 'duration': 3.022}, {'end': 3367.51, 'text': "I'm going to close this.", 'start': 3366.77, 'duration': 0.74}, {'end': 3370.932, 'text': 'And then we are outputting right here a title.', 'start': 3368.611, 'duration': 2.321}, {'end': 3375.255, 'text': 'We are encoding the title and outputting in the title tag.', 'start': 3372.313, 'duration': 2.942}, {'end': 3376.756, 'text': 'Nothing special going on right here.', 'start': 3375.335, 'duration': 1.421}, {'end': 3380.939, 'text': "And then let's observe the RAP, okay? So we have begin, body, end, body.", 'start': 3377.517, 'duration': 3.422}, {'end': 3381.779, 'text': 'We talked about this.', 'start': 3380.959, 'duration': 0.82}, {'end': 3383.3, 'text': "So let's open RAP.", 'start': 3382.28, 'duration': 1.02}, {'end': 3386.562, 'text': 'And inside here, we are using navbar class.', 'start': 3383.72, 'duration': 2.842}, {'end': 3388.564, 'text': 'This is a UI widget.', 'start': 3387.163, 'duration': 1.401}, {'end': 3392.486, 'text': 'And UI widgets are heavily used in E-framework.', 'start': 3389.504, 'duration': 2.982}, {'end': 3402.792, 'text': 'And if you get from the beginning, it seems like a confusing and people prefer to write plain HTML rather than using UI widgets.', 'start': 3392.926, 'duration': 9.866}, {'end': 3409.556, 'text': 'Okay But if you get familiar with UI widgets, actually, they can save you some time.', 'start': 3403.312, 'duration': 6.244}, {'end': 3416.06, 'text': 'Okay In this case, the framework is using the basic template is using navbar widget.', 'start': 3410.056, 'duration': 6.004}, {'end': 3420.803, 'text': 'Okay, which has brand label and brand url and a couple of options.', 'start': 3416.46, 'duration': 4.343}, {'end': 3425.788, 'text': 'this brand label and brand url are the fields which is displayed right here.', 'start': 3420.803, 'duration': 4.985}, {'end': 3431.693, 'text': 'okay, my application, my application, is the application name which can be configured.', 'start': 3425.788, 'duration': 5.905}, {'end': 3441.309, 'text': 'okay, if we just open backend config main right here and give it a name free code tube.', 'start': 3431.693, 'duration': 9.616}, {'end': 3443.81, 'text': "okay, so that's the application name.", 'start': 3441.309, 'duration': 2.501}, {'end': 3448.513, 'text': 'okay, if i save this and reload the browser right here, i see free code tube.', 'start': 3443.81, 'duration': 4.703}, {'end': 3449.894, 'text': "okay, that's awesome.", 'start': 3448.513, 'duration': 1.381}, {'end': 3457.958, 'text': "so let's go to the layout again and we have home url, which is the main url the application has, and couple of options.", 'start': 3449.894, 'duration': 8.064}, {'end': 3462.042, 'text': "So let's just remove these options because they are for bootstrap three.", 'start': 3458.238, 'duration': 3.804}, {'end': 3465.865, 'text': "Okay Let's just remove this, go to the browser, reload.", 'start': 3462.382, 'duration': 3.483}, {'end': 3468.608, 'text': 'And right here we see home and login.', 'start': 3466.025, 'duration': 2.583}, {'end': 3473.953, 'text': 'Okay This is, these are bootstrap force, uh, navigation.', 'start': 3468.928, 'duration': 5.025}, {'end': 3478.297, 'text': "Okay So let's scroll down and see what happens right here.", 'start': 3474.453, 'duration': 3.844}, {'end': 3479.798, 'text': 'If we just log in, okay.', 'start': 3478.417, 'duration': 1.381}, {'end': 3482.641, 'text': 'Test just like this.', 'start': 3480.599, 'duration': 2.042}, {'end': 3488.229, 'text': "Okay, so I'm logged in.", 'start': 3487.188, 'duration': 1.041}, {'end': 3492.595, 'text': "This logo is not looking very nice, but I'm actually logged in.", 'start': 3488.59, 'duration': 4.005}, {'end': 3493.756, 'text': "So let's have a look.", 'start': 3493.055, 'duration': 0.701}, {'end': 3496.48, 'text': 'So we have menu items array right here.', 'start': 3494.177, 'duration': 2.303}, {'end': 3498.602, 'text': 'Okay, then we do some things.', 'start': 3496.5, 'duration': 2.102}, {'end': 3503.428, 'text': 'Inside the menu items, we just push home, okay, with its URL.', 'start': 3498.923, 'duration': 4.505}, {'end': 3510.763, 'text': 'then right here we check if the application user and what is this user okay.', 'start': 3504.517, 'duration': 6.246}, {'end': 3515.126, 'text': 'so the application is a application which is currently active and running,', 'start': 3510.763, 'duration': 4.363}, {'end': 3521.992, 'text': 'which we created in the backend web index php and the user is its component.', 'start': 3515.126, 'duration': 6.866}, {'end': 3524.675, 'text': 'okay, what is a component component?', 'start': 3521.992, 'duration': 2.683}, {'end': 3526.636, 'text': 'is a singleton object.', 'start': 3524.675, 'duration': 1.961}, {'end': 3530.82, 'text': 'okay, we define components in the configuration phase.', 'start': 3526.636, 'duration': 4.184}, {'end': 3535.625, 'text': 'okay, if we go to the backend config main php right here we have components.', 'start': 3530.82, 'duration': 4.805}, {'end': 3547.437, 'text': 'okay, and we define these components during the configuration phase and the components then can be accessed using the following way e up and the component key.', 'start': 3535.625, 'duration': 11.812}, {'end': 3552.742, 'text': 'Okay, in this case we have user component and we can access this user component.', 'start': 3548.038, 'duration': 4.704}, {'end': 3555.064, 'text': 'We have a request component as well.', 'start': 3553.243, 'duration': 1.821}, {'end': 3558.507, 'text': 'We have session component, we have log component, and so on.', 'start': 3555.344, 'duration': 3.163}, {'end': 3562.03, 'text': 'And we can access them, all of them, in the following way.', 'start': 3558.827, 'duration': 3.203}, {'end': 3564.993, 'text': 'E up request, for example.', 'start': 3562.491, 'duration': 2.502}], 'summary': 'An application is created and configured with properties in e-framework, with components such as user, request, and session.', 'duration': 76.518, 'max_score': 3267.81, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug3267810.jpg'}, {'end': 3503.428, 'src': 'embed', 'start': 3474.453, 'weight': 1, 'content': [{'end': 3478.297, 'text': "Okay So let's scroll down and see what happens right here.", 'start': 3474.453, 'duration': 3.844}, {'end': 3479.798, 'text': 'If we just log in, okay.', 'start': 3478.417, 'duration': 1.381}, {'end': 3482.641, 'text': 'Test just like this.', 'start': 3480.599, 'duration': 2.042}, {'end': 3488.229, 'text': "Okay, so I'm logged in.", 'start': 3487.188, 'duration': 1.041}, {'end': 3492.595, 'text': "This logo is not looking very nice, but I'm actually logged in.", 'start': 3488.59, 'duration': 4.005}, {'end': 3493.756, 'text': "So let's have a look.", 'start': 3493.055, 'duration': 0.701}, {'end': 3496.48, 'text': 'So we have menu items array right here.', 'start': 3494.177, 'duration': 2.303}, {'end': 3498.602, 'text': 'Okay, then we do some things.', 'start': 3496.5, 'duration': 2.102}, {'end': 3503.428, 'text': 'Inside the menu items, we just push home, okay, with its URL.', 'start': 3498.923, 'duration': 4.505}], 'summary': "Logged in successfully, added 'home' to menu items array.", 'duration': 28.975, 'max_score': 3474.453, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug3474453.jpg'}], 'start': 2456.912, 'title': 'Web application development', 'summary': 'Covers topics such as controller and view flow, troubleshooting bootstrap 4 migration, e-framework layout and application properties, and web application configuration and components. it includes examples, conventions, and processes for creating and troubleshooting, as well as the utilization of core components in web application development.', 'chapters': [{'end': 2815.065, 'start': 2456.912, 'title': 'Controller and view flow', 'summary': "Explains the creation of a controller action with an example of the 'hello world' application, along with the convention for naming view files and the process of installing bootstrap 4 using composer.", 'duration': 358.153, 'highlights': ["The logic of creating an action in the controller involves using a normal function with an 'action' prefix and a naming convention similar to that of the controller, with the action having its own ID.", 'Naming the view file the same as the action ID is a good practice, and following this convention is recommended for rendering views in the controller.', "The process of installing Bootstrap 4 involves using Composer to require the 'esoft/e2-bootstrap' package and removing the old Bootstrap package using the integrated terminal.", "The folder naming convention for view files follows the same ID as that of the controller, and creating a folder with the appropriate name and an 'index.php' file allows for rendering the view within the controller's flow."]}, {'end': 3159.645, 'start': 2815.065, 'title': 'Troubleshooting bootstrap 4 migration', 'summary': 'Explains the process of troubleshooting errors encountered after migrating from bootstrap to bootstrap 4, including identifying and replacing incorrect namespaces, and the dependencies of asset bundles.', 'duration': 344.58, 'highlights': ['The errors occur due to the incorrect usage of namespaces, such as accessing hello index and including classes from the wrong namespace, leading to errors in backend views and common widgets.', 'The AppAsset class is dependent on eWebEAsset and eBootstrapBootstrapAsset classes, and the dependencies of these assets, along with their namespaces, need to be correctly managed to resolve errors.', 'The layout file contains PHP code and special events triggered by methods like begin page, begin body, end body, and end page, illustrating the default usage of PHP in Eto framework for managing views.']}, {'end': 3449.894, 'start': 3159.645, 'title': 'E-framework: layout and application properties', 'summary': 'Explains the layout structure in e-framework, including the code placement for new layouts and the registration of css files, as well as the configuration and usage of application properties like language and charset.', 'duration': 290.249, 'highlights': ['The framework specifies the code placement for new layouts, such as calling specific code after html, before body closing tag, and exactly after body closing tag, ensuring proper layout structure and functionality.', 'The registration of CSS files in E-framework involves the use of app asset bundle to ensure that dependencies are included before the site CSS, enhancing page performance and functionality.', 'The backend of the E-framework allows for the configuration and usage of application properties like language and charset, which can be modified in the configuration files, offering flexibility and customization for applications.']}, {'end': 3725.248, 'start': 3449.894, 'title': 'Web application configuration and components', 'summary': "Explores the configuration and utilization of core components in a web application, including the use of key value pairs and the creation of singleton objects, with a focus on the main configuration files and their impact on the application's functionality and structure.", 'duration': 275.354, 'highlights': ['The configuration and utilization of core components in a web application, including the use of key value pairs and the creation of singleton objects', 'Explanation of how special classes are created and given key value pairs when instances are created', "The impact of the main configuration files on the application's functionality and structure"]}], 'duration': 1268.336, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug2456912.jpg', 'highlights': ["The process of installing Bootstrap 4 involves using Composer to require the 'esoft/e2-bootstrap' package and removing the old Bootstrap package using the integrated terminal.", "The logic of creating an action in the controller involves using a normal function with an 'action' prefix and a naming convention similar to that of the controller, with the action having its own ID.", "The folder naming convention for view files follows the same ID as that of the controller, and creating a folder with the appropriate name and an 'index.php' file allows for rendering the view within the controller's flow.", 'The errors occur due to the incorrect usage of namespaces, such as accessing hello index and including classes from the wrong namespace, leading to errors in backend views and common widgets.', 'The framework specifies the code placement for new layouts, such as calling specific code after html, before body closing tag, and exactly after body closing tag, ensuring proper layout structure and functionality.', 'The backend of the E-framework allows for the configuration and usage of application properties like language and charset, which can be modified in the configuration files, offering flexibility and customization for applications.', 'The registration of CSS files in E-framework involves the use of app asset bundle to ensure that dependencies are included before the site CSS, enhancing page performance and functionality.', 'The layout file contains PHP code and special events triggered by methods like begin page, begin body, end body, and end page, illustrating the default usage of PHP in Eto framework for managing views.', 'The configuration and utilization of core components in a web application, including the use of key value pairs and the creation of singleton objects']}, {'end': 6429.535, 'segs': [{'end': 5604.37, 'src': 'heatmap', 'start': 4833.631, 'weight': 1, 'content': [{'end': 4838.733, 'text': "um, There's some partial content in its own files, for example.", 'start': 4833.631, 'duration': 5.102}, {'end': 4843.574, 'text': 'so I generally Do like this for example, underscore header?', 'start': 4838.733, 'duration': 4.841}, {'end': 4852.337, 'text': "Okay, and I'm gonna move a header content right here and I'm gonna create one more file underscore sidebar.", 'start': 4843.594, 'duration': 8.743}, {'end': 4855.2, 'text': 'okay. So these are just PHP files.', 'start': 4852.337, 'duration': 2.863}, {'end': 4865.009, 'text': 'Now I will go to the main.php and take this header content, the whole navbar basically, and move it in the header.php right here.', 'start': 4855.4, 'duration': 9.609}, {'end': 4870.134, 'text': 'However, we need to import these classes.', 'start': 4866.37, 'duration': 3.764}, {'end': 4873.577, 'text': 'navclass, for example, hit Alt-Enter, import this one.', 'start': 4870.234, 'duration': 3.343}, {'end': 4875.9, 'text': "Let's import navbar as well.", 'start': 4873.858, 'duration': 2.042}, {'end': 4884.387, 'text': 'and we have right here our header.php and i need to use this header.php in the main.php layout right now.', 'start': 4876.54, 'duration': 7.847}, {'end': 4892.294, 'text': "okay, so i'm going to use this render method and i'm going to specify header.", 'start': 4884.387, 'duration': 7.907}, {'end': 4895.577, 'text': 'okay, i want to render header right here.', 'start': 4892.294, 'duration': 3.283}, {'end': 4896.878, 'text': "okay, that's awesome.", 'start': 4895.577, 'duration': 1.301}, {'end': 4902.535, 'text': "let's have a look in the browser on the back-end side and I see the exact same result.", 'start': 4896.878, 'duration': 5.657}, {'end': 4905.701, 'text': 'Now we need Sidebar as well.', 'start': 4903.437, 'duration': 2.264}, {'end': 4910.43, 'text': "So I'm going to render Sidebar, just like this.", 'start': 4905.962, 'duration': 4.468}, {'end': 4918.087, 'text': 'However, I need a couple of more classes and divs to create the proper layout.', 'start': 4911.704, 'duration': 6.383}, {'end': 4921.888, 'text': "So I'm going to create a main tag right here.", 'start': 4918.767, 'duration': 3.121}, {'end': 4930.272, 'text': "Inside the main tag, I'm going to put this sidebar on the left side, and on the right side, we're going to have the whole content.", 'start': 4923.049, 'duration': 7.223}, {'end': 4934.775, 'text': "However, I don't want this container class on this content.", 'start': 4930.992, 'duration': 3.783}, {'end': 4938.919, 'text': "I'll just give it a class content wrapper, for example.", 'start': 4935.236, 'duration': 3.683}, {'end': 4941.681, 'text': 'Give it a little bit of padding, just like this.', 'start': 4939.239, 'duration': 2.442}, {'end': 4947.485, 'text': "Then on the main class, I'm going to give it a class of display flex.", 'start': 4943.082, 'duration': 4.403}, {'end': 4952.129, 'text': "On the wrap class, I'm going to give it the full height.", 'start': 4949.807, 'duration': 2.322}, {'end': 4954.991, 'text': 'the wrap class 800.', 'start': 4953.63, 'duration': 1.361}, {'end': 4962.514, 'text': "I'm going to give it d flex for display flex, but we need to have flex column.", 'start': 4954.991, 'duration': 7.523}, {'end': 4967.637, 'text': 'okay, just like this, and this one will be the first, this one will be the next.', 'start': 4962.514, 'duration': 5.123}, {'end': 4972.319, 'text': 'and this wall, this one, has also display flex.', 'start': 4967.637, 'duration': 4.682}, {'end': 4973.82, 'text': "so let's have a look.", 'start': 4972.319, 'duration': 1.501}, {'end': 4976.041, 'text': "we don't have anything in the sidebar actually.", 'start': 4973.82, 'duration': 2.221}, {'end': 4978.262, 'text': "so let's put something in the sidebar.", 'start': 4976.041, 'duration': 2.221}, {'end': 4980.963, 'text': "okay, so I'm going to use bootstrap.", 'start': 4978.262, 'duration': 2.701}, {'end': 4987.067, 'text': 'so let me just open get-bootstrap.com.', 'start': 4980.963, 'duration': 6.104}, {'end': 4989.349, 'text': 'Okay, so we are using Bootstrap 4..', 'start': 4987.067, 'duration': 2.282}, {'end': 4998.007, 'text': "Go to its documentation, go to components and right here i'm going to search for list group.", 'start': 4989.349, 'duration': 8.658}, {'end': 5000.93, 'text': 'i want to take the list group and use that.', 'start': 4998.007, 'duration': 2.923}, {'end': 5002.211, 'text': 'okay, this one just.', 'start': 5000.93, 'duration': 1.281}, {'end': 5005.713, 'text': 'i want the list group which has anchor links inside.', 'start': 5002.211, 'duration': 3.502}, {'end': 5008.015, 'text': "so let's just copy this one.", 'start': 5005.713, 'duration': 2.302}, {'end': 5010.957, 'text': "okay, so i'm going to take this.", 'start': 5008.015, 'duration': 2.942}, {'end': 5014.7, 'text': 'okay, go to right here and paste this list group.', 'start': 5010.957, 'duration': 3.743}, {'end': 5016.121, 'text': "okay, let's have a look.", 'start': 5014.7, 'duration': 1.421}, {'end': 5023.385, 'text': 'so go to the Backend, reload the page and on the left side I see this list group.', 'start': 5016.121, 'duration': 7.264}, {'end': 5026.488, 'text': 'okay?. And I see this main content right here.', 'start': 5023.385, 'duration': 3.103}, {'end': 5030.171, 'text': 'Actually, we need to apply more styles.', 'start': 5028.31, 'duration': 1.861}, {'end': 5038.359, 'text': "So let me make a slight cleanup, okay? So let's remove footer, okay? We don't want footer at all.", 'start': 5030.672, 'duration': 7.687}, {'end': 5042.063, 'text': "Let's open this index.php.", 'start': 5040.121, 'duration': 1.942}, {'end': 5045.874, 'text': "inside site and let's clean up everything.", 'start': 5043.433, 'duration': 2.441}, {'end': 5049.436, 'text': "okay, so let's just call this uh, index.", 'start': 5045.874, 'duration': 3.562}, {'end': 5050.777, 'text': "okay, let's save this.", 'start': 5049.436, 'duration': 1.341}, {'end': 5051.877, 'text': 'just have a look.', 'start': 5050.777, 'duration': 1.1}, {'end': 5053.358, 'text': "okay, that's looking.", 'start': 5051.877, 'duration': 1.481}, {'end': 5059.421, 'text': 'uh, better, actually, i want to use for this sidebar navigation also nav widget.', 'start': 5053.358, 'duration': 6.063}, {'end': 5069.606, 'text': "okay, this nav widget basically gives me possibility that whenever i navigate between pages, it automatically activates the url i'm, i'm on.", 'start': 5059.421, 'duration': 10.185}, {'end': 5077.01, 'text': "okay, so let's just go right here in the in the sidebar and i'm going to change this with nav widget.", 'start': 5070.026, 'duration': 6.984}, {'end': 5081.512, 'text': "okay, so let's just use php echo.", 'start': 5077.01, 'duration': 4.502}, {'end': 5085.074, 'text': "okay, nav, i'm using bootstrap's nav widget.", 'start': 5081.512, 'duration': 3.562}, {'end': 5087.994, 'text': 'okay, And right here I need to specify items.', 'start': 5085.074, 'duration': 2.92}, {'end': 5090.475, 'text': 'The only thing which is required is items.', 'start': 5088.635, 'duration': 1.84}, {'end': 5092.675, 'text': 'Each item is an array.', 'start': 5091.075, 'duration': 1.6}, {'end': 5095.976, 'text': 'And then right here, we have label.', 'start': 5093.356, 'duration': 2.62}, {'end': 5108.859, 'text': "And I'm going to give two items, like dashboard, which will have a URL of, let's give it a URL as an array, by all means.", 'start': 5096.756, 'duration': 12.103}, {'end': 5113.46, 'text': "Let's give it a URL of site slash index.", 'start': 5109.239, 'duration': 4.221}, {'end': 5114.84, 'text': "That's going to be the dashboard.", 'start': 5113.56, 'duration': 1.28}, {'end': 5122.668, 'text': "and we're going to have second item label to be videos.", 'start': 5115.78, 'duration': 6.888}, {'end': 5127.914, 'text': 'okay, and the url needs to be as an array.', 'start': 5122.668, 'duration': 5.246}, {'end': 5133.258, 'text': "video controllers, index action okay, so that's going to be the url.", 'start': 5127.914, 'duration': 5.344}, {'end': 5134.819, 'text': "so let's remove this.", 'start': 5133.258, 'duration': 1.561}, {'end': 5139.861, 'text': "but we need to give a couple of classes to the nav widget, otherwise it won't look nice.", 'start': 5134.819, 'duration': 5.042}, {'end': 5142.182, 'text': "so let's just remove this and have a look in the browser.", 'start': 5139.861, 'duration': 2.321}, {'end': 5146.144, 'text': 'okay. so we have this next to each other.', 'start': 5142.182, 'duration': 3.962}, {'end': 5148.645, 'text': "so i'm going to give it options.", 'start': 5146.144, 'duration': 2.501}, {'end': 5152.287, 'text': 'okay, these options always means attributes.', 'start': 5148.645, 'duration': 3.642}, {'end': 5154.028, 'text': 'okay, html attributes.', 'start': 5152.287, 'duration': 1.741}, {'end': 5171.983, 'text': "so we're going to specify right here class html attribute to be d flex, flex column okay, and that's okay, and we can also give it nav pills,", 'start': 5154.588, 'duration': 17.395}, {'end': 5172.584, 'text': 'for example.', 'start': 5171.983, 'duration': 0.601}, {'end': 5174.645, 'text': 'okay, just like this.', 'start': 5173.084, 'duration': 1.561}, {'end': 5178.709, 'text': "okay, and we're gonna change appearance slightly.", 'start': 5174.645, 'duration': 4.064}, {'end': 5182.111, 'text': 'okay. so for this we need to write a little bit of CSS.', 'start': 5178.709, 'duration': 3.402}, {'end': 5184.794, 'text': 'I will try to write as less CSS as possible.', 'start': 5182.111, 'duration': 2.683}, {'end': 5192.68, 'text': "I want to fully focus on a framework, not spend some time on on writing CSS, but let's make very minimalistic changes.", 'start': 5184.794, 'duration': 7.886}, {'end': 5197.744, 'text': 'so go to the backend, web CSS, and right here we have the site CSS.', 'start': 5192.68, 'duration': 5.064}, {'end': 5201.327, 'text': 'okay, which is also registered in the app asset.', 'start': 5197.744, 'duration': 3.583}, {'end': 5204.968, 'text': "okay. so let's make some cleanups right here.", 'start': 5201.747, 'duration': 3.221}, {'end': 5207.309, 'text': "i'm going to remove everything what we have right now.", 'start': 5204.968, 'duration': 2.341}, {'end': 5212.011, 'text': "i don't want anything and make some changes.", 'start': 5207.309, 'duration': 4.702}, {'end': 5218.053, 'text': "actually, i'm going to quickly copy and paste some css and i will give you a quick explanation.", 'start': 5212.011, 'duration': 6.042}, {'end': 5220.916, 'text': 'okay, Okay, so here we go.', 'start': 5218.053, 'duration': 2.863}, {'end': 5222.918, 'text': 'The only thing.', 'start': 5222.458, 'duration': 0.46}, {'end': 5232.428, 'text': "what we need to change inside the sidebar is that let's put everything this nav inside a div which has a class, not div,", 'start': 5222.918, 'duration': 9.51}, {'end': 5234.349, 'text': "but let's give it an aside class.", 'start': 5232.428, 'duration': 1.921}, {'end': 5236.392, 'text': "Okay, let's put this inside aside.", 'start': 5234.41, 'duration': 1.982}, {'end': 5240.855, 'text': 'okay, inside css we just change some links.', 'start': 5237.012, 'duration': 3.843}, {'end': 5248.58, 'text': 'okay, we just remove border radius, we just give the color and yeah, some very, very basic things of the links,', 'start': 5240.855, 'duration': 7.725}, {'end': 5251.101, 'text': 'which is which is displayed through this nav.', 'start': 5248.58, 'duration': 2.521}, {'end': 5255.644, 'text': "okay, let's save this and let's see in the browser and look at this.", 'start': 5251.101, 'duration': 4.543}, {'end': 5257.766, 'text': 'okay, this looks much better.', 'start': 5255.644, 'duration': 2.122}, {'end': 5261.388, 'text': 'okay, we can actually give this a minimum width.', 'start': 5257.766, 'duration': 3.622}, {'end': 5262.589, 'text': "okay, it's to have.", 'start': 5261.388, 'duration': 1.201}, {'end': 5274.514, 'text': "So let's go to site CSS right here and for a side we can give minimum width to be like 200 pixels, for example.", 'start': 5263.649, 'duration': 10.865}, {'end': 5277.355, 'text': "Okay, so let's just reload and this is how it looks like.", 'start': 5274.694, 'duration': 2.661}, {'end': 5284.198, 'text': "And whenever we are on the dashboard page, this is active because we specified site index and we're on site index.", 'start': 5277.655, 'duration': 6.543}, {'end': 5287.56, 'text': "The videos page doesn't exist and this is how it looks like.", 'start': 5284.578, 'duration': 2.982}, {'end': 5291.726, 'text': "so let's give this one a little bit of shadow.", 'start': 5288.2, 'duration': 3.526}, {'end': 5299.578, 'text': "so i'm going to give it a a shadow shadow, sm maybe, or just shadow.", 'start': 5291.726, 'duration': 7.852}, {'end': 5301.541, 'text': "let's give it just shadow, okay.", 'start': 5299.578, 'duration': 1.963}, {'end': 5308.685, 'text': 'so this looks good and i need to specify, um, also the height.', 'start': 5301.541, 'duration': 7.144}, {'end': 5310.366, 'text': 'the height should be the full height.', 'start': 5308.685, 'duration': 1.681}, {'end': 5320.748, 'text': "so for this i think we need to go to the layouts, main, php, and right here let's give this uh, main and inline style just quickly,", 'start': 5310.366, 'duration': 10.382}, {'end': 5322.989, 'text': 'or we can put this in the in the css.', 'start': 5320.748, 'duration': 2.241}, {'end': 5330.166, 'text': 'also right here main needs to have flex of one, okay, just like this.', 'start': 5322.989, 'duration': 7.177}, {'end': 5339.29, 'text': 'so this one now has full uh height and this content also needs to have some flex to be stretched till the end, okay.', 'start': 5330.166, 'duration': 9.124}, {'end': 5344.392, 'text': "so let's do also like this, and the class is called content wrapper.", 'start': 5339.29, 'duration': 5.102}, {'end': 5348.233, 'text': "okay. so let's take this content wrapper inside site css.", 'start': 5344.392, 'duration': 3.841}, {'end': 5356.425, 'text': "let's give it a flex of one, some quick css, okay, that's much better.", 'start': 5348.233, 'duration': 8.192}, {'end': 5360.508, 'text': "and let's give shadow to the navbar as well, to the header, okay.", 'start': 5356.425, 'duration': 4.083}, {'end': 5362.129, 'text': 'so here we have this number.', 'start': 5360.508, 'duration': 1.621}, {'end': 5373.137, 'text': "let's specify options right here and let's just put right here class to be equal to shadow, okay.", 'start': 5362.129, 'duration': 11.008}, {'end': 5378.239, 'text': "so let's save this, let's reload and we see this shadow.", 'start': 5373.137, 'duration': 5.102}, {'end': 5382.042, 'text': "uh, let's give it a shadow of sm.", 'start': 5378.239, 'duration': 3.803}, {'end': 5387.365, 'text': "okay, and i don't see these links anymore because of the shadow.", 'start': 5382.042, 'duration': 5.323}, {'end': 5389.366, 'text': 'i think okay.', 'start': 5387.365, 'duration': 2.001}, {'end': 5391.587, 'text': "so i don't see these links anymore.", 'start': 5389.366, 'duration': 2.221}, {'end': 5393.188, 'text': "so let's have a look.", 'start': 5391.587, 'duration': 1.601}, {'end': 5401.212, 'text': "so let's open actually the navbar, okay, from here, And let's scroll down to the template.", 'start': 5393.188, 'duration': 8.024}, {'end': 5406.76, 'text': "and I'm going to take these classes NavBarLight, PGLight, okay?, I need these classes.", 'start': 5401.212, 'duration': 5.548}, {'end': 5415.671, 'text': "So let's just take this, and inside the class add, okay? NavBarExpandLG, NavBarLight, PGLight, and ShadowSM.", 'start': 5407.1, 'duration': 8.571}, {'end': 5417.373, 'text': "let's have a look.", 'start': 5416.252, 'duration': 1.121}, {'end': 5420.054, 'text': "okay, it's good, we have this small shadow.", 'start': 5417.373, 'duration': 2.681}, {'end': 5421.395, 'text': 'we have the sidebar.', 'start': 5420.054, 'duration': 1.341}, {'end': 5423.537, 'text': 'the dashboard is activated.', 'start': 5421.395, 'duration': 2.142}, {'end': 5425.518, 'text': 'so this is our basic layout.', 'start': 5423.537, 'duration': 1.981}, {'end': 5432.182, 'text': 'however, if we log out, we see our login form inside this layout, which is not very good.', 'start': 5425.518, 'duration': 6.664}, {'end': 5441.749, 'text': "so we need to have a different layout for, uh, for like login for okay, so let's implement this one as well.", 'start': 5432.182, 'duration': 9.567}, {'end': 5453.397, 'text': "so let's go to the views layout right here, and i'm going to actually copy and paste this main php and call it our php.", 'start': 5441.749, 'duration': 11.648}, {'end': 5458.86, 'text': 'okay, so this is the second layout we want to have.', 'start': 5453.397, 'duration': 5.463}, {'end': 5463.323, 'text': "let's hit the enter and we need to change actually some things.", 'start': 5458.86, 'duration': 4.463}, {'end': 5475.011, 'text': 'but The thing is that we have to still leave this doctype HTML, all the head stuff, and we just need to remove the sidebar, okay, from this auth.php.', 'start': 5463.323, 'duration': 11.688}, {'end': 5481.296, 'text': "And we, it seems like we will have a repetitive code, which is something I really don't like.", 'start': 5475.411, 'duration': 5.885}, {'end': 5484.379, 'text': "Okay, I don't want the code to be repeated.", 'start': 5481.856, 'duration': 2.523}, {'end': 5491.225, 'text': "Okay, if I just remove this sidebar from here and we will use this out layout and let's actually do this.", 'start': 5484.719, 'duration': 6.506}, {'end': 5497.691, 'text': "Okay, so I'll go to the site controller, go to the login and right here I want to change the layout.", 'start': 5491.325, 'duration': 6.366}, {'end': 5502.974, 'text': 'Okay, so this layout to be equal to auth.', 'start': 5497.851, 'duration': 5.123}, {'end': 5507.337, 'text': "okay, now i'm going to use auth layout for this particular action.", 'start': 5502.974, 'duration': 4.363}, {'end': 5511.76, 'text': "so let's save this, reload the page and yeah, it looks good.", 'start': 5507.337, 'duration': 4.423}, {'end': 5519.085, 'text': "so we don't have the sidebar, however, in the auth php and in the main php as well.", 'start': 5511.76, 'duration': 7.325}, {'end': 5521.066, 'text': 'so we have this repetitive code.', 'start': 5519.085, 'duration': 1.981}, {'end': 5524.428, 'text': 'okay, so i just want to avoid this.', 'start': 5521.066, 'duration': 3.362}, {'end': 5535.713, 'text': "so for this i'm going to create a base layout file okay, base php And I'm going to basically go to the main PHP.", 'start': 5524.428, 'duration': 11.285}, {'end': 5537.614, 'text': 'This is base PHP.', 'start': 5536.353, 'duration': 1.261}, {'end': 5538.834, 'text': "Okay, let's do like this.", 'start': 5537.954, 'duration': 0.88}, {'end': 5544.815, 'text': 'Inside base PHP, I want to remove this content.', 'start': 5539.134, 'duration': 5.681}, {'end': 5552.197, 'text': 'Okay And I will just write here PHP echo content variable.', 'start': 5545.215, 'duration': 6.982}, {'end': 5555.737, 'text': "Okay I'm outputting right here content variable.", 'start': 5552.537, 'duration': 3.2}, {'end': 5557.998, 'text': "Let's now open main PHP.", 'start': 5556.198, 'duration': 1.8}, {'end': 5567.465, 'text': "i'm going to remove the top area okay, everything and the bottom area everything.", 'start': 5558.678, 'duration': 8.787}, {'end': 5573.169, 'text': 'okay, i just leave this wrap, but i need to use the base layout.', 'start': 5567.465, 'duration': 5.704}, {'end': 5579.994, 'text': 'okay, i want this content to be injected inside the base layouts.', 'start': 5573.169, 'duration': 6.825}, {'end': 5583.556, 'text': 'uh, this place where where content variable is used.', 'start': 5579.994, 'duration': 3.562}, {'end': 5589.747, 'text': "so for this i'm going to use this begin content method.", 'start': 5583.556, 'duration': 6.191}, {'end': 5601.63, 'text': "okay, and i'm going to specify right here the path where is the base php i want to like begin content with, and i'm going to use it backend.", 'start': 5589.747, 'duration': 11.883}, {'end': 5604.37, 'text': "okay, i'm going to explain this in a moment.", 'start': 5601.63, 'duration': 2.74}], 'summary': 'Developing php files to create a website layout with sidebar, navbar, and content. using bootstrap 4 and applying minimal css changes. implementing different layouts for login form and main content to avoid repetition.', 'duration': 770.739, 'max_score': 4833.631, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug4833631.jpg'}, {'end': 5182.111, 'src': 'embed', 'start': 5148.645, 'weight': 4, 'content': [{'end': 5152.287, 'text': 'okay, these options always means attributes.', 'start': 5148.645, 'duration': 3.642}, {'end': 5154.028, 'text': 'okay, html attributes.', 'start': 5152.287, 'duration': 1.741}, {'end': 5171.983, 'text': "so we're going to specify right here class html attribute to be d flex, flex column okay, and that's okay, and we can also give it nav pills,", 'start': 5154.588, 'duration': 17.395}, {'end': 5172.584, 'text': 'for example.', 'start': 5171.983, 'duration': 0.601}, {'end': 5174.645, 'text': 'okay, just like this.', 'start': 5173.084, 'duration': 1.561}, {'end': 5178.709, 'text': "okay, and we're gonna change appearance slightly.", 'start': 5174.645, 'duration': 4.064}, {'end': 5182.111, 'text': 'okay. so for this we need to write a little bit of CSS.', 'start': 5178.709, 'duration': 3.402}], 'summary': 'Specified class html attribute as d flex, flex column and nav pills for appearance change, requiring some css.', 'duration': 33.466, 'max_score': 5148.645, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug5148645.jpg'}, {'end': 5920.126, 'src': 'embed', 'start': 5891.29, 'weight': 0, 'content': [{'end': 5894.332, 'text': 'okay, we can use this one also on command line.', 'start': 5891.29, 'duration': 3.042}, {'end': 5903.738, 'text': "however, it is mostly used from user interface and we're going to use this also and we have, like, a lot of options right here, working, uh,", 'start': 5894.332, 'duration': 9.406}, {'end': 5905.359, 'text': 'with e php e.', 'start': 5903.738, 'duration': 1.621}, {'end': 5915.924, 'text': 'okay, so we can use right now, at the moment, uh, phpe, because this phpe actually is a command which creates a console application.', 'start': 5905.979, 'duration': 9.945}, {'end': 5920.126, 'text': 'okay, so this one is a controller and this one is an action.', 'start': 5915.924, 'duration': 4.202}], 'summary': 'Using phpe command line and user interface with a lot of options for working with e php e.', 'duration': 28.836, 'max_score': 5891.29, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug5891290.jpg'}, {'end': 5979.424, 'src': 'embed', 'start': 5952.077, 'weight': 1, 'content': [{'end': 5957.624, 'text': 'If you actually specify the name like this create XYZ table.', 'start': 5952.077, 'duration': 5.547}, {'end': 5961.088, 'text': 'it generates special code for you to create an actual table.', 'start': 5957.624, 'duration': 3.464}, {'end': 5964.633, 'text': "Okay, so let's just specify a few more parameters.", 'start': 5961.349, 'duration': 3.284}, {'end': 5966.515, 'text': 'Okay, minus minus fields.', 'start': 5964.733, 'duration': 1.782}, {'end': 5970.44, 'text': 'Okay, I want to create videos table and here are the fields.', 'start': 5966.916, 'duration': 3.524}, {'end': 5977.583, 'text': 'so each video needs to have a unique id and this id will be a random string.', 'start': 5971.321, 'duration': 6.262}, {'end': 5979.424, 'text': 'okay, hard to guess.', 'start': 5977.583, 'duration': 1.841}], 'summary': 'Using specified parameters, special code creates xyz table with unique video ids.', 'duration': 27.347, 'max_score': 5952.077, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug5952077.jpg'}, {'end': 6130.914, 'src': 'embed', 'start': 6100.771, 'weight': 2, 'content': [{'end': 6107.477, 'text': "So let's close the terminal and let's go to the following folder, console migrations.", 'start': 6100.771, 'duration': 6.706}, {'end': 6111.72, 'text': 'And right here, we actually have three migrations.', 'start': 6107.937, 'duration': 3.783}, {'end': 6113.782, 'text': 'The first two comes with the installation.', 'start': 6111.88, 'duration': 1.902}, {'end': 6115.663, 'text': 'This is what we just created.', 'start': 6114.182, 'duration': 1.481}, {'end': 6117.685, 'text': 'Create videos table.', 'start': 6115.783, 'duration': 1.902}, {'end': 6118.986, 'text': "Let's expand this.", 'start': 6118.125, 'duration': 0.861}, {'end': 6122.81, 'text': "and let's have a look.", 'start': 6120.729, 'duration': 2.081}, {'end': 6126.552, 'text': 'so here is the code create table videos.', 'start': 6122.81, 'duration': 3.742}, {'end': 6128.153, 'text': 'id is the primary key.', 'start': 6126.552, 'duration': 1.601}, {'end': 6130.914, 'text': 'video id, title description created by.', 'start': 6128.153, 'duration': 2.761}], 'summary': 'Three migrations found, including one for creating videos table.', 'duration': 30.143, 'max_score': 6100.771, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug6100771.jpg'}, {'end': 6349.084, 'src': 'embed', 'start': 6322.405, 'weight': 3, 'content': [{'end': 6329.838, 'text': 'so we have video id, title, description, tags, status, his thumbnail, video name.', 'start': 6322.405, 'duration': 7.433}, {'end': 6336.772, 'text': 'I think we need to add also created it when the video was actually uploaded.', 'start': 6329.838, 'duration': 6.934}, {'end': 6344.82, 'text': "And that's going to be timestamp, okay? This integer, okay, 11, and let's add updated at column as well.", 'start': 6337.132, 'duration': 7.688}, {'end': 6349.084, 'text': 'Updated at, when the video was last time updated.', 'start': 6345.34, 'duration': 3.744}], 'summary': 'Adding created at and updated at columns with timestamp for videos.', 'duration': 26.679, 'max_score': 6322.405, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug6322405.jpg'}], 'start': 3725.949, 'title': 'Web application development', 'summary': 'Covers core components in web application development, explains identity class in php configuration, url generation, navigation options, and creating a youtube clone layout, along with database table migration and layout modification in php.', 'chapters': [{'end': 3916.201, 'start': 3725.949, 'title': 'Understanding web application components', 'summary': 'Discusses the usage of core components such as ewebrequest, ewebresponse, log, view, formatter, and url manager in a web application, with insights into their properties and methods.', 'duration': 190.252, 'highlights': ['The core components of a web application include eWebRequest, eWebResponse, Log, View, Formatter, Internalization, and URL manager, which are available in any web applications.', 'The URL manager class includes properties such as enable pretty URL and show script name, with the ability to configure these properties in the backend config main PHP.', 'The UserComponent has methods and properties such as IsGuess, which returns true if the user is not authorized, and a form creation for logout functionality.', 'An alternative method for creating the logout functionality involves using an array with specified labels and current user information from e-app.']}, {'end': 4343.297, 'start': 3916.201, 'title': 'Understanding identity class in php configuration', 'summary': 'Explains the identity class in php configuration, including its implementation, usage, and validation rules for model classes like user, and also discusses the functionality of behaviors like verbfilterbehavior in the ito framework.', 'duration': 427.096, 'highlights': ['The identity class in PHP configuration is an instance of the identity class inside the common models user, which extends active record and implements identity interface, mapped to the database table called user, and every active record object is a child class of model, with models in general dealing mostly with the database and validation rules.', 'The identity class implements methods like findIdentity, findIdentityByAccessToken, findByUsername, and find by password reset token for searching users in the database, and behaviors like VerbFilterBehavior extends the functionality of the class by blocking requests that are not post on a logout action.', "The JavaScript in E-Framework handles special properties like menu items generated for the navigation, and it's important to understand these concepts step by step for developing purposes."]}, {'end': 4748.445, 'start': 4343.878, 'title': 'Web development: url generation and navigation options', 'summary': 'Explains the process of url generation, navigation options, and the importance of using the correct approach for generating urls in web development, emphasizing the use of url helper and the array notation for menu items.', 'duration': 404.567, 'highlights': ['The importance of using the correct approach for generating URLs in web development, emphasizing the use of URL helper and the array notation for menu items.', 'Explanation of the process of URL generation and the impact of different URL configurations on the functionality of links.', 'Demonstration of the navigation options through specifying link attributes and the impact on the generated HTML elements.']}, {'end': 5638.215, 'start': 4748.845, 'title': 'Creating youtube clone layout', 'summary': 'Describes modifying the layout to create a youtube clone by adding a header, sidebar with navigation, and content using php and bootstrap, and implementing different layouts for login and main pages to avoid repetitive code.', 'duration': 889.37, 'highlights': ['The chapter walks through the process of modifying the layout to create a YouTube clone by adding a header, sidebar with navigation, and content using PHP and Bootstrap.', 'Implementing different layouts for login and main pages to avoid repetitive code.', 'Using PHP to move partial content into separate files, such as underscore header and underscore sidebar, for better organization and maintenance.']}, {'end': 6429.535, 'start': 5638.215, 'title': 'Database table migration and layout modification in php', 'summary': 'Details the modification of layout files in php, the implementation of aliases and the creation of a videos table in a database, including specifying fields and applying the migration, culminating in the successful creation of the videos table in the database.', 'duration': 791.32, 'highlights': ['The chapter details the modification of layout files in PHP, including copying content from one file to another, making changes to the layout structure, and verifying the changes in the browser.', 'The implementation of aliases in PHP is explained, including their usage for paths, the method for saving and retrieving aliases, and the inclusion of bootstrap.php in the entry script web.index.php.', 'The creation of a videos table in the database is outlined, covering the specification of fields such as video ID, title, description, created by, tags, status, hasThumbnail, video name, created at, and updated at, as well as the application of the migration and verification in phpMyAdmin.']}], 'duration': 2703.586, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug3725949.jpg', 'highlights': ['The core components of a web application include eWebRequest, eWebResponse, Log, View, Formatter, Internalization, and URL manager.', 'The URL manager class includes properties such as enable pretty URL and show script name, configurable in the backend config main PHP.', 'The identity class in PHP configuration is an instance of the identity class inside the common models user, which extends active record and implements identity interface.', 'The importance of using the correct approach for generating URLs in web development, emphasizing the use of URL helper and the array notation for menu items.', 'The chapter walks through the process of modifying the layout to create a YouTube clone by adding a header, sidebar with navigation, and content using PHP and Bootstrap.']}, {'end': 7902.727, 'segs': [{'end': 6487.721, 'src': 'embed', 'start': 6457.228, 'weight': 5, 'content': [{'end': 6464.471, 'text': 'Okay? So, replace all of the occurrences right here, right here, here, here, here.', 'start': 6457.228, 'duration': 7.243}, {'end': 6466.431, 'text': "Okay, let's, that's good.", 'start': 6464.911, 'duration': 1.52}, {'end': 6470.853, 'text': "So, let's just save this and let's just apply this migration again.", 'start': 6466.811, 'duration': 4.042}, {'end': 6479.437, 'text': 'emigrate, hit the enter type yes, and one migration was applied.', 'start': 6472.493, 'duration': 6.944}, {'end': 6480.097, 'text': 'collapse this.', 'start': 6479.437, 'duration': 0.66}, {'end': 6484.859, 'text': 'go to phpmyadmin, reload the page and right here i see video.', 'start': 6480.097, 'duration': 4.762}, {'end': 6487.721, 'text': 'okay, now i need to generate a model.', 'start': 6484.859, 'duration': 2.862}], 'summary': 'Performed migration, applied one migration, and generated a model.', 'duration': 30.493, 'max_score': 6457.228, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug6457228.jpg'}, {'end': 6929.292, 'src': 'embed', 'start': 6905.13, 'weight': 3, 'content': [{'end': 6914.541, 'text': 'of course, the form should not look like this, but the tool gii just generated for every field, like video, id, title, description,', 'start': 6905.13, 'duration': 9.411}, {'end': 6917.124, 'text': 'text status has thumbnail, video name and so on.', 'start': 6914.541, 'duration': 2.583}, {'end': 6922.187, 'text': 'okay, so we want to, of course, change this form and make some corrections.', 'start': 6917.344, 'duration': 4.843}, {'end': 6929.292, 'text': 'but if we just fill up this form and click the save button, the record will automatically appear right here.', 'start': 6922.187, 'duration': 7.105}], 'summary': 'The tool gii generates fields for video data, but the form needs corrections; filling and saving the form will automatically display the record.', 'duration': 24.162, 'max_score': 6905.13, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug6905130.jpg'}, {'end': 7284.616, 'src': 'embed', 'start': 7223.01, 'weight': 0, 'content': [{'end': 7235.3, 'text': "so let's just do one div and inside the div i want to actually copy and paste this text and i want to put the icon as well and the button okay.", 'start': 7223.01, 'duration': 12.29}, {'end': 7236.741, 'text': "so let's do like this.", 'start': 7235.3, 'duration': 1.441}, {'end': 7239.123, 'text': 'so we have paragraph right here.', 'start': 7236.741, 'duration': 2.382}, {'end': 7241.945, 'text': "so let's just close this paragraph.", 'start': 7239.123, 'duration': 2.822}, {'end': 7245.894, 'text': "okay, and right here Let's just open the paragraph.", 'start': 7241.945, 'duration': 3.949}, {'end': 7251.435, 'text': 'okay?. However, the last paragraph needs to have a class TextMuted to gray out, okay?', 'start': 7245.894, 'duration': 5.541}, {'end': 7253.196, 'text': 'Slightly to be grayed out.', 'start': 7251.695, 'duration': 1.501}, {'end': 7263.379, 'text': "Then right here, I want to put the icon, okay? So I'm going to create UploadIconDiv, and right here, I want to put the icon.", 'start': 7254.776, 'duration': 8.603}, {'end': 7267.18, 'text': "For this I'm going to use FontAwesomeIcons.", 'start': 7263.619, 'duration': 3.561}, {'end': 7272.902, 'text': "okay?. So let's go and let's type in the Google font AwesomeIcons.", 'start': 7267.18, 'duration': 5.722}, {'end': 7278.608, 'text': "okay?. let's go right here and this is icon list.", 'start': 7272.902, 'duration': 5.706}, {'end': 7280.09, 'text': 'if it opens, this is icon list.', 'start': 7278.608, 'duration': 1.482}, {'end': 7281.632, 'text': 'what i want to use?', 'start': 7280.09, 'duration': 1.542}, {'end': 7284.616, 'text': 'okay, so i want upload icon.', 'start': 7281.632, 'duration': 2.984}], 'summary': 'Creating a div with text, icon, and button. adding class textmuted for last paragraph.', 'duration': 61.606, 'max_score': 7223.01, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug7223010.jpg'}], 'start': 6430.856, 'title': 'Backend video controller overview', 'summary': 'Discusses the generation of six files including one controller and five view files, and explains the functionality and flow of the backend video controller, detailing the creation and rendering of the video form as well as the use of the debug bar.', 'chapters': [{'end': 6623.536, 'start': 6430.856, 'title': 'Database table modification and model generation', 'summary': 'Covers modifying the database table from plural to singular form, applying a migration, and generating a model using gii tool, resulting in the creation of video.php and video query files with specific annotations and rules.', 'duration': 192.68, 'highlights': ["Changed the name of the database table from plural to singular form, explaining the reason behind it and applied the migration, resulting in the creation of a table named 'video' in the database.", "Utilized the GII tool to generate a model for the 'video' table, specifying the namespace and table prefix syntax, which led to the creation of Video.php and Video Query files with annotations and rules."]}, {'end': 6827.067, 'start': 6623.677, 'title': 'Creating video model and generating crud application', 'summary': 'Explains the creation of a video model with validation rules and a relationship to the user table, followed by the process of generating a crud application for the video model using giik, specifying the model class, controller, and view path.', 'duration': 203.39, 'highlights': ['The chapter explains the creation of a video model with validation rules, including attributes like video ID, which should be a string with a maximum length of 16, and the indication that video ID needs to be unique.', "It also details the relation between the video model and the user table, indicating that a video has one user as a creator, with the user ID corresponding to the video's 'created by' attribute.", 'Furthermore, it outlines the process of generating a CRUD application for the video model using GIIK, specifying the model class, controller, and view path for the application.']}, {'end': 7108.411, 'start': 6827.067, 'title': 'Backend video controller overview', 'summary': 'Discusses the generation of six files including one controller and five view files, and explains the functionality and flow of the backend video controller, detailing the creation and rendering of the video form as well as the use of the debug bar.', 'duration': 281.344, 'highlights': ['The chapter explains the generation of six files including one controller and five view files.', 'It details the functionality and flow of the backend video controller, including the creation and rendering of the video form and the use of the debug bar.', "The video controller's create action is explained, including the process of creating an instance of the video model, loading post data into the model, saving changes in the database, and redirecting to the view page."]}, {'end': 7284.616, 'start': 7108.411, 'title': 'Bootstrap 4 form and icon usage', 'summary': 'Discusses using bootstrap 4 classes and activeform for front-end validation, generating form elements with activeform, and integrating fontawesomeicons for icon usage.', 'duration': 176.205, 'highlights': ['Using ActiveForm from Bootstrap 4 namespace for front-end validation and generating form elements, resulting in improved user experience.', 'Integrating FontAwesomeIcons to create an UploadIconDiv and using the upload icon for enhanced visual appeal.']}, {'end': 7498, 'start': 7284.616, 'title': 'Adding font awesome and styling upload icon', 'summary': 'Covers adding font awesome fifth version using cdn.js and applying css to style the upload button, with the need for hard reload to reflect the changes.', 'duration': 213.384, 'highlights': ['The chapter covers adding Font Awesome fifth version using CDN.js and applying CSS to style the upload button, with the need for hard reload to reflect the changes.', 'Instructions on including Font Awesome using CDN.js and specifying the CSS version, emphasizing the need to put it in the base layout for universal use.', 'Demonstration of applying CSS to style the upload button and addressing the issue of browser caching, requiring a hard reload for the changes to take effect.']}, {'end': 7902.727, 'start': 7498, 'title': 'Handling file caching in e-framework', 'summary': 'Discusses the implementation of the asset manager component in e-framework to prevent caching, the usage of active form for file upload, and the inclusion of javascript for submitting the form, with a focus on improving performance and functionality.', 'duration': 404.727, 'highlights': ["Implementation of asset manager component in E-Framework to prevent caching and ensure that the timestamp of the file does not change, maintaining the file's original timestamp even on page reloads.", 'Usage of active form for file upload with the specification of encoding type to be multi-part form data to enable file uploading functionality.', 'Inclusion of JavaScript to select the file, listen to its change, and trigger the form submission upon file selection, providing a seamless user experience for file upload.', 'Discussion on the common issue for developers telling clients to clear the cache and the recommendation of utilizing the asset manager component in E-Framework as a good practice, emphasizing the importance of preventing caching and its benefits.', 'Demonstration of adding classes and minor adjustments in the form to improve its appearance and functionality, showcasing a practical approach to enhancing user interface and experience.']}], 'duration': 1471.871, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug6430856.jpg', 'highlights': ["Changed database table name to singular form, created 'video' table", "Utilized GII tool to generate model and query files for 'video' table", 'Explained video model creation with validation rules and user table relation', 'Generated CRUD application for video model using GIIK', 'Explained functionality and flow of backend video controller', 'Implemented asset manager component in E-Framework to prevent caching']}, {'end': 8813.765, 'segs': [{'end': 7956.317, 'src': 'embed', 'start': 7902.727, 'weight': 0, 'content': [{'end': 7907.972, 'text': "get instance by name and i'm going to specify the name of the input type file.", 'start': 7902.727, 'duration': 5.245}, {'end': 7911.315, 'text': 'okay, and that is the this one.', 'start': 7907.972, 'duration': 3.343}, {'end': 7913.517, 'text': 'this one is the name.', 'start': 7911.315, 'duration': 2.202}, {'end': 7916.98, 'text': "okay, so we have this file and let's just dump this file.", 'start': 7913.517, 'duration': 3.463}, {'end': 7920.583, 'text': "okay, i'm gonna print for dump and exit right here.", 'start': 7916.98, 'duration': 3.603}, {'end': 7924.869, 'text': "so let's just reload the page And here is our uploaded file.", 'start': 7920.583, 'duration': 4.286}, {'end': 7930.611, 'text': 'Okay, so we have the name, we have tmp name, size, type, and everything about this file.', 'start': 7925.109, 'duration': 5.502}, {'end': 7941.036, 'text': 'So now what we need to do is we need to actually save this video file on the file system as well as create a record in the database.', 'start': 7931.012, 'duration': 10.024}, {'end': 7947.062, 'text': "Okay, it's a big challenge, right? No, it's not that complicated, so let's start implementing this.", 'start': 7941.556, 'duration': 5.506}, {'end': 7956.317, 'text': "So let's open a video model, and right here, let's create a public property Okay? This is just a public property.", 'start': 7947.542, 'duration': 8.775}], 'summary': 'Implementing file upload and database record creation for video model.', 'duration': 53.59, 'max_score': 7902.727, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug7902727.jpg'}, {'end': 8127.978, 'src': 'embed', 'start': 8101.263, 'weight': 6, 'content': [{'end': 8107.164, 'text': "So I'm checking if the current request, okay, is post.", 'start': 8101.263, 'duration': 5.901}, {'end': 8116.075, 'text': "In this case, let's call the model save, okay? If it's not request, let's come right here and render the form.", 'start': 8108.164, 'duration': 7.911}, {'end': 8119.576, 'text': 'Okay, so this one looks good.', 'start': 8116.655, 'duration': 2.921}, {'end': 8127.978, 'text': 'If the current method is post, and if we just open this URL right now, it is not post, so it just renders the form.', 'start': 8120.376, 'duration': 7.602}], 'summary': 'Checking if current request is post, calling model save, rendering form if not post.', 'duration': 26.715, 'max_score': 8101.263, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug8101263.jpg'}, {'end': 8754.762, 'src': 'embed', 'start': 8697.796, 'weight': 2, 'content': [{'end': 8699.658, 'text': 'OK, something actually happened.', 'start': 8697.796, 'duration': 1.862}, {'end': 8712.811, 'text': "So we see a ViewPage, OK? And we only see ViewPage, according to the VideoController's code, this CreateActionCode, only when ModelSave worked.", 'start': 8700.158, 'duration': 12.653}, {'end': 8715.654, 'text': 'So this means that the ModelSave actually worked.', 'start': 8713.392, 'duration': 2.262}, {'end': 8717.235, 'text': "OK, so let's have a look.", 'start': 8716.134, 'duration': 1.101}, {'end': 8720.877, 'text': "Let's go to the videos and right here we see record.", 'start': 8718.015, 'duration': 2.862}, {'end': 8722.178, 'text': "Okay, that's good.", 'start': 8721.438, 'duration': 0.74}, {'end': 8723.479, 'text': 'It was actually saved.', 'start': 8722.338, 'duration': 1.141}, {'end': 8738.371, 'text': "Let's now go to the frontend. okay, frontend web storage videos. and here is our video, our uploaded video okay, which has random string as a name.", 'start': 8723.94, 'duration': 14.431}, {'end': 8740.513, 'text': 'So it actually worked, which is awesome.', 'start': 8738.731, 'duration': 1.782}, {'end': 8744.375, 'text': "Okay, so let's make a couple of changes right here.", 'start': 8740.993, 'duration': 3.382}, {'end': 8748.918, 'text': "Whenever a video is uploaded, we don't want to be redirected to the view page.", 'start': 8744.776, 'duration': 4.142}, {'end': 8754.762, 'text': 'Instead, I want to be redirected to the video update page.', 'start': 8749.339, 'duration': 5.423}], 'summary': 'Modelsave worked, video uploaded successfully, redirect to video update page', 'duration': 56.966, 'max_score': 8697.796, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug8697796.jpg'}], 'start': 7902.727, 'title': 'Video file management', 'summary': 'Covers uploading and saving video files, specifying file name, saving on file system, creating a record in the database, challenges, debugging techniques, saving and loading data in the video model, overwriting the save method, generating video id and title, handling validation, accessing uploaded videos in web accessible directories, and successful access from studio and front-end side.', 'chapters': [{'end': 8044.52, 'start': 7902.727, 'title': 'Uploading and saving video files', 'summary': 'Covers the process of uploading video files, including specifying file name, saving on file system, and creating a record in the database, highlighting challenges and debugging techniques.', 'duration': 141.793, 'highlights': ['The process involves specifying the name of the input type file, dumping the file, and reloading the page to view the uploaded file, demonstrating the successful file upload process.', 'The implementation includes creating a public property for the video file, assigning the uploaded file to the video model, and addressing validation errors, providing a detailed insight into the code implementation.', 'The need to save the video file on the file system and create a record in the database is emphasized, showcasing the primary objectives of the upload process.']}, {'end': 8458.904, 'start': 8044.76, 'title': 'Video model save and load', 'summary': 'Discusses the process of saving and loading data in the video model, including overwriting the save method and generating a video id, a title, and saving the video file as well as handling validation and file system storage.', 'duration': 414.144, 'highlights': ["The video model's save method needs to be overwritten to handle the video upload, including generating a video ID and assigning the video title.", 'A random string of 8 characters length is generated for the video ID, ensuring it is not guessable.', 'The save method includes logic to handle validation, including not saving the video file if the validation fails.', 'The process of saving the video file to the file system is discussed, including checking if the file was successfully saved and generating the video path.']}, {'end': 8813.765, 'start': 8458.904, 'title': 'Saving and accessing video files in web applications', 'summary': "Covers saving video files in web accessible directories, creating storage directories, checking and creating video directories if they don't exist, and successfully accessing the uploaded video from both studio and front-end side.", 'duration': 354.861, 'highlights': ['Video file is saved inside the web accessible directory, either in the backend or front-end web, to ensure access from both domains. The file is given a name based on the video id and saved as .mp4 for simplicity.', "If the video directory doesn't exist, the code checks and creates the directory using FileHelper in E-Framework, ensuring the successful saving of the video file.", 'After successful upload, the ViewPage is displayed only if the ModelSave worked, indicating that the video was successfully saved. The video can be accessed from the frontend web storage directory.', 'When a video is uploaded, the redirection to the video update page is preferred over the ViewPage, and the video update page URL is modified to include the video ID as a query parameter.', 'The video update page is displayed with the assigned title and video name, illustrating the successful upload and accessibility of the video file.', "The URL manager in the backend's config main is used to modify the URL and make it more user-friendly by defining rules."]}], 'duration': 911.038, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug7902727.jpg', 'highlights': ['The process involves specifying the name of the input type file, dumping the file, and reloading the page to view the uploaded file, demonstrating the successful file upload process.', 'The need to save the video file on the file system and create a record in the database is emphasized, showcasing the primary objectives of the upload process.', 'The implementation includes creating a public property for the video file, assigning the uploaded file to the video model, and addressing validation errors, providing a detailed insight into the code implementation.', 'Video file is saved inside the web accessible directory, either in the backend or front-end web, to ensure access from both domains. The file is given a name based on the video id and saved as .mp4 for simplicity.', "The video model's save method needs to be overwritten to handle the video upload, including generating a video ID and assigning the video title.", 'After successful upload, the ViewPage is displayed only if the ModelSave worked, indicating that the video was successfully saved. The video can be accessed from the frontend web storage directory.', 'A random string of 8 characters length is generated for the video ID, ensuring it is not guessable.', "If the video directory doesn't exist, the code checks and creates the directory using FileHelper in E-Framework, ensuring the successful saving of the video file.", 'When a video is uploaded, the redirection to the video update page is preferred over the ViewPage, and the video update page URL is modified to include the video ID as a query parameter.', 'The save method includes logic to handle validation, including not saving the video file if the validation fails.']}, {'end': 10399.008, 'segs': [{'end': 8952.582, 'src': 'embed', 'start': 8927.5, 'weight': 4, 'content': [{'end': 8934.005, 'text': "okay?. I mentioned when I was talking about configuration that I'm going to use it a lot throughout the building application.", 'start': 8927.5, 'duration': 6.505}, {'end': 8935.726, 'text': 'So this is the configuration.', 'start': 8934.405, 'duration': 1.321}, {'end': 8941.51, 'text': "In the class, we're going to specify BlameableBehaviour, okay? That's the class.", 'start': 8936.226, 'duration': 5.284}, {'end': 8945.178, 'text': 'And before I continue, let me explain what this does.', 'start': 8942.617, 'duration': 2.561}, {'end': 8952.582, 'text': 'Timestamp behavior, if you open this, has two main attributes, createdAt and updatedAt.', 'start': 8945.879, 'duration': 6.703}], 'summary': 'Configuring blameablebehaviour class with timestamp behavior for createdat and updatedat attributes.', 'duration': 25.082, 'max_score': 8927.5, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug8927500.jpg'}, {'end': 9063.497, 'src': 'embed', 'start': 9005.545, 'weight': 1, 'content': [{'end': 9010.187, 'text': 'okay, so this is the configuration example of e-framework.', 'start': 9005.545, 'duration': 4.642}, {'end': 9012.707, 'text': 'okay, so it does.', 'start': 9010.187, 'duration': 2.52}, {'end': 9015.608, 'text': 'uh, it creates an instance of playable behavior.', 'start': 9012.707, 'duration': 2.901}, {'end': 9018.569, 'text': 'however, it will set updated by attribute into false.', 'start': 9015.608, 'duration': 2.961}, {'end': 9022.211, 'text': "So let's do everything step by step, as I said.", 'start': 9019.329, 'duration': 2.882}, {'end': 9025.353, 'text': "So, let's go to the Video Create page.", 'start': 9022.611, 'duration': 2.742}, {'end': 9029.375, 'text': "Actually, let's link from here, okay? Video Create page.", 'start': 9026.674, 'duration': 2.701}, {'end': 9032.277, 'text': "Let's go to Header PHP.", 'start': 9029.696, 'duration': 2.581}, {'end': 9034.919, 'text': 'And right here, we have this Create.', 'start': 9033.118, 'duration': 1.801}, {'end': 9039.642, 'text': "So, let's link this into Video slash Create Action.", 'start': 9035.179, 'duration': 4.463}, {'end': 9041.723, 'text': 'Video Controllers, Create Action.', 'start': 9039.882, 'duration': 1.841}, {'end': 9043.384, 'text': 'So, reload the page.', 'start': 9042.284, 'duration': 1.1}, {'end': 9044.305, 'text': 'Click right here.', 'start': 9043.584, 'duration': 0.721}, {'end': 9047.667, 'text': "Let's choose one more video file.", 'start': 9045.125, 'duration': 2.542}, {'end': 9053.03, 'text': 'And we are redirected on the view page.', 'start': 9050.849, 'duration': 2.181}, {'end': 9056.092, 'text': "However, we don't want, as I mentioned, this view page.", 'start': 9053.111, 'duration': 2.981}, {'end': 9058.554, 'text': 'So we need to go to the update page.', 'start': 9056.453, 'duration': 2.101}, {'end': 9060.675, 'text': "Let's change these also really quickly.", 'start': 9058.654, 'duration': 2.021}, {'end': 9063.497, 'text': "So let's go to action create.", 'start': 9060.915, 'duration': 2.582}], 'summary': 'Configuration example of e-framework creating an instance of playable behavior and setting updated by attribute to false, followed by navigation and updates.', 'duration': 57.952, 'max_score': 9005.545, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug9005545.jpg'}, {'end': 9119.992, 'src': 'embed', 'start': 9089.841, 'weight': 2, 'content': [{'end': 9094.027, 'text': "And we don't still see this created it and updated it.", 'start': 9089.841, 'duration': 4.186}, {'end': 9096.111, 'text': "Why? Let's take the other one.", 'start': 9094.608, 'duration': 1.503}, {'end': 9097.032, 'text': "Maybe it's the other one.", 'start': 9096.151, 'duration': 0.881}, {'end': 9099.817, 'text': 'Update slash this one.', 'start': 9097.994, 'duration': 1.823}, {'end': 9102.327, 'text': 'And yeah, it was the other one.', 'start': 9101.207, 'duration': 1.12}, {'end': 9106.448, 'text': 'So here we have created at, updated at, and created by.', 'start': 9102.587, 'duration': 3.861}, {'end': 9107.749, 'text': 'Okay, we have these fields.', 'start': 9106.569, 'duration': 1.18}, {'end': 9112.15, 'text': 'Okay, and it will be in the database as well if you see using phpMyAdmin.', 'start': 9108.049, 'duration': 4.101}, {'end': 9119.992, 'text': 'Okay, what else do we need? We need to redirect user to the update page when the video is created.', 'start': 9112.97, 'duration': 7.022}], 'summary': 'Discussing creation and update of fields in a database and redirecting users to update page.', 'duration': 30.151, 'max_score': 9089.841, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug9089841.jpg'}, {'end': 9244.742, 'src': 'embed', 'start': 9212.632, 'weight': 0, 'content': [{'end': 9219.816, 'text': 'So hisThumbnail will be by default 0.', 'start': 9212.632, 'duration': 7.184}, {'end': 9223.022, 'text': "OK, so let's upload video once again.", 'start': 9219.816, 'duration': 3.206}, {'end': 9226.548, 'text': 'OK, choose another video.', 'start': 9223.042, 'duration': 3.506}, {'end': 9229.513, 'text': "And let's see.", 'start': 9228.631, 'duration': 0.882}, {'end': 9232.995, 'text': 'So we are redirected to the update page.', 'start': 9230.834, 'duration': 2.161}, {'end': 9234.136, 'text': 'Scroll down.', 'start': 9233.636, 'duration': 0.5}, {'end': 9239.299, 'text': 'The status is zero, has thumbnail is zero, and we have everything basically what we need.', 'start': 9234.296, 'duration': 5.003}, {'end': 9242.04, 'text': 'Description and tags needs to be empty.', 'start': 9239.939, 'duration': 2.101}, {'end': 9244.742, 'text': 'They need to be written by the user.', 'start': 9242.2, 'duration': 2.542}], 'summary': 'Video uploaded successfully with default thumbnail and empty description/tags.', 'duration': 32.11, 'max_score': 9212.632, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug9212632.jpg'}], 'start': 8813.765, 'title': 'Video management and display', 'summary': 'Discusses improving url structure for video access, setting default values for video creation, configuring timestamp and blameable behavior, displaying video link and name, and implementing video status and custom thumbnail features.', 'chapters': [{'end': 8876.116, 'start': 8813.765, 'title': 'Url manager and video controller update', 'summary': 'Discusses the use of url manager to improve the url structure for a video, allowing for easier access and functionality, and the need to assign default values such as created at, updated at, and created by when a video is created.', 'duration': 62.351, 'highlights': ['URL manager can improve the URL structure for a video, allowing for easier access and functionality, and without it, the page will not be found', 'When a video is created, default values such as created at, updated at, and created by need to be assigned']}, {'end': 9381.71, 'start': 8876.476, 'title': 'Video configuration and form update', 'summary': 'Covers configuring the timestamp and blameable behavior in video.php, setting default values for status and hasthumbnail, and updating the video form layout.', 'duration': 505.234, 'highlights': ['The chapter explains configuring timestamp and blameable behavior in Video.php, setting createdAt and updatedAt attributes using timestamp behavior and createdBy attribute using blameable behavior, and applying default values for status and hasThumbnail.', 'The speaker sets the default value for status as unlisted and published, with unlisted being 0 and published being 1.', 'The form layout is updated by removing non-updatable fields, adjusting the status to be a dropdown, and organizing the fields to match the design of the actual studio.']}, {'end': 9807.722, 'start': 9381.71, 'title': 'Displaying video link and name', 'summary': 'Covers the process of displaying a video link and name, including the creation of a method to retrieve the video link, addressing domain hardcoding issues, and implementing a responsive video display using bootstrap.', 'duration': 426.012, 'highlights': ['The video link is constructed using the video id and domain, with the domain being hardcoded in the model, presenting a potential problem when deployed to production.', "A method 'get video link' is created in the video.php file to retrieve the actual video link, addressing the need to display the video link on the front-end.", "The issue of hardcoding the domain in the model is resolved by moving it to a params file, specifically 'common/config/params/local.php', ensuring flexibility when deployed to different domains.", "The process of displaying the video link and name in the 'form.php' file is detailed, including the creation of a paragraph and div elements to showcase the video link and name, and the implementation of an anchor link to open the video in the browser.", "The implementation of a responsive video display using Bootstrap's 'responsive embed' component is explained, including the modification of the iframe to display the actual video link and the addition of video controls for user interaction."]}, {'end': 10399.008, 'start': 9807.722, 'title': 'Implementing video status and custom thumbnail', 'summary': "Covers implementing a dropdown status feature with options for 'published' and 'unlisted', and creating a custom thumbnail feature with a method to handle the thumbnail file, including setting, saving, and displaying it.", 'duration': 591.286, 'highlights': ["Implementing a dropdown status feature with options for 'published' and 'unlisted' and displaying it on the form with a method to return status labels.", 'Creating a custom thumbnail feature with methods to handle the thumbnail file, including setting, saving, and displaying it.', 'Updating the form to include the custom file input for the thumbnail, and ensuring the form has the correct encoding type for multi-part form data.']}], 'duration': 1585.243, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug8813765.jpg', 'highlights': ['URL manager improves video access and functionality, crucial for page availability', 'Default values like created at, updated at, and created by are assigned when creating a video', 'Configuring timestamp and blameable behavior in Video.php is explained', 'Setting default values for status and hasThumbnail, and updating form layout', 'Constructing video link using video id and domain, and resolving hardcoding issue', 'Creating method to retrieve video link, displaying video link and name, and implementing responsive video display', 'Implementing dropdown status feature and custom thumbnail feature with methods to handle the thumbnail file', 'Updating form to include custom file input for the thumbnail and ensuring correct encoding type']}, {'end': 11716.16, 'segs': [{'end': 10801.903, 'src': 'embed', 'start': 10768.26, 'weight': 1, 'content': [{'end': 10772.062, 'text': 'okay, need to do this, as i was talking.', 'start': 10768.26, 'duration': 3.802}, {'end': 10779.527, 'text': "so let's have a look in the terminal and right here it installed these two packages imagine and e2, imagine.", 'start': 10772.062, 'duration': 7.465}, {'end': 10788.193, 'text': "so let's go to the save method we have right down below and whenever we save the thumbnail, right here, after the thumbnail is saved,", 'start': 10779.527, 'duration': 8.666}, {'end': 10792.376, 'text': 'actually we need to take the save thumbnail and resize it.', 'start': 10788.193, 'duration': 4.183}, {'end': 10801.903, 'text': "okay. so i'm going to call image okay, which is a which comes from e image namespace, image getImaging.", 'start': 10792.376, 'duration': 9.527}], 'summary': 'Installing two packages, imagine and e2, in the terminal. refactoring the save method to resize saved thumbnails using the e image namespace.', 'duration': 33.643, 'max_score': 10768.26, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug10768260.jpg'}, {'end': 11538.618, 'src': 'embed', 'start': 11515.459, 'weight': 2, 'content': [{'end': 11522.381, 'text': 'we need to convert them into dates and for this we have formatter called date time.', 'start': 11515.459, 'duration': 6.922}, {'end': 11529.147, 'text': "okay, let's do this for updated it as well, and this is how it formats the date.", 'start': 11522.381, 'duration': 6.766}, {'end': 11533.212, 'text': 'okay, nice, it formats it in a nice way.', 'start': 11529.147, 'duration': 4.065}, {'end': 11538.618, 'text': "so the next thing is to let's take care of the status and then the video id.", 'start': 11533.212, 'duration': 5.406}], 'summary': 'Using a formatter to convert dates, updating and formatting dates, and addressing status and video id', 'duration': 23.159, 'max_score': 11515.459, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug11515459.jpg'}, {'end': 11625.046, 'src': 'embed', 'start': 11598.15, 'weight': 0, 'content': [{'end': 11601.332, 'text': "my bad, it's called get status labels.", 'start': 11598.15, 'duration': 3.182}, {'end': 11603.815, 'text': 'okay, these get status labels.', 'start': 11601.332, 'duration': 2.483}, {'end': 11607.9, 'text': "it's an associative array and let's call it get status labels as well.", 'start': 11603.815, 'duration': 4.085}, {'end': 11611.805, 'text': 'and right here we need to specify model status.', 'start': 11607.9, 'duration': 3.905}, {'end': 11621.203, 'text': "Okay, I want to take the label for this key and that's going to be either 0 or 1, so it will take either unlisted or published.", 'start': 11612.574, 'duration': 8.629}, {'end': 11625.046, 'text': "Okay, so let's save this and have a look in the browser.", 'start': 11621.623, 'duration': 3.423}], 'summary': 'The script involves creating an associative array called get status labels to specify model status, where the key can have a label of either 0 or 1, indicating unlisted or published status.', 'duration': 26.896, 'max_score': 11598.15, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug11598150.jpg'}], 'start': 10399.008, 'title': 'Video management', 'summary': 'Covers the creation and implementation of methods for thumbnail retrieval, video upload validation, resizing, and display. it also includes video and thumbnail validation with tag input functionality, error handling, and displaying video list with various columns.', 'chapters': [{'end': 10495.004, 'start': 10399.008, 'title': 'Thumbnail link method and implementation', 'summary': "Covers the creation of a 'get thumbnail link' method to retrieve video thumbnails and its implementation in a php form, ensuring that videos have thumbnails for display and handling cases where thumbnails do not exist.", 'duration': 95.996, 'highlights': ["The creation of a 'get thumbnail link' method to dynamically retrieve video thumbnails from the frontend storage was discussed, ensuring the presence of thumbnails for video display.", "The implementation of the 'get thumbnail link' method in the PHP form was demonstrated, enabling the display of video thumbnails and preventing blank pages when thumbnails are absent.", 'The use of a ternary if operator to handle cases where thumbnails do not exist was explained, ensuring the proper display of videos even when thumbnails are not available.']}, {'end': 10657.376, 'start': 10495.004, 'title': 'Implementing video upload and thumbnail resizing', 'summary': 'Discusses implementing video upload validation to allow only jpg files, resizing the thumbnail, and installing a package for image resizing using composer.', 'duration': 162.372, 'highlights': ['Implementing validation to allow only JPG files for video upload and specifying minimum width for thumbnail (e.g. 3000) to trigger validation errors if not met', "Installing 'esoft/e2-imagine' package using composer for resizing thumbnail images", 'Adding rules for thumbnail validation and specifying that it needs to be an image']}, {'end': 11321.593, 'start': 10657.836, 'title': 'Thumbnail and video validation with tag input', 'summary': 'Covers implementing thumbnail and video validation, including error handling, file type validation, and image resizing. it also includes the addition of tag input functionality using a jquery plugin.', 'duration': 663.757, 'highlights': ['The form.php file is updated to display errors using the formErrorSummary method and to specify model for error display, contributing to improved error handling.', 'Video validation is enhanced by restricting file types to only mp4 extensions, ensuring that only valid video files are accepted.', 'The implementation of tag input functionality involves creating a new asset bundle, registering the tags input asset on the form.php view, and specifying input options to convert text fields into tags input, enhancing user experience.']}, {'end': 11716.16, 'start': 11321.593, 'title': 'Implementing video form and displaying video list', 'summary': 'Discusses implementing the video form with features like status, thumbnail, title, and description, and then proceeds to explain the process of displaying videos in a list with columns like video visibility and upload date using gridview and dataprovider.', 'duration': 394.567, 'highlights': ['Implementing the video form with features like status, thumbnail, title, and description.', 'Explaining the process of displaying videos in a list with columns like video visibility and upload date using GridView and DataProvider.', 'Utilizing GridView as a special UI widget responsible for rendering data in a table.', 'Understanding DataProvider as special classes handling data, including pagination and sorting.', 'Configuring columns for the video list, including the video ID, status, creation and update timestamps.', 'Formatting timestamps into dates using a formatter called datetime.', 'Representing status as an associative array with attributes and corresponding content.', 'Utilizing partial view file to handle the display of individual video items.']}], 'duration': 1317.152, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug10399008.jpg', 'highlights': ['Implemented thumbnail link retrieval method for video display', 'Enhanced video validation by restricting file types and implementing tag input functionality', 'Configured video list display with GridView and DataProvider for improved user experience', "Utilized 'esoft/e2-imagine' package for resizing thumbnail images"]}, {'end': 13521.812, 'segs': [{'end': 13248.258, 'src': 'embed', 'start': 13221.552, 'weight': 2, 'content': [{'end': 13227.658, 'text': "Actually, I'm going to give you also a hint how you can do it, and the code will be available on my GitHub account.", 'start': 13221.552, 'duration': 6.106}, {'end': 13229.279, 'text': 'so definitely, definitely.', 'start': 13227.658, 'duration': 1.621}, {'end': 13234.487, 'text': 'I really encourage you to clone this and experiment with this and make changes right there, okay?', 'start': 13229.279, 'duration': 5.208}, {'end': 13239.335, 'text': 'So if this would be a real project and we would have a lot of time,', 'start': 13234.867, 'duration': 4.468}, {'end': 13248.258, 'text': 'I would probably create a subclass of this action class action column excuse me and make these buttons working globally.', 'start': 13239.335, 'duration': 8.923}], 'summary': 'Encouraged to clone code from github for experimentation and make changes.', 'duration': 26.706, 'max_score': 13221.552, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug13221552.jpg'}, {'end': 13502.516, 'src': 'embed', 'start': 13470.347, 'weight': 0, 'content': [{'end': 13471.928, 'text': "now let's go to a video.php.", 'start': 13470.347, 'duration': 1.581}, {'end': 13480.216, 'text': 'Okay, right here and handle the case that when the video is deleted, we need to clean up its thumbnail in video as well.', 'start': 13473.689, 'duration': 6.527}, {'end': 13485.441, 'text': 'Okay, so for this, we need to override after delete method.', 'start': 13480.616, 'duration': 4.825}, {'end': 13491.168, 'text': 'Okay, after delete, when the delete actually happens or after the delete actually happens.', 'start': 13485.882, 'duration': 5.286}, {'end': 13492.789, 'text': 'Okay, right here.', 'start': 13491.588, 'duration': 1.201}, {'end': 13497.693, 'text': 'And whenever this happens, we need to delete its thumbnail and video as well.', 'start': 13493.59, 'duration': 4.103}, {'end': 13502.516, 'text': "So let's just copy the thumbnail path as well as the video path.", 'start': 13498.093, 'duration': 4.423}], 'summary': 'Override after delete method to clean up video thumbnail and path.', 'duration': 32.169, 'max_score': 13470.347, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug13470347.jpg'}], 'start': 11716.16, 'title': 'Implementing video features', 'summary': "Covers implementing video display with bootstrap's media component, adding access control behavior to the video controller, emphasizing the need for authorized user roles, updating front-end layout, configuring backend settings, implementing video query functions, and discussing sorting and pagination for grid view.", 'chapters': [{'end': 12123.989, 'start': 11716.16, 'title': 'Implementing video display and security', 'summary': "Covers implementing the display of video items with bootstrap's media component, using helper classes for functionality, and addressing security concerns by adding access control behavior to the video controller.", 'duration': 407.829, 'highlights': ["Implementing the display of video items using Bootstrap's Media component and utilizing helper classes for functionality.", 'Addressing security concerns by adding access control behavior to the video controller.', 'Demonstrating the use of url helpers method for generating URLs correctly and considering various aspects.', "Showing the process of opening the update page by clicking on the video thumbnail, utilizing embed responsive and specifying the video controller's update action.", 'Demonstrating the feature of active links when navigating between dashboard and videos, ensuring proper functionality.']}, {'end': 12456.124, 'start': 12123.989, 'title': 'Video controller access and front-end layout', 'summary': 'Discusses access control in the video controller, emphasizing the need for authorized user roles and the creation of a new account to filter displayed videos, along with the process of updating the front-end layout to match the backend, resolving errors, and ensuring proper css and layout functionality.', 'duration': 332.135, 'highlights': ['The need for authorized user roles to access the Video Controller and the requirement to log in for any action, ensuring controlled access (quantifiable data: access control rules)', 'The necessity to filter displayed videos based on the specific account and the creation of a new account to achieve this (quantifiable data: filtering videos for the specific account)', 'The process of updating the front-end layout to match the backend, including replacing Bootstrap 3 with Bootstrap 4, fixing layout errors, and ensuring proper CSS functionality (quantifiable data: updating layout and CSS from Bootstrap 3 to Bootstrap 4)', 'The requirement to adjust menu items in the header and sidebar of the front-end layout to match the functionality of the backend layout (quantifiable data: adjusting menu items in the front-end layout)', "The need to change the layout when registering, including modifying the displayed pages and not calling videos in the dashboard, such as renaming the dashboard to 'home' and 'history' pages (quantifiable data: modifying layout when registering)"]}, {'end': 12719.915, 'start': 12456.124, 'title': 'Frontend and backend configuration', 'summary': 'Details the process of configuring the frontend and backend settings, including renaming the application, adjusting the sidebar, implementing user authentication, and addressing security concerns, ultimately demonstrating the authorization process for video access.', 'duration': 263.791, 'highlights': ["The backend folder name is changed to 'my application' and 'free code tube' in the backend config main.php.", "The frontend common config main.php is updated with the name 'freecode2', affecting the frontend display.", "Adjusting the frontend sidebar to display 'home' and 'history' links with corresponding titles.", "Implementing user authentication by adding 'sign up' and 'login' links based on user status.", 'Addressing a bug in the signup process by fixing the namespace issue in the signup.php file.', 'Modifying the user status in the database from 9 to 10 to enable user activation.', 'Identifying and addressing a security issue related to video access by configuring the video controller to restrict access based on the currently authorized user.']}, {'end': 13032.229, 'start': 12720.335, 'title': 'Implementing video query functions', 'summary': "Explains the implementation of video query functions, including the use of 'and where' for multiple conditions, adding a method to find videos by creator id, and sorting videos by latest upload using the 'orderby' function.", 'duration': 311.894, 'highlights': ["The 'and where' method is used to avoid overwriting previous 'where' statements, preventing issues with query methods.", 'A method is added to find all videos whose creator is the specified user ID, enhancing the query functionality.', "The 'orderBy' function is utilized to sort videos by the latest upload date, providing a way to display the most recent videos at the top."]}, {'end': 13521.812, 'start': 13034.316, 'title': 'Implementing sorting and pagination', 'summary': 'Discusses implementing sorting and pagination for a grid view, including applying sorting by createdat, changing the display of buttons, enabling deletion with confirmation, and handling cleanup of videos and thumbnails after deletion.', 'duration': 487.496, 'highlights': ['The chapter covers implementing sorting and pagination for a grid view, including applying sorting by createdAt, which automatically selects the count and applies pagination, and changing the display of buttons in the grid view.', 'It discusses enabling deletion with a confirmation message using the data confirm attribute, which prompts the user with a confirmation dialog before deleting a video.', 'The chapter also addresses the need to handle cleanup of videos and thumbnails after deletion by overriding the after delete method to delete the respective video and thumbnail paths.', 'It mentions the use of HTML helpers and options html attributes, such as specifying the data method as post for making a request and the use of unlink to delete the video and thumbnail paths after deletion.']}], 'duration': 1805.652, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug11716160.jpg', 'highlights': ['Implementing sorting and pagination for grid view, including sorting by createdAt and applying pagination (quantifiable data: sorting and pagination)', 'Adding access control behavior to the video controller to restrict access based on authorized user (quantifiable data: access control rules)', 'Updating front-end layout to match the backend, including replacing Bootstrap 3 with Bootstrap 4 and adjusting menu items (quantifiable data: updating layout and CSS from Bootstrap 3 to Bootstrap 4)', "Implementing video query functions, including using 'and where' method and 'orderBy' function for sorting (quantifiable data: video query functions)", 'The necessity of authorized user roles to access the Video Controller and the requirement to log in for any action (quantifiable data: access control rules)']}, {'end': 15135.305, 'segs': [{'end': 13753.657, 'src': 'embed', 'start': 13716.54, 'weight': 0, 'content': [{'end': 13723.727, 'text': "so let's go to the front end views right here and create video.", 'start': 13716.54, 'duration': 7.187}, {'end': 13738.743, 'text': "okay, inside the video i'm going to create one file called index.php, just like this, and for now i'm just going to write here Okay, nothing else.", 'start': 13723.727, 'duration': 15.016}, {'end': 13749.873, 'text': 'but what I want is that whenever I open the domain, I want the video index to be used, okay, instead of the site index.', 'start': 13738.743, 'duration': 11.13}, {'end': 13753.657, 'text': 'Okay, so for this, I need to go to the front-end config.', 'start': 13750.314, 'duration': 3.343}], 'summary': 'Creating a video index file in the front end views to be used instead of the site index.', 'duration': 37.117, 'max_score': 13716.54, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug13716540.jpg'}, {'end': 14877.101, 'src': 'embed', 'start': 14817.627, 'weight': 2, 'content': [{'end': 14824.671, 'text': "we will need a little bit of javascript to implement this, but for now let's just show the controls.", 'start': 14817.627, 'duration': 7.044}, {'end': 14831.953, 'text': "so let's open view and add controls right here, just like this, awesome.", 'start': 14824.671, 'duration': 7.282}, {'end': 14835.094, 'text': "so i'll reload the page and we have the video right here.", 'start': 14831.953, 'duration': 3.141}, {'end': 14837.215, 'text': 'okay, what else do we need?', 'start': 14835.094, 'duration': 2.121}, {'end': 14847.64, 'text': 'we need to show the video title down below, number of views when it was uploaded, and like and dislike buttons okay,', 'start': 14837.215, 'duration': 10.425}, {'end': 14853.102, 'text': 'and we need to also show the channel name and some description of the video.', 'start': 14847.64, 'duration': 5.462}, {'end': 14854.243, 'text': "okay, let's do this.", 'start': 14853.102, 'duration': 1.141}, {'end': 14860.312, 'text': "so let's go to the view file and right here, down below, let's just write the title.", 'start': 14855.109, 'duration': 5.203}, {'end': 14869.297, 'text': "let's put this in the h6, for example, php echo model is a video and we output its title.", 'start': 14860.312, 'duration': 8.985}, {'end': 14871.818, 'text': 'then we need to output number of views.', 'start': 14869.297, 'duration': 2.521}, {'end': 14875.28, 'text': "again. let's just write like some amount of views.", 'start': 14871.818, 'duration': 3.462}, {'end': 14877.101, 'text': 'dummy, okay views.', 'start': 14875.28, 'duration': 1.821}], 'summary': 'Implement controls, display video with title, views, like/dislike, channel name, and video description.', 'duration': 59.474, 'max_score': 14817.627, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug14817627.jpg'}], 'start': 13522.092, 'title': 'Video management and display', 'summary': 'Covers video deletion, thumbnail checking, front-end implementation, listview customization, and video view page creation, resulting in successful video management and display on the application.', 'chapters': [{'end': 13636.275, 'start': 13522.092, 'title': 'Video deletion and thumbnail checking', 'summary': 'Describes the process of deleting videos, checking for thumbnail existence, and testing the functionality, with a successful deletion of videos and implementation of video uploading.', 'duration': 114.183, 'highlights': ['The video deletion process was successfully implemented, resulting in the deletion of six video items from the file system.', 'The chapter details the steps for checking the existence of thumbnails before deleting a video, emphasizing the need to ensure thumbnail presence to facilitate successful video deletion.', 'The process of uploading videos, including setting status and choosing thumbnails, was successfully implemented, resulting in the addition of two videos with published status.']}, {'end': 13890.786, 'start': 13636.275, 'title': 'Implementing video output on front-end', 'summary': 'Focuses on implementing the output of videos on the front-end and side, including creating a videocontroller, setting the default route to video index, and selecting and displaying all published videos on the page.', 'duration': 254.511, 'highlights': ['Creating a VideoController for the front-end application to handle video output.', "Setting the default route to 'video/index' in the front-end configuration to display the video index instead of the site index.", 'Selecting all published videos and displaying them on the front-end page by creating an active data provider and a method to filter published videos.']}, {'end': 14388.534, 'start': 13891.286, 'title': 'Php listview with activedataprovider', 'summary': 'Focuses on creating a php listview with activedataprovider to display and customize video items, including model properties and css adjustments, resulting in a layout with videos displayed next to each other.', 'duration': 497.248, 'highlights': ['Creating a PHP ListView with ActiveDataProvider to display video items and customize the layout, resulting in a cohesive display of videos next to each other', 'Utilizing model properties such as title, createdBy, number of views, and relative time to populate the video items, enhancing the content with relevant information', 'Implementing CSS adjustments, including padding and margin modifications, to improve the visual layout of the video items']}, {'end': 15135.305, 'start': 14388.534, 'title': 'Implementing video view page', 'summary': 'Focuses on implementing a video view page, including adding an anchor link to the video element, creating a video controller action to display the video based on the id, and designing the layout to display the video, title, views, like and dislike buttons, channel name, and description.', 'duration': 746.771, 'highlights': ['Implementing a video view page by adding an anchor link to the video element, creating a video controller action to display the video based on the ID, and designing the layout to display the video, title, views, like and dislike buttons, channel name, and description.', "Adjusting the layout to remove the left sidebar and specifying the 'alpha layout' to provide more space for the video.", 'Adding controls to the video, displaying the video title, number of views, date, like and dislike buttons, and channel name, and formatting the date using the formatter component.', 'Utilizing Bootstrap classes and icons to create like and dislike buttons, and adjusting the layout to position the buttons and views correctly.']}], 'duration': 1613.213, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug13522092.jpg', 'highlights': ['Successfully implemented video deletion, removing six video items from the file system', 'Implemented video upload process, adding two videos with published status', 'Created PHP ListView with ActiveDataProvider to display and customize video items', 'Implemented video view page with layout design, controls, and Bootstrap classes']}, {'end': 16660.907, 'segs': [{'end': 15213.042, 'src': 'embed', 'start': 15186.967, 'weight': 3, 'content': [{'end': 15195.27, 'text': 'okay?. So for this we need to create a table where we will save each individual view, okay?', 'start': 15186.967, 'duration': 8.303}, {'end': 15201.354, 'text': 'And we need this table also to have the user who actually visited the video.', 'start': 15196.21, 'duration': 5.144}, {'end': 15207.498, 'text': 'If the user is guest, if the user is not authorized, this one, the ID of the user will be null.', 'start': 15201.754, 'duration': 5.744}, {'end': 15213.042, 'text': 'But if the user is authorized, we will say that the user visited that particular video.', 'start': 15207.999, 'duration': 5.043}], 'summary': 'Create a table to save individual video views, including user ids for authorized users and null for guests.', 'duration': 26.075, 'max_score': 15186.967, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug15186967.jpg'}, {'end': 15602.13, 'src': 'embed', 'start': 15573.04, 'weight': 2, 'content': [{'end': 15578.646, 'text': 'okay, video id, user id is null and created at this looks good.', 'start': 15573.04, 'duration': 5.606}, {'end': 15581.975, 'text': 'so the views were saved.', 'start': 15579.853, 'duration': 2.122}, {'end': 15584.998, 'text': 'but we need to output this on the front-end side.', 'start': 15581.975, 'duration': 3.023}, {'end': 15587.7, 'text': 'we need to output how many views the video has.', 'start': 15584.998, 'duration': 2.702}, {'end': 15591.664, 'text': "okay, so let's open now a video.", 'start': 15587.7, 'duration': 3.964}, {'end': 15599.629, 'text': "i'm going to open video view again and scroll down right here and we have this get user, which is a relation.", 'start': 15591.664, 'duration': 7.965}, {'end': 15602.13, 'text': 'okay, this is whenever you see has one.', 'start': 15599.629, 'duration': 2.501}], 'summary': 'Video views were successfully saved, but need to be displayed on the front-end for user interaction.', 'duration': 29.09, 'max_score': 15573.04, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug15573040.jpg'}, {'end': 16278.14, 'src': 'embed', 'start': 16247.487, 'weight': 0, 'content': [{'end': 16252.069, 'text': "okay, and we can write here dislike, because we're going to implement this section as well.", 'start': 16247.487, 'duration': 4.582}, {'end': 16256.75, 'text': 'okay, this access control only applies to like and dislike.', 'start': 16252.069, 'duration': 4.681}, {'end': 16258.691, 'text': 'and what are the rules?', 'start': 16256.75, 'duration': 1.941}, {'end': 16271.113, 'text': "let's specify that rules are the following we allow only whose role is authorized authorized.", 'start': 16258.691, 'duration': 12.422}, {'end': 16272.835, 'text': 'okay, just like this.', 'start': 16271.113, 'duration': 1.722}, {'end': 16278.14, 'text': "now, if i reload and click the button, i'm redirected to the login page.", 'start': 16272.835, 'duration': 5.305}], 'summary': 'Implementing access control for like and dislike, allowing only authorized roles.', 'duration': 30.653, 'max_score': 16247.487, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug16247487.jpg'}, {'end': 16413.605, 'src': 'embed', 'start': 16376.036, 'weight': 1, 'content': [{'end': 16381.02, 'text': 'we need to apply ajax right here when we click like and dislike buttons.', 'start': 16376.036, 'duration': 4.984}, {'end': 16385.043, 'text': "so let's implement ajax.", 'start': 16381.02, 'duration': 4.023}, {'end': 16397.092, 'text': "we're going to use pjax, which is for working with ajax actually, and if framework it has a very good integration with pjax and let's do like this.", 'start': 16385.043, 'duration': 12.049}, {'end': 16403.537, 'text': "so right here i'm going to use php pjax widget.", 'start': 16397.092, 'duration': 6.445}, {'end': 16413.605, 'text': "okay, pjax, okay, i'm going to start right here my pjax widget and i'm going to end it right here.", 'start': 16403.537, 'duration': 10.068}], 'summary': 'Implement ajax using pjax for like and dislike buttons in php.', 'duration': 37.569, 'max_score': 16376.036, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug16376036.jpg'}], 'start': 15135.865, 'title': 'Video functionality implementation', 'summary': 'Covers implementing video view count, creating a table to store individual views, displaying view counts on the front-end, implementing like and dislike functionality, and integrating access control and ajax for improved user experience.', 'chapters': [{'end': 15433.137, 'start': 15135.865, 'title': 'Implementing video view count', 'summary': 'Discusses implementing a video view count feature and creating a table to store individual views, including user information, and generating corresponding code and models.', 'duration': 297.272, 'highlights': ['The chapter discusses creating a table to store individual views, including user information and implementing a video view count feature.', "A migration is applied to create the 'video view' table with fields such as video id, user id, and created at, with foreign keys and indices generated.", 'The chapter mentions the use of Gi tool for generating models and preferences saved in the runtime folder, and the exclusion of user-generated content from version control using git ignore.']}, {'end': 15897.367, 'start': 15433.817, 'title': 'Implementing video views and like/dislike functionality', 'summary': "Details the process of implementing video views, including the creation of a 'video view' instance with user and timestamp details, as well as the display of view counts on the front-end, with a demonstration of an increasing count upon page reload. additionally, it outlines the plan for implementing like and dislike functionality, with the creation of a 'video like' table containing video id, user id, date, and type fields.", 'duration': 463.55, 'highlights': ["The process of implementing video views, including creating a 'video view' instance with user and timestamp details, and display of view counts on the front-end, with a demonstration of an increasing count upon page reload", "The plan for implementing like and dislike functionality, with the creation of a 'video like' table containing video id, user id, date, and type fields", "Detailed explanation of creating a 'video like' table with specific field types and constraints"]}, {'end': 16212.993, 'start': 15897.367, 'title': 'Video like functionality implementation', 'summary': 'Details the implementation of a video like functionality, including the generation and application of migration, model generation, controller action creation, and the process of creating and saving a new videolike instance, encountering an issue with user authentication.', 'duration': 315.626, 'highlights': ["The migration for the video like functionality was successfully generated and applied using 'phpe migrate', with one migration being applied immediately.", "The process of model generation for 'Video Like' was demonstrated, including the creation of the model and the active query.", "The implementation of a controller action for the video like functionality was detailed, involving the creation of an 'action like' and the introduction of a protected function to find and return the video based on the provided ID.", 'The creation and saving of a new VideoLike instance was explained, involving the assignment of videoId and userId, encountering an issue with user authentication where the userId cannot be blank.']}, {'end': 16660.907, 'start': 16213.393, 'title': 'Implementing access control and ajax for video controller', 'summary': "Discusses implementing access control for 'like' and 'dislike' actions, allowing only authorized users, and integrating ajax using pjax widget to replace button content via ajax request, resulting in improved user experience.", 'duration': 447.514, 'highlights': ["Implementing access control for 'like' and 'dislike' actions, allowing only authorized users, and specifying rules to restrict access based on user role.", "Integrating pjax widget to make Ajax requests when clicking 'like' and 'dislike' buttons, resulting in a seamless user experience without page reload.", 'Creating a separate view file for buttons, returning it from the controller using render ajax, and updating the buttons content using Ajax for improved user interface.']}], 'duration': 1525.042, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug15135865.jpg', 'highlights': ["Implementing access control for 'like' and 'dislike' actions, allowing only authorized users, and specifying rules to restrict access based on user role.", "Integrating pjax widget to make Ajax requests when clicking 'like' and 'dislike' buttons, resulting in a seamless user experience without page reload.", "The process of implementing video views, including creating a 'video view' instance with user and timestamp details, and display of view counts on the front-end, with a demonstration of an increasing count upon page reload", 'The chapter discusses creating a table to store individual views, including user information and implementing a video view count feature.']}, {'end': 17754.564, 'segs': [{'end': 16774.333, 'src': 'embed', 'start': 16722.894, 'weight': 0, 'content': [{'end': 16728.359, 'text': 'so we have a lot of small things to do right here around this like and dislike feature.', 'start': 16722.894, 'duration': 5.465}, {'end': 16734.982, 'text': "okay, so let's focus on one button like button, and then we can implement this for Dislike as well.", 'start': 16728.359, 'duration': 6.623}, {'end': 16744.003, 'text': 'Okay, so if I click the Like button a few more times, in the database it creates several Like records, which is not good, okay?', 'start': 16735.921, 'duration': 8.082}, {'end': 16749.144, 'text': 'So if I like the video and then I click the same button, it is an Unlike.', 'start': 16744.242, 'duration': 4.902}, {'end': 16751.185, 'text': 'If I click, it is a Like.', 'start': 16749.844, 'duration': 1.341}, {'end': 16752.744, 'text': 'If I click, it is an Unlike.', 'start': 16751.305, 'duration': 1.439}, {'end': 16758.986, 'text': 'So it just deletes the Like record, Dislike record, okay? So we need to handle this.', 'start': 16753.025, 'duration': 5.961}, {'end': 16760.607, 'text': "And let's do like this.", 'start': 16759.606, 'duration': 1.001}, {'end': 16767.85, 'text': "I'm going to write VideoLike equals to, and let's find if VideoLike already exists.", 'start': 16761.026, 'duration': 6.824}, {'end': 16774.333, 'text': "okay?. Let's find VideoLike and let's specify right here a couple of and where statements.", 'start': 16767.85, 'duration': 6.483}], 'summary': 'Improving like and dislike feature to prevent multiple records and handle like/unlike actions.', 'duration': 51.439, 'max_score': 16722.894, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug16722894.jpg'}, {'end': 17280.763, 'src': 'embed', 'start': 17253.507, 'weight': 1, 'content': [{'end': 17268.968, 'text': "so let's create this method right here, public function liked, and this one will add one more end wear where type corresponds to video like.", 'start': 17253.507, 'duration': 15.461}, {'end': 17272.052, 'text': 'type like, just like this.', 'start': 17268.968, 'duration': 3.084}, {'end': 17273.013, 'text': 'okay, awesome.', 'start': 17272.052, 'duration': 0.961}, {'end': 17278.42, 'text': "so let's add this method liked right here and look at this.", 'start': 17273.013, 'duration': 5.407}, {'end': 17280.763, 'text': "it's a very, very readable as well.", 'start': 17278.42, 'duration': 2.343}], 'summary': "Creating a public function 'liked' to add one new 'like' for video type.", 'duration': 27.256, 'max_score': 17253.507, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug17253507.jpg'}, {'end': 17365.57, 'src': 'embed', 'start': 17336.922, 'weight': 5, 'content': [{'end': 17341.565, 'text': "okay, let's hit the button again and now it turns into gray.", 'start': 17336.922, 'duration': 4.643}, {'end': 17349.771, 'text': "okay. so if i reload it's gray, if i click right here, it turns into blue okay, which is very good.", 'start': 17341.565, 'duration': 8.206}, {'end': 17351.634, 'text': 'Awesome! Okay.', 'start': 17351.013, 'duration': 0.621}, {'end': 17354.197, 'text': 'so what else do we need?', 'start': 17351.634, 'duration': 2.563}, {'end': 17357.721, 'text': 'We need to output the count how many likes the video has.', 'start': 17354.257, 'duration': 3.464}, {'end': 17364.128, 'text': "Okay, so let's go to the buttons right here, and we have 9 hard-coded.", 'start': 17357.741, 'duration': 6.387}, {'end': 17365.57, 'text': "so let's change this.", 'start': 17364.128, 'duration': 1.442}], 'summary': 'Demonstrating button functionality, changing colors, and updating like count to 9.', 'duration': 28.648, 'max_score': 17336.922, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug17336922.jpg'}, {'end': 17665.555, 'src': 'embed', 'start': 17636.48, 'weight': 3, 'content': [{'end': 17639.72, 'text': 'so we have this disliked method in video like query.', 'start': 17636.48, 'duration': 3.24}, {'end': 17642.521, 'text': 'so now we can use this right here and we have.', 'start': 17639.72, 'duration': 2.801}, {'end': 17647.442, 'text': 'this is disliked by method ready and right here.', 'start': 17642.521, 'duration': 4.921}, {'end': 17649.083, 'text': 'the phpstorm can understand this.', 'start': 17647.442, 'duration': 1.641}, {'end': 17651.204, 'text': "we don't have get dislikes.", 'start': 17649.583, 'duration': 1.621}, {'end': 17653.506, 'text': "so let's go to likes method.", 'start': 17651.204, 'duration': 2.302}, {'end': 17659.13, 'text': 'just duplicate this one, call it get dislikes, okay.', 'start': 17653.506, 'duration': 5.624}, {'end': 17665.555, 'text': 'we need to go to video like, which has type and we are disliked okay.', 'start': 17659.13, 'duration': 6.425}], 'summary': "Using the video query method, we can now access the 'dislikes' data in phpstorm.", 'duration': 29.075, 'max_score': 17636.48, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug17636480.jpg'}], 'start': 16660.907, 'title': 'Implementing like and dislike functionality', 'summary': 'Focuses on implementing a like and dislike feature for videos, addressing issues such as handling multiple likes, unlikes, turning buttons blue upon liking, and implementing a method to check if the current user has liked the video or not. it also demonstrates the implementation of like and dislike functionality for a video, including updating the like count, displaying likes and dislikes as arrays in php, and creating a separate dislike action in the video controller.', 'chapters': [{'end': 17336.922, 'start': 16660.907, 'title': 'Implement like and dislike feature', 'summary': 'Focuses on implementing a like and dislike feature for videos, addressing issues such as handling multiple likes, unlikes, and turning buttons blue upon liking, along with implementing a method to check if the current user has liked the video or not.', 'duration': 676.015, 'highlights': ['The functionality of the like and dislike feature, including handling multiple likes and unlikes, is explained in detail, ensuring a seamless user experience.', 'The process of implementing a method to check if the current user has liked the video is elaborated, emphasizing the need for efficient code and readability.', 'The steps for creating and utilizing methods to handle likes and dislikes for videos, including the use of find and where statements, are outlined for clarity and understanding.']}, {'end': 17754.564, 'start': 17336.922, 'title': 'Implementing like and dislike functionality', 'summary': 'Demonstrates the implementation of like and dislike functionality for a video, including updating the like count and displaying likes and dislikes as arrays in php. it also covers the creation of a separate dislike action in the video controller.', 'duration': 417.642, 'highlights': ['The chapter demonstrates the implementation of like and dislike functionality for a video, including updating the like count and displaying likes and dislikes as arrays in PHP.', "The video's like count is hard-coded as 9, and the implementation involves creating methods to retrieve and output the number of likes and dislikes for the video.", 'The implementation involves creating methods to retrieve and output the number of likes and dislikes for the video, along with updating the displayed count based on user actions such as liking or disliking the video.']}], 'duration': 1093.657, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug16660907.jpg', 'highlights': ['The functionality of the like and dislike feature, including handling multiple likes and unlikes, is explained in detail, ensuring a seamless user experience.', 'The process of implementing a method to check if the current user has liked the video is elaborated, emphasizing the need for efficient code and readability.', 'The steps for creating and utilizing methods to handle likes and dislikes for videos, including the use of find and where statements, are outlined for clarity and understanding.', 'The chapter demonstrates the implementation of like and dislike functionality for a video, including updating the like count and displaying likes and dislikes as arrays in PHP.', 'The implementation involves creating methods to retrieve and output the number of likes and dislikes for the video, along with updating the displayed count based on user actions such as liking or disliking the video.', "The video's like count is hard-coded as 9, and the implementation involves creating methods to retrieve and output the number of likes and dislikes for the video."]}, {'end': 18777.257, 'segs': [{'end': 17817.322, 'src': 'embed', 'start': 17788.353, 'weight': 4, 'content': [{'end': 17795.04, 'text': "Hit the enter, let's go right here inside, and this video has one like, but it's gray because I have not liked.", 'start': 17788.353, 'duration': 6.687}, {'end': 17799.604, 'text': 'Okay, so I click the like and now the video has two likes.', 'start': 17795.28, 'duration': 4.324}, {'end': 17801.006, 'text': 'Okay, awesome.', 'start': 17799.864, 'duration': 1.142}, {'end': 17808.713, 'text': 'So we have implemented views and we have implemented like and dislike, which is already a great progress.', 'start': 17801.606, 'duration': 7.107}, {'end': 17817.322, 'text': "Okay, let's have a closer look again on YouTube video, and we have channel name and description right here, which we don't display.", 'start': 17809.668, 'duration': 7.654}], 'summary': 'Implemented views, like, and dislike, with video now having two likes.', 'duration': 28.969, 'max_score': 17788.353, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug17788353.jpg'}, {'end': 18071.741, 'src': 'embed', 'start': 18040.769, 'weight': 2, 'content': [{'end': 18050.199, 'text': "channel does not exist just like this, and let's take out this, this one, and put in its own separate method.", 'start': 18040.769, 'duration': 9.43}, {'end': 18053.842, 'text': "actually, i'm going to use phpstorms feature for this.", 'start': 18050.199, 'duration': 3.643}, {'end': 18058.767, 'text': 'find channel, hit the enter and it generated the code for me.', 'start': 18053.842, 'duration': 4.925}, {'end': 18060.449, 'text': 'find channel.', 'start': 18059.628, 'duration': 0.821}, {'end': 18064.033, 'text': 'it does all the things what i had before.', 'start': 18060.449, 'duration': 3.584}, {'end': 18071.741, 'text': 'and when we find the channel channel just like this, i need to pass this to the view.', 'start': 18064.033, 'duration': 7.708}], 'summary': "Using phpstorm's feature, the speaker generated code for finding and passing a channel to the view.", 'duration': 30.972, 'max_score': 18040.769, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug18040769.jpg'}, {'end': 18193.624, 'src': 'embed', 'start': 18165.971, 'weight': 3, 'content': [{'end': 18177.676, 'text': "so if we just type in the url c, for example, and let's just type the code holic okay, so this opens the channel name.", 'start': 18165.971, 'duration': 11.705}, {'end': 18178.697, 'text': 'okay, this would.', 'start': 18177.676, 'duration': 1.021}, {'end': 18180.077, 'text': 'this would be awesome.', 'start': 18178.697, 'duration': 1.38}, {'end': 18184.72, 'text': "so let's just do this, and this is very, very easy to do in eFramework.", 'start': 18180.077, 'duration': 4.643}, {'end': 18193.624, 'text': 'okay, so we just need to open frontend config, main.php, and down below, when we have this url manager.', 'start': 18184.72, 'duration': 8.904}], 'summary': 'Demonstrating how to open a channel name using a specific url in eframework.', 'duration': 27.653, 'max_score': 18165.971, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug18165971.jpg'}, {'end': 18476.354, 'src': 'embed', 'start': 18454.44, 'weight': 1, 'content': [{'end': 18464.423, 'text': "save, let's update the php docs right here, reload the page and right here i see the channel name and i see this subscribe button and i see this nine.", 'start': 18454.44, 'duration': 9.983}, {'end': 18471.306, 'text': "let's take a bell button from font awesome and put in this subscribe inside the subscribe button.", 'start': 18464.423, 'duration': 6.883}, {'end': 18473.107, 'text': 'okay, so where is the bell?', 'start': 18471.306, 'duration': 1.801}, {'end': 18473.907, 'text': "let's take this bell.", 'start': 18473.107, 'duration': 0.8}, {'end': 18476.354, 'text': 'so click on this.', 'start': 18474.813, 'duration': 1.541}], 'summary': 'Updating php docs with bell icon for subscribe button.', 'duration': 21.914, 'max_score': 18454.44, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug18454440.jpg'}, {'end': 18777.257, 'src': 'embed', 'start': 18747.824, 'weight': 0, 'content': [{'end': 18755.034, 'text': 'okay, click on this icst login page, even though the request is made using ajax.', 'start': 18747.824, 'duration': 7.21}, {'end': 18767.249, 'text': 'okay, the javascript of the e-framework handles the redirect tags and makes an actual redirect to the login page.', 'start': 18755.034, 'duration': 12.215}, {'end': 18775.015, 'text': 'okay, even though that this is using ajax, this is managed by the framework by default, which is, i think, very,', 'start': 18767.249, 'duration': 7.766}, {'end': 18777.257, 'text': 'very good and gives you a lot of time saving.', 'start': 18775.015, 'duration': 2.242}], 'summary': 'E-framework handles ajax requests, saving a lot of time.', 'duration': 29.433, 'max_score': 18747.824, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug18747824.jpg'}], 'start': 17754.564, 'title': 'Implementing channel features', 'summary': 'Covers implementing like and dislike features, creating channel views in php, and implementing a channel subscription feature. it includes topics such as adding and removing likes, rendering views, setting up url routing, using html helpers, ajax requests, user authorization, and handling unauthorized requests through javascript redirects.', 'chapters': [{'end': 18039.909, 'start': 17754.564, 'title': 'Implementing like and dislike feature', 'summary': 'Discusses implementing the like and dislike feature, including adding and removing likes, displaying channel name and video description, and preparing to implement the channel page.', 'duration': 285.345, 'highlights': ['The video has two likes after clicking the like button, showing successful implementation of the like feature.', 'The chapter demonstrates securing the website from potential script tags in the video description by using html helpers encode method.', 'The chapter prepares to implement the channel page and subscribe/unsubscribe buttons for videos uploaded from a specific channel.']}, {'end': 18427.559, 'start': 18040.769, 'title': 'Creating channel views in php', 'summary': 'Discusses creating channel views in php, covering topics such as rendering views, setting up url routing, and using html helpers for creating anchor links.', 'duration': 386.79, 'highlights': ["The chapter covers rendering channel views in PHP using PHPStorm's feature for generating code and specifying the channel name for rendering.", "Setting up URL routing by modifying the frontend config, main.php, to redirect URLs like 'c/someText' to the 'channel/view' action.", 'Using HTML helpers to create anchor links for the channel username, demonstrating the functionality through the URL manager and URL rules.']}, {'end': 18777.257, 'start': 18427.559, 'title': 'Implementing channel subscription feature', 'summary': 'Details the process of implementing a channel subscription feature, including the use of ajax requests and the need for user authorization, with a demonstration of handling unauthorized requests through javascript redirects.', 'duration': 349.698, 'highlights': ["The chapter discusses the process of implementing a channel subscription feature, including updating the PHP docs, integrating a subscribe button with Font Awesome's bell icon, and linking it to a channel's subscribe action.", 'It demonstrates the use of AJAX requests for subscribing and unsubscribing from a channel, and the necessity of user authorization to perform these actions, with a focus on the handling of unauthorized requests through JavaScript redirects.', 'The chapter emphasizes the automatic redirection to the login page for unauthorized requests, even when made through AJAX, highlighting the time-saving nature of this default framework behavior.']}], 'duration': 1022.693, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug17754564.jpg', 'highlights': ['The chapter emphasizes the automatic redirection to the login page for unauthorized requests, even when made through AJAX, highlighting the time-saving nature of this default framework behavior.', "The chapter discusses the process of implementing a channel subscription feature, including updating the PHP docs, integrating a subscribe button with Font Awesome's bell icon, and linking it to a channel's subscribe action.", "The chapter covers rendering channel views in PHP using PHPStorm's feature for generating code and specifying the channel name for rendering.", "Setting up URL routing by modifying the frontend config, main.php, to redirect URLs like 'c/someText' to the 'channel/view' action.", 'The video has two likes after clicking the like button, showing successful implementation of the like feature.']}, {'end': 20557.822, 'segs': [{'end': 18907.837, 'src': 'embed', 'start': 18873.345, 'weight': 0, 'content': [{'end': 18878.837, 'text': "subscriber query click preview, click generate button and that's it.", 'start': 18873.345, 'duration': 5.492}, {'end': 18887.382, 'text': 'it is so easy to create table and to generate model in eFramework that I just love working with it.', 'start': 18878.837, 'duration': 8.545}, {'end': 18893.306, 'text': 'okay, so right here we already have the subscriber class, so we can create an instance out of it.', 'start': 18887.382, 'duration': 5.924}, {'end': 18899.729, 'text': 'okay, new subscriber, just like this subscriber.', 'start': 18893.306, 'duration': 6.423}, {'end': 18905.073, 'text': 'excuse me, channel id equals to channels id.', 'start': 18899.729, 'duration': 5.344}, {'end': 18907.837, 'text': 'okay, subscriber.', 'start': 18905.073, 'duration': 2.764}], 'summary': 'Creating tables and models in eframework is easy, with a simple process for generating and previewing queries.', 'duration': 34.492, 'max_score': 18873.345, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug18873345.jpg'}, {'end': 19287.246, 'src': 'embed', 'start': 19260.631, 'weight': 2, 'content': [{'end': 19267.433, 'text': 'so actually the channel and the user has like many to many connection, okay.', 'start': 19260.631, 'duration': 6.802}, {'end': 19275.177, 'text': 'so user has can be subscribed to main channel and channel can have many subscribers.', 'start': 19267.433, 'duration': 7.744}, {'end': 19282.823, 'text': 'okay, right here we have to make a relation between user and user as well.', 'start': 19275.177, 'duration': 7.646}, {'end': 19287.246, 'text': 'we are like junction table which is called subscriber table.', 'start': 19282.823, 'duration': 4.423}], 'summary': 'Users and channels have a many-to-many connection with a subscriber table.', 'duration': 26.615, 'max_score': 19260.631, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug19260631.jpg'}, {'end': 19541.258, 'src': 'embed', 'start': 19509.955, 'weight': 4, 'content': [{'end': 19513.217, 'text': 'but there may be hundreds of videos, so we need pagination as well.', 'start': 19509.955, 'duration': 3.262}, {'end': 19517.841, 'text': 'okay, so whenever you need pagination, consider to use data providers.', 'start': 19513.217, 'duration': 4.624}, {'end': 19521.864, 'text': "and more specifically, right here we're going to use active data provider.", 'start': 19517.841, 'duration': 4.023}, {'end': 19534.153, 'text': "okay, data provider variable is new active data provider and we're going to specify query right here to be video.", 'start': 19521.864, 'duration': 12.289}, {'end': 19541.258, 'text': 'find whose creator is the currently uh, the channel user.', 'start': 19534.153, 'duration': 7.105}], 'summary': 'Use active data provider for pagination with hundreds of videos.', 'duration': 31.303, 'max_score': 19509.955, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug19509955.jpg'}, {'end': 19869.439, 'src': 'embed', 'start': 19842.492, 'weight': 3, 'content': [{'end': 19845.836, 'text': "Let's go to the test channel and right here click the subscribe button.", 'start': 19842.492, 'duration': 3.344}, {'end': 19848.82, 'text': 'And these are the videos for test channel.', 'start': 19846.217, 'duration': 2.603}, {'end': 19854.867, 'text': 'Okay, so we have successfully implemented subscribe and unsubscribe feature in the channel page.', 'start': 19849.3, 'duration': 5.567}, {'end': 19855.909, 'text': 'For you.', 'start': 19855.228, 'duration': 0.681}, {'end': 19860.554, 'text': 'as a challenge, I will leave you to create a user profile table,', 'start': 19855.909, 'duration': 4.645}, {'end': 19869.439, 'text': 'connect it to the user table and inside the user profile you can have a one field for thumbnail okay,', 'start': 19861.255, 'duration': 8.184}], 'summary': 'Implemented subscribe/unsubscribe feature in test channel page.', 'duration': 26.947, 'max_score': 19842.492, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug19842492.jpg'}, {'end': 19955.047, 'src': 'embed', 'start': 19928.215, 'weight': 1, 'content': [{'end': 19931.697, 'text': 'Sending email when the user subscribes to channel.', 'start': 19928.215, 'duration': 3.482}, {'end': 19938.139, 'text': "We're going to send an email to channel that, hey, look at this, the following user has just subscribed to you.", 'start': 19931.717, 'duration': 6.422}, {'end': 19942.361, 'text': "okay, and i'm going to use mail trap for this.", 'start': 19939.039, 'duration': 3.322}, {'end': 19944.762, 'text': "okay, let's go to mail trap.", 'start': 19942.361, 'duration': 2.401}, {'end': 19947.123, 'text': "let's just type mail trap and open.", 'start': 19944.762, 'duration': 2.361}, {'end': 19949.064, 'text': 'open this mail trap io.', 'start': 19947.123, 'duration': 1.941}, {'end': 19955.047, 'text': "it's a free, open like, not open source, free and, uh, fake mail mailer sender.", 'start': 19949.064, 'duration': 5.983}], 'summary': 'Sending email notification to channel upon user subscription using mailtrap.', 'duration': 26.832, 'max_score': 19928.215, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug19928215.jpg'}], 'start': 18777.257, 'title': 'Implementation of channel page features', 'summary': 'Covers creating a subscriber table with specified fields using eframework, updating the user model to establish a many-to-many connection between users and channels, and implementing features such as specifying paths for video items, creating link helpers, and sending emails upon subscription. it also explains the creation of a junction table for subscribers and setting up pagination for videos uploaded by the channel, resulting in successful implementation and testing of the subscription functionality, as well as email sending using mail trap for user subscription.', 'chapters': [{'end': 19233.216, 'start': 18777.257, 'title': 'Creating subscriber table and model in eframework', 'summary': 'Covers the process of creating a subscriber table with specified fields using eframework, generating a subscriber model, and implementing methods to check and handle user subscriptions, resulting in successful implementation and testing of the subscription functionality.', 'duration': 455.959, 'highlights': ['Successfully creating a subscriber table with specified fields and applying the migration using eFramework.', 'Generating a subscriber model using model generator in eFramework.', 'Implementing methods to check if the user is already subscribed, creating a subscriber instance, and rendering the subscribe view file.', "Testing the subscription functionality, checking for records in the database, and implementing the counter of subscribers and styling the subscribe button based on user's subscription status."]}, {'end': 19640.517, 'start': 19233.216, 'title': 'User model update and many-to-many relation', 'summary': 'Covers updating the user model to establish a many-to-many connection between users and channels, explaining the creation of a junction table for subscribers and implementing a function to retrieve the number of subscribers for a specific channel, as well as setting up pagination for videos uploaded by the channel.', 'duration': 407.301, 'highlights': ['The user model is updated to establish a many-to-many connection between users and channels, creating a junction table for subscribers, and implementing a function to retrieve the number of subscribers for a specific channel.', 'The process involves setting up pagination for videos uploaded by the channel and considering the use of data providers, specifically an active data provider, to display only published videos uploaded by the channel.', 'The implementation includes explaining the creation of a function to retrieve the number of subscribers for a specific channel and using AJAX to dynamically update the number of subscribers when a user subscribes or unsubscribes from a channel.']}, {'end': 20557.822, 'start': 19640.517, 'title': 'Implementing channel page features', 'summary': 'Covers implementing features such as specifying paths for video items, creating link helpers, implementing subscribe and unsubscribe features, and sending emails upon subscription, with a focus on implementing email sending using mail trap for user subscription.', 'duration': 917.305, 'highlights': ['Implementing email sending using mail trap for user subscription, with the help of mailer helper and setting up the email template in HTML and text formats.', 'Creating link helpers for channel links and specifying paths for video items.', 'Implementing subscribe and unsubscribe features on the channel page, allowing users to subscribe and unsubscribe from channels.', 'Specifying paths for video items by writing relative and absolute paths.']}], 'duration': 1780.565, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug18777257.jpg', 'highlights': ['Successfully creating a subscriber table with specified fields and applying the migration using eFramework.', 'Implementing email sending using mail trap for user subscription, with the help of mailer helper and setting up the email template in HTML and text formats.', 'The user model is updated to establish a many-to-many connection between users and channels, creating a junction table for subscribers, and implementing a function to retrieve the number of subscribers for a specific channel.', 'Implementing subscribe and unsubscribe features on the channel page, allowing users to subscribe and unsubscribe from channels.', 'Setting up pagination for videos uploaded by the channel and considering the use of data providers, specifically an active data provider, to display only published videos uploaded by the channel.']}, {'end': 22266.65, 'segs': [{'end': 20658.438, 'src': 'embed', 'start': 20629.302, 'weight': 0, 'content': [{'end': 20633.625, 'text': "Okay This is the JavaScript in three hours and let's upload one more video.", 'start': 20629.302, 'duration': 4.323}, {'end': 20637.393, 'text': 'which will be like data structures.', 'start': 20635.612, 'duration': 1.781}, {'end': 20639.653, 'text': "okay, so let's just change the thumbnail.", 'start': 20637.393, 'duration': 2.26}, {'end': 20645.115, 'text': 'the videos, of course, are not real, but i took the thumbnails to look like real.', 'start': 20639.653, 'duration': 5.462}, {'end': 20646.495, 'text': "so let's save this.", 'start': 20645.115, 'duration': 1.38}, {'end': 20649.316, 'text': 'and here we have so free code camp has three videos.', 'start': 20646.495, 'duration': 2.821}, {'end': 20652.977, 'text': 'all of them are published and we can see them on the home page.', 'start': 20649.316, 'duration': 3.661}, {'end': 20658.438, 'text': 'okay, right here we see latest videos published by free code camp.', 'start': 20652.977, 'duration': 5.461}], 'summary': "Uploaded 3 javascript and data structures videos on free code camp's home page.", 'duration': 29.136, 'max_score': 20629.302, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug20629302.jpg'}, {'end': 20886.756, 'src': 'embed', 'start': 20856.347, 'weight': 1, 'content': [{'end': 20860.889, 'text': "and inside the by keyword i'm going to specify the actual keyword.", 'start': 20856.347, 'duration': 4.542}, {'end': 20863.149, 'text': 'so right here we need to search.', 'start': 20860.889, 'duration': 2.26}, {'end': 20867.09, 'text': 'we need to render this search search view.', 'start': 20863.149, 'duration': 3.941}, {'end': 20869.511, 'text': 'of course, youtube does it slightly differently.', 'start': 20867.09, 'duration': 2.421}, {'end': 20871.992, 'text': 'when i search something, for example javascript.', 'start': 20869.511, 'duration': 2.481}, {'end': 20878.754, 'text': "Okay, so it shows in a list view in the one video on the line, but let's do it differently.", 'start': 20872.552, 'duration': 6.202}, {'end': 20886.756, 'text': "Okay, so let's do by default, as we display on home page, because that's easier for us and give us a little bit of time saving,", 'start': 20878.814, 'duration': 7.942}], 'summary': 'Demonstrating how to customize search view and display on home page.', 'duration': 30.409, 'max_score': 20856.347, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug20856347.jpg'}, {'end': 21242.713, 'src': 'embed', 'start': 21214.152, 'weight': 8, 'content': [{'end': 21221.218, 'text': 'so save and reload and this whatever is written in the url is inserted right now inside the form.', 'start': 21214.152, 'duration': 7.066}, {'end': 21225.24, 'text': "Okay, so let's test this search working functionality.", 'start': 21221.978, 'duration': 3.262}, {'end': 21233.306, 'text': 'First of all, if we delete everything and hit enter, it just writes no video found and we need to fix this one as well.', 'start': 21225.601, 'duration': 7.705}, {'end': 21235.767, 'text': 'Go to the video controller and right here.', 'start': 21233.806, 'duration': 1.961}, {'end': 21242.713, 'text': "so actually I'm going to take out this code in a variable called query.", 'start': 21237.448, 'duration': 5.265}], 'summary': "Testing search functionality, fixing 'no video found' issue, and refactoring code into a variable.", 'duration': 28.561, 'max_score': 21214.152, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug21214152.jpg'}, {'end': 21446.826, 'src': 'embed', 'start': 21419.922, 'weight': 2, 'content': [{'end': 21430.214, 'text': 'so this looks like closer to what we want, rather than php for beginners or javascript tutorial, And this one has a higher score.', 'start': 21419.922, 'duration': 10.292}, {'end': 21434.537, 'text': 'And we can actually sort the videos based on the score.', 'start': 21430.654, 'duration': 3.883}, {'end': 21440.061, 'text': 'Of course, the video finding algorithm is much, much more complex on YouTube.', 'start': 21434.937, 'duration': 5.124}, {'end': 21443.623, 'text': 'It uses the artificial intelligence and machine learning for this.', 'start': 21440.121, 'duration': 3.502}, {'end': 21446.826, 'text': 'And it finds the video based on the information.', 'start': 21444.284, 'duration': 2.542}], 'summary': 'Youtube uses ai and machine learning to sort videos based on score.', 'duration': 26.904, 'max_score': 21419.922, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug21419922.jpg'}, {'end': 21579.671, 'src': 'embed', 'start': 21503.497, 'weight': 3, 'content': [{'end': 21509.44, 'text': "Let's just save this and reload the page and I see this one PHP numbers is the first one.", 'start': 21503.497, 'duration': 5.943}, {'end': 21511.981, 'text': 'PHP strings tutorial is the second one.', 'start': 21509.44, 'duration': 2.541}, {'end': 21514.763, 'text': 'then we have JavaScript tutorial and then PHP for beginners.', 'start': 21511.981, 'duration': 2.782}, {'end': 21517.105, 'text': 'So it actually used this kind of sorting.', 'start': 21515.103, 'duration': 2.002}, {'end': 21525.232, 'text': 'However, as I mentioned, taking out the query parameter and putting inside the database query is really unsecure thing,', 'start': 21517.205, 'duration': 8.027}, {'end': 21529.996, 'text': 'and your code basically contains SQL injection.', 'start': 21525.232, 'duration': 4.764}, {'end': 21535.639, 'text': 'And this needs to be fixed, and this keyword needs to be bound as a parameter.', 'start': 21530.396, 'duration': 5.243}, {'end': 21541.583, 'text': "There's no direct way to bound this parameter right now, but there is a solution, believe me.", 'start': 21535.919, 'duration': 5.664}, {'end': 21546.866, 'text': "And I'm just going to go into very details and implement these kind of things.", 'start': 21541.843, 'duration': 5.023}, {'end': 21552.549, 'text': "So just find out this on your own, okay? So for now, let's just leave this.", 'start': 21547.266, 'duration': 5.283}, {'end': 21557.812, 'text': 'But again, as a side note, this is not secure to leave on your production application.', 'start': 21552.929, 'duration': 4.883}, {'end': 21563.194, 'text': "Okay, actually, I'm going to fully remove this, okay? Let's just remove.", 'start': 21559.15, 'duration': 4.044}, {'end': 21573.484, 'text': 'Okay, so we have the video finding algorithm which finds the videos and if we specify some description from the backend, some tags,', 'start': 21564.896, 'duration': 8.588}, {'end': 21579.671, 'text': 'this description and tags are applied and videos are found based on this information.', 'start': 21573.484, 'duration': 6.187}], 'summary': 'The transcript covers fixing sql injection and implementing secure parameter binding in php and javascript tutorials.', 'duration': 76.174, 'max_score': 21503.497, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug21503497.jpg'}, {'end': 21665.007, 'src': 'embed', 'start': 21636.224, 'weight': 6, 'content': [{'end': 21647.016, 'text': 'we need to go to video view page right here, and when we select the video and pass it down to the view file right here, we can select similar videos.', 'start': 21636.224, 'duration': 10.792}, {'end': 21649.979, 'text': "okay. so let's select similar videos.", 'start': 21647.016, 'duration': 2.963}, {'end': 21651.641, 'text': "we don't want pagination right now.", 'start': 21649.979, 'duration': 1.662}, {'end': 21656.667, 'text': 'we can just display the first 10 similar videos, for example.', 'start': 21651.641, 'duration': 5.026}, {'end': 21661.464, 'text': "okay, so let's just call video find.", 'start': 21657.881, 'duration': 3.583}, {'end': 21665.007, 'text': 'we need to find all published videos by keyword.', 'start': 21661.464, 'duration': 3.543}], 'summary': 'Develop feature to display 10 similar videos based on keyword search.', 'duration': 28.783, 'max_score': 21636.224, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug21636224.jpg'}], 'start': 20557.822, 'title': 'Video publishing and search optimization', 'summary': 'Covers the process of creating and publishing three videos on freecodecamp, implementing a search functionality using php and mysql, optimizing youtube video search results by using php, refining results by relevance, and implementing sorting, finding similar videos, and fixing sql injection issues.', 'chapters': [{'end': 21271.889, 'start': 20557.822, 'title': 'Freecodecamp video upload and search', 'summary': 'Covers the process of creating and publishing three videos on freecodecamp, implementing a search functionality using php and mysql, and fixing issues related to search functionality and url handling.', 'duration': 714.067, 'highlights': ['Implemented video upload and publishing for Python, JavaScript, and data structures on FreeCodeCamp, totaling in three published videos.', "Developed a search functionality using PHP and MySQL, allowing users to search for videos based on keywords, with a focus on implementing the 'by keyword' method.", "Resolved issues related to URL handling and search functionality, including fixing the display of 'no video found' message and ensuring the URL parameters are reflected in the search form."]}, {'end': 21446.826, 'start': 21272.429, 'title': 'Youtube video search optimization', 'summary': 'Discusses optimizing youtube video search results by using php as a search query, refining results by relevance, and understanding the video finding algorithm which utilizes artificial intelligence and machine learning.', 'duration': 174.397, 'highlights': ['YouTube video search results can be optimized by using PHP as a search query and refining results by relevance.', 'The video finding algorithm on YouTube utilizes artificial intelligence and machine learning for result optimization.', 'Refining search results by relevance can improve the user experience on YouTube.']}, {'end': 22266.65, 'start': 21447.146, 'title': 'Implementing sorting and finding similar videos', 'summary': 'Discusses implementing sorting based on keyword and order, fixing sql injection by binding parameters, implementing video finding algorithm using description and tags, and finding and displaying similar videos using match against and limiting to 10 videos.', 'duration': 819.504, 'highlights': ['Implementing sorting based on keyword and order, showing PHP numbers as the first result, PHP strings tutorial as the second result, JavaScript tutorial as the third result, and PHP for beginners as the fourth result', 'Fixing SQL injection by binding the keyword parameter, addressing the unsecure nature of leaving it in the production application, and removing it from the code', "Implementing video finding algorithm using description and tags, allowing the search for videos based on specified information, such as finding Git for beginners and PHP strings tutorial by specifying the keyword 'Git'", 'Implementing the display of similar videos by finding all published videos by a keyword, specifying the video title, limiting the display to the first 10 similar videos, and excluding the current video from the found list']}], 'duration': 1708.828, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug20557822.jpg', 'highlights': ['Implemented video upload and publishing for Python, JavaScript, and data structures on FreeCodeCamp, totaling in three published videos.', "Developed a search functionality using PHP and MySQL, allowing users to search for videos based on keywords, with a focus on implementing the 'by keyword' method.", 'Refining search results by relevance can improve the user experience on YouTube.', 'Implemented sorting based on keyword and order, showing PHP numbers as the first result, PHP strings tutorial as the second result, JavaScript tutorial as the third result, and PHP for beginners as the fourth result', 'Fixing SQL injection by binding the keyword parameter, addressing the unsecure nature of leaving it in the production application, and removing it from the code', "Implementing video finding algorithm using description and tags, allowing the search for videos based on specified information, such as finding Git for beginners and PHP strings tutorial by specifying the keyword 'Git'", 'Implementing the display of similar videos by finding all published videos by a keyword, specifying the video title, limiting the display to the first 10 similar videos, and excluding the current video from the found list', 'YouTube video search results can be optimized by using PHP as a search query and refining results by relevance.', "Resolved issues related to URL handling and search functionality, including fixing the display of 'no video found' message and ensuring the URL parameters are reflected in the search form."]}, {'end': 24045.889, 'segs': [{'end': 22296.725, 'src': 'embed', 'start': 22266.67, 'weight': 0, 'content': [{'end': 22270.592, 'text': "So let's implement the history page on the front end side as well.", 'start': 22266.67, 'duration': 3.922}, {'end': 22274.554, 'text': 'So we have already a table video view.', 'start': 22271.053, 'duration': 3.501}, {'end': 22281.978, 'text': 'And inside the video view, we save which videos are visited at what time by which user.', 'start': 22274.815, 'duration': 7.163}, {'end': 22288.662, 'text': 'And we need to make a select from this table, video view table.', 'start': 22283.219, 'duration': 5.443}, {'end': 22296.725, 'text': "But it's a little bit tricky, okay? So I'm going to show this right now, how we're going to actually do this.", 'start': 22290.182, 'duration': 6.543}], 'summary': 'Implement history page on front end, select visited videos from table video view.', 'duration': 30.055, 'max_score': 22266.67, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug22266670.jpg'}, {'end': 23010.205, 'src': 'embed', 'start': 22982.197, 'weight': 1, 'content': [{'end': 22987.939, 'text': 'We have nice URLs, we have email sending and what else.', 'start': 22982.197, 'duration': 5.742}, {'end': 22990.08, 'text': "so let's do one more thing.", 'start': 22987.939, 'duration': 2.141}, {'end': 22996.482, 'text': "let's go to the backend right now and create a very, very minimalistic, like analytics dashboard.", 'start': 22990.08, 'duration': 6.402}, {'end': 23001.123, 'text': 'okay, so we have so many things done and we need, like minimalistic analytics.', 'start': 22996.482, 'duration': 4.641}, {'end': 23010.205, 'text': "when we open this dashboard page, let's show the latest uploaded video, for example, number of views, number of subscribers and some.", 'start': 23001.123, 'duration': 9.082}], 'summary': 'Create a minimalistic analytics dashboard for latest uploaded video with views and subscribers.', 'duration': 28.008, 'max_score': 22982.197, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug22982197.jpg'}, {'end': 23253.443, 'src': 'embed', 'start': 23223.287, 'weight': 3, 'content': [{'end': 23235.195, 'text': 'so select everything from video views, join to video and find those views whose videos are uploaded by current user and finally get account.', 'start': 23223.287, 'duration': 11.908}, {'end': 23237.557, 'text': 'okay, this count will be simply number.', 'start': 23235.195, 'duration': 2.362}, {'end': 23243.059, 'text': "now we need, let's select also number of subscribers.", 'start': 23238.357, 'duration': 4.702}, {'end': 23247.941, 'text': 'okay, number of subscribers.', 'start': 23243.059, 'duration': 4.882}, {'end': 23253.443, 'text': 'this is going to be the current user, which will be, in this case, e app identity.', 'start': 23247.941, 'duration': 5.502}], 'summary': 'Retrieve count of video views and number of subscribers for the current user.', 'duration': 30.156, 'max_score': 23223.287, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug23223287.jpg'}, {'end': 23643.987, 'src': 'embed', 'start': 23619.088, 'weight': 2, 'content': [{'end': 23624.692, 'text': "So if we go to the dashboard and let's go to this particular video,", 'start': 23619.088, 'duration': 5.604}, {'end': 23628.995, 'text': "refresh it a few more times to increase the number of views and let's like the video.", 'start': 23624.692, 'duration': 4.303}, {'end': 23633.499, 'text': 'okay?. So right here i see one like in nine views.', 'start': 23628.995, 'duration': 4.504}, {'end': 23635.8, 'text': 'okay, so this is very good.', 'start': 23633.499, 'duration': 2.301}, {'end': 23641.645, 'text': "of course we can apply some, like small padding and things like that, but i'm just gonna spend time more on this.", 'start': 23635.8, 'duration': 5.845}, {'end': 23643.987, 'text': 'so we need more cards.', 'start': 23641.645, 'duration': 2.342}], 'summary': 'Video has 9 views and 1 like, aiming for more engagement.', 'duration': 24.899, 'max_score': 23619.088, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug23619088.jpg'}], 'start': 22266.67, 'title': 'Video history and analytics implementation', 'summary': 'Discusses implementing a history page on the front end, optimizing video history display, backend analytics, and querying video data and user subscribers, resulting in improved display and dashboard with features such as latest uploaded video, number of views, and subscribers.', 'chapters': [{'end': 22419.558, 'start': 22266.67, 'title': 'Implementing history page on front end', 'summary': 'Discusses implementing a history page on the front end by selecting visited videos, ensuring uniqueness, and sorting by latest visit time.', 'duration': 152.888, 'highlights': ['Implementing a history page on the front end by selecting visited videos and ensuring uniqueness', 'Sorting visited videos by their latest visit time', 'Using SQL queries to achieve the desired functionality']}, {'end': 22908.701, 'start': 22421.354, 'title': 'Optimizing video history display', 'summary': 'Discusses optimizing the video history display by implementing a query to select the maximum visit date for each video for a specific user, joining it with the video table, and sorting the results in descending order by the maximum visit date, resulting in an improved video history display.', 'duration': 487.347, 'highlights': ['The query selects the maximum visit date for each video for user number three, optimizing the video history display.', 'The chapter covers implementing the query in the video controller and rendering the video history page, simplifying the process of optimizing the video history display.', 'The chapter emphasizes joining the virtual table with the video table and using an alias for the video find table, streamlining the process of optimizing the video history display.']}, {'end': 23186.691, 'start': 22909.021, 'title': 'Implementing history and backend analytics', 'summary': 'Covers implementing history functionality to display one video at a time with other information, as well as creating a minimalistic analytics dashboard with features such as displaying the latest uploaded video, number of views, and number of subscribers on the backend side.', 'duration': 277.67, 'highlights': ['Implementing history functionality to display one video at a time with other information on the front-end side.', 'Creating a minimalistic analytics dashboard on the backend side, including features such as displaying the latest uploaded video, number of views, and number of subscribers.', 'Selecting the latest video and limiting the query to avoid excessive memory usage on the backend side.']}, {'end': 23490.964, 'start': 23188.442, 'title': 'Querying video data and user subscribers', 'summary': 'Covers querying video views, user-created videos, and subscriber counts, with a focus on selecting the latest subscribers and displaying them, along with the number of views and subscribers.', 'duration': 302.522, 'highlights': ['Select video views joined with videos uploaded by the current user and retrieve the count, which is a simple number.', "Obtain the number of subscribers for the current user, using the 'get subscribers' method and then retrieving the count.", "Retrieve the latest subscribers by querying the subscriber table and limiting the selection to the current user's channel ID, then displaying the latest three subscribers."]}, {'end': 24045.889, 'start': 23492.392, 'title': 'Creating video cards and displaying subscriber information', 'summary': 'Covers the creation of video cards, displaying video information such as likes, views, and titles, and displaying subscriber information, including sorting subscribers by latest first and using the debug bar for detailed application insights.', 'duration': 553.497, 'highlights': ['The chapter covers the creation of video cards, including displaying video information such as likes, views, and titles, as well as an edit button for video updates.', 'Demonstrates displaying subscriber information, including sorting subscribers by latest first and accessing detailed application insights using the debug bar.', 'Provides insights into using PHP to access and display subscriber user information, including usernames and sorting subscribers by latest first.']}], 'duration': 1779.219, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug22266670.jpg', 'highlights': ['Implementing a history page on the front end by selecting visited videos and ensuring uniqueness', 'Creating a minimalistic analytics dashboard on the backend side, including features such as displaying the latest uploaded video, number of views, and number of subscribers', 'The chapter covers the creation of video cards, including displaying video information such as likes, views, and titles, as well as an edit button for video updates', 'Select video views joined with videos uploaded by the current user and retrieve the count, which is a simple number', 'Implementing history functionality to display one video at a time with other information on the front-end side']}, {'end': 25462.289, 'segs': [{'end': 24129.858, 'src': 'embed', 'start': 24100.92, 'weight': 1, 'content': [{'end': 24109.385, 'text': 'Okay, select subscriber with the user, and this one will now make one select less.', 'start': 24100.92, 'duration': 8.465}, {'end': 24120.573, 'text': 'so if we open this database again and scroll down at the very bottom right here, we see that it selected both of the users with just single select.', 'start': 24109.385, 'duration': 11.188}, {'end': 24124.915, 'text': 'Okay, that is exactly what the with basically does.', 'start': 24121.073, 'duration': 3.842}, {'end': 24129.858, 'text': 'Okay, and this problem basically happens on the front-end side as well.', 'start': 24125.376, 'duration': 4.482}], 'summary': "The 'with' command selects both users at once, reducing selects by one and causing front-end issues.", 'duration': 28.938, 'max_score': 24100.92, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug24100920.jpg'}, {'end': 24187.106, 'src': 'embed', 'start': 24158.618, 'weight': 2, 'content': [{'end': 24166.885, 'text': 'when we select videos, we can specify right here select the video with its created by okay.', 'start': 24158.618, 'duration': 8.267}, {'end': 24173.854, 'text': 'And right now, if I reload the page, I see 15 queries instead of 21..', 'start': 24168.229, 'duration': 5.625}, {'end': 24180.02, 'text': 'And if the data grows, the application starts making more and more selects.', 'start': 24173.854, 'duration': 6.166}, {'end': 24182.202, 'text': 'And you need to pay attention to this.', 'start': 24180.52, 'duration': 1.682}, {'end': 24187.106, 'text': 'So it now selects every user information.', 'start': 24184.364, 'duration': 2.742}], 'summary': 'Application makes 15 queries instead of 21, potentially increasing with data growth.', 'duration': 28.488, 'max_score': 24158.618, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug24158618.jpg'}, {'end': 24323.973, 'src': 'embed', 'start': 24245.946, 'weight': 3, 'content': [{'end': 24248.067, 'text': 'it comes by default with the framework.', 'start': 24245.946, 'duration': 2.121}, {'end': 24251.61, 'text': "you don't need to install anything, which is, i think, very good.", 'start': 24248.067, 'duration': 3.543}, {'end': 24254.772, 'text': 'okay, so we are almost finished.', 'start': 24252.23, 'duration': 2.542}, {'end': 24263.637, 'text': "we have done a lot of things, so we have um, let's close all the bugs, okay, so we have implemented uploading of videos.", 'start': 24254.772, 'duration': 8.865}, {'end': 24266.999, 'text': 'we have implemented basic analytics right here.', 'start': 24263.637, 'duration': 3.362}, {'end': 24272.402, 'text': 'we can, of course, uh, have much more analytics, and i really encourage you again.', 'start': 24266.999, 'duration': 5.403}, {'end': 24279.03, 'text': 'you can find the link of the project on the github and you can find and clone and experiment with it.', 'start': 24272.402, 'duration': 6.628}, {'end': 24281.774, 'text': 'these are total views, total subscribers.', 'start': 24279.03, 'duration': 2.744}, {'end': 24283.015, 'text': 'we have a lot of information.', 'start': 24281.774, 'duration': 1.241}, {'end': 24290.926, 'text': 'basically, we have like general search, which searches by the by inside the tags as well.', 'start': 24283.015, 'duration': 7.911}, {'end': 24302.716, 'text': "inside the, In the description, we have this similar video section like and dislike, and that's basically it.", 'start': 24290.926, 'duration': 11.79}, {'end': 24306.54, 'text': 'And we have the history, which is also a very, very good feature.', 'start': 24302.736, 'duration': 3.804}, {'end': 24311.504, 'text': 'okay. last thing which i want to show you is caching.', 'start': 24307.1, 'duration': 4.404}, {'end': 24318.209, 'text': 'okay, how generally caching works if we go to the dashboard right here okay, this one.', 'start': 24311.504, 'duration': 6.705}, {'end': 24320.01, 'text': 'uh, 15 queries are made on this page.', 'start': 24318.209, 'duration': 1.801}, {'end': 24323.973, 'text': "okay, so let's just cache, for example, number of subscribers.", 'start': 24320.01, 'duration': 3.963}], 'summary': 'The project includes default features, video uploading, analytics, search, and caching functionality with 15 queries on the dashboard.', 'duration': 78.027, 'max_score': 24245.946, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug24245946.jpg'}, {'end': 24548.76, 'src': 'embed', 'start': 24494.854, 'weight': 0, 'content': [{'end': 24502.299, 'text': "so let's just reload the page and 15 queries are made and right now it put the value inside the cache.", 'start': 24494.854, 'duration': 7.445}, {'end': 24506.242, 'text': 'if we just reload it again, 13 queries are made right now.', 'start': 24502.299, 'duration': 3.943}, {'end': 24509.625, 'text': 'okay, so it just uses now.', 'start': 24506.542, 'duration': 3.083}, {'end': 24513.909, 'text': 'value from the cache okay, and that is very awesome.', 'start': 24509.625, 'duration': 4.284}, {'end': 24520.64, 'text': 'if you just want to like clear cache, you need to go to the backend runtime and this is the cache folder.', 'start': 24513.909, 'duration': 6.731}, {'end': 24522.161, 'text': 'okay, and we just.', 'start': 24520.64, 'duration': 1.521}, {'end': 24523.821, 'text': 'we can just delete the folder.', 'start': 24522.161, 'duration': 1.66}, {'end': 24528.743, 'text': 'okay and reload the page and 15 queries are made again.', 'start': 24523.821, 'duration': 4.922}, {'end': 24539.43, 'text': "one thing to consider as well on the dashboard if the user is new user and the user doesn't have any uploaded videos yet on the dashboard we will see error.", 'start': 24528.743, 'duration': 10.687}, {'end': 24545.036, 'text': 'something like this call to a member function, get thumbnail leak link on null.', 'start': 24539.43, 'duration': 5.606}, {'end': 24548.76, 'text': "that's simply because the latest video returns null.", 'start': 24545.036, 'duration': 3.724}], 'summary': 'Reloading the page reduced queries from 15 to 13. cache value is utilized. clearing cache led to 15 queries again.', 'duration': 53.906, 'max_score': 24494.854, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug24494854.jpg'}, {'end': 24922.206, 'src': 'embed', 'start': 24889.807, 'weight': 8, 'content': [{'end': 24902.525, 'text': "So let's go to the index page right down below, right here action index, and I'm going to specify right here pagination property and pagination has,", 'start': 24889.807, 'duration': 12.718}, {'end': 24907.836, 'text': 'for example, page size of five.', 'start': 24902.525, 'duration': 5.311}, {'end': 24911.118, 'text': "okay, let's display five videos in a page.", 'start': 24907.836, 'duration': 3.282}, {'end': 24915.501, 'text': 'reload the page and right here i see five videos and i see these links.', 'start': 24911.118, 'duration': 4.383}, {'end': 24916.202, 'text': 'one and two.', 'start': 24915.501, 'duration': 0.701}, {'end': 24922.206, 'text': "the links are not nice, of course, and that's because by default, the uh list view,", 'start': 24916.202, 'duration': 6.004}], 'summary': 'Implemented pagination with page size of 5, displaying 5 videos per page.', 'duration': 32.399, 'max_score': 24889.807, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug24889807.jpg'}, {'end': 25129.953, 'src': 'embed', 'start': 25102.641, 'weight': 9, 'content': [{'end': 25107.844, 'text': 'So this is a new model, which is just an extend or child class of the model.', 'start': 25102.641, 'duration': 5.203}, {'end': 25116.029, 'text': 'It has its rules and does the validation based on the rule, finds the model and sends an email.', 'start': 25108.184, 'duration': 7.845}, {'end': 25122.066, 'text': 'using eAppMailerCompose, as we have already covered.', 'start': 25117.862, 'duration': 4.204}, {'end': 25129.953, 'text': 'Then down below we have this ResetPassword method and down below we have VerifyEmail.', 'start': 25122.786, 'duration': 7.167}], 'summary': 'New model extends parent, validates based on rules, sends email.', 'duration': 27.312, 'max_score': 25102.641, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug25102641.jpg'}], 'start': 24045.889, 'title': 'Database query optimization and web development', 'summary': 'Discusses optimizing database queries, reducing front-end queries from 21 to 15 and implementing caching to reduce queries, along with backend and frontend overview and model extension with email sending. it also highlights github availability for experimentation and encourages further exploration of the provided code.', 'chapters': [{'end': 24215.063, 'start': 24045.889, 'title': 'Database query optimization', 'summary': 'Discusses optimizing database queries to reduce the number of select statements, resulting in a decrease from 21 to 15 queries on the front-end and a single select to retrieve all user information.', 'duration': 169.174, 'highlights': ['Optimizing database queries resulted in a decrease from 21 to 15 queries on the front-end, enhancing application performance.', "Using 'with' in database queries allowed selecting both users with just a single select, providing a significant optimization.", 'Selecting the video with its creator reduced the number of queries, resulting in improved efficiency.', "The use of 'with' in database queries streamlined the process, decreasing the number of selects and optimizing performance.", 'Selecting all user information with just one select improved efficiency and reduced redundant select statements.']}, {'end': 24494.854, 'start': 24215.303, 'title': 'Optimizing caching and analytics in web development', 'summary': 'Discusses optimizing caching, which reduces the number of queries by caching frequently accessed data, and implementing basic analytics with the framework. it also mentions the availability of project details on github for experimentation and the various features added to the application.', 'duration': 279.551, 'highlights': ['The feature of caching in web development can reduce the number of queries by storing frequently accessed data, such as the number of subscribers, in the cache, resulting in improved performance and reduced load on the database.', 'The implementation of basic analytics in the framework can provide valuable insights into user behavior and interaction with the application, enabling further enhancements based on the data collected.', 'The availability of project details on GitHub for experimentation and cloning allows for practical exploration and customization of the web development project, facilitating learning and innovation in web development.', 'The addition of various features to the application, including the history feature, asset bundles, mail, application timeline, user information, and dump information, enhances the functionality and usability of the web application.']}, {'end': 25102.341, 'start': 24494.854, 'title': 'Backend and frontend overview', 'summary': 'Details the caching process, backend modifications to handle null video errors, and frontend functionalities including video management, pagination, and user authentication.', 'duration': 607.487, 'highlights': ['The caching process reduces the number of queries from 15 to 13 after the initial page reload, demonstrating a 13.3% reduction in queries.', "Modifying the backend to handle null video errors by implementing an if statement within the card PHP, successfully resolves the issue of displaying 'You don't have uploaded videos yet' on the dashboard.", 'Implementation of pagination with a page size of 5 results in the display of five videos per page, enhancing user experience and navigation.', "The frontend functionalities including video management, pagination, and user authentication are detailed, providing insights into the system's capabilities and features."]}, {'end': 25462.289, 'start': 25102.641, 'title': 'Model extension and frontend configuration', 'summary': 'Covers extending a model class for validation and email sending, frontend layout configuration, and adding icons to the frontend. it also encourages further exploration of the provided code.', 'duration': 359.648, 'highlights': ['The chapter covers extending a model class for validation and email sending.', 'Frontend layout is configured to show or hide the sidebar based on page type.', 'Icons are added to the frontend using font awesome, with a note to apply the same in the backend.']}], 'duration': 1416.4, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/whuIf33v2Ug/pics/whuIf33v2Ug24045889.jpg', 'highlights': ['The caching process reduces queries from 15 to 13, demonstrating a 13.3% reduction.', "Using 'with' in database queries streamlined the process, optimizing performance.", 'Selecting all user information with just one select improved efficiency.', 'The feature of caching in web development reduces queries, improving performance.', 'The implementation of basic analytics provides valuable insights into user behavior.', 'The availability of project details on GitHub allows for practical exploration and customization.', 'The addition of various features enhances the functionality and usability of the web application.', 'Modifying the backend to handle null video errors successfully resolves the issue.', 'Implementation of pagination with a page size of 5 enhances user experience.', 'The chapter covers extending a model class for validation and email sending.']}], 'highlights': ['E2 framework offers speed, customizability, and support for databases, with GII generating applications in 5 seconds.', "Running 'php init' initializes the application, prompting mode selection.", "The process of installing Bootstrap 4 involves using Composer to require the 'esoft/e2-bootstrap' package and removing the old Bootstrap package using the integrated terminal.", 'The core components of a web application include eWebRequest, eWebResponse, Log, View, Formatter, Internalization, and URL manager.', "Changed database table name to singular form, created 'video' table", 'The process involves specifying the name of the input type file, dumping the file, and reloading the page to view the uploaded file, demonstrating the successful file upload process.', 'URL manager improves video access and functionality, crucial for page availability', 'Default values like created at, updated at, and created by are assigned when creating a video', 'Implementing sorting and pagination for grid view, including sorting by createdAt and applying pagination', 'Successfully implemented video deletion, removing six video items from the file system', "Implementing access control for 'like' and 'dislike' actions, allowing only authorized users, and specifying rules to restrict access based on user role.", 'The chapter emphasizes the automatic redirection to the login page for unauthorized requests, even when made through AJAX, highlighting the time-saving nature of this default framework behavior.', 'Successfully creating a subscriber table with specified fields and applying the migration using eFramework.', 'Implemented video upload and publishing for Python, JavaScript, and data structures on FreeCodeCamp, totaling in three published videos.', 'The caching process reduces queries from 15 to 13, demonstrating a 13.3% reduction.']}