Laravel:解释基本概念。 第二部分:练习

大家好! 我们期待“ Framework Laravel”课程的开始,继续制作一系列版权出版物。 在上一篇文章中,我们研究了Laravel的理论基础。 但是,任何框架的理论都可以研究很长时间,并且在您实际编写任何东西之前都不了解。



因此,让我们编写一个应用程序,每个用户都可以在其中登录,创建新相册并在那里上传照片。 如果您还不知道MVC是什么,请阅读此书 ,很快您将不得不在实践中使用它

这类指南首先介绍了如何设置环境等。 问题是在每个平台上它都是不同的,但是我希望这篇文章对每个人都有趣。 我只提供必要链接,您将尝试自己安装和配置它。

因此,我们需要:



作曲家 对于其中的那些人,Composer是PHP的软件包管理器(是的,例如JavaScript的npm)。 您可以在此处下载。

Laravel本人。 这里有一些最受欢迎的选项:Homestead和Valet(实际上还有许多其他选项)。 但是,后者仅适用于Mac OS。 从技术上讲,只要符合这些要求,阅读器就可以使用任何喜欢的组件。

还有一个细微的细节,但是我们还需要Node.js来安装npm软件包。

运行命令: composer global require laravel/installer来安装Laravel。

请记住,将$Home/.composer/vendor/bin (或OS上的等效$Home/.composer/vendor/bin )放在PATH变量中,以便Laravel命令在您的系统上可用。

因此,一个好的项目始于一个可以理解的TOR。 让我们尝试为我们的简单应用制定基本要求:



用户可以将自己创建的相册中的照片上传到网站。 他可以注册并可以登录。 该数据库是MySQL。 用于简化布局过程的框架是Bootstrap,它是最常见的布局框架。

创建后立即执行的第一个操作是连接数据库。 如果仍然不了解如何安装和运行数据库,请使用Evil Corporation的现成桌面解决方案: 此处此处 。 一开始就足够了。

一切准备就绪。 我们转到您最喜欢的目录,并从以下项目开始

 laravel new gallery 

接下来,您需要连接我们的数据库。 为此,请通过MySQL分支并创建一个新的图库数据库(不要忘记将Character Set设置为utf-8,将ollat​​ion设置为utf_general_ci以避免俄语问题)。



接下来,转到.ENV文件并配置类似的连接,记住将变量更改为您的用户名和密码:

 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=gallery DB_USERNAME=pavel DB_PASSWORD= 

之后,我们将能够迁移我们的数据库。

 php artisan migrate 

如果您在.ENV正确配置了连接,那么一切都会为您工作。

按照我们在t / z上达成的协议,我们将有一个授权,注册过程,并且用户将有机会在其中创建相册并上传照片。 为了实现所有这些,我们需要数据库中适当的表。

创建相册

那么后端从哪里开始呢? 通过在我们的数据库中创建表。 终端中的此命令将为我们提供一个迁移到数据库的机会:

 php artisan make:migration CreateAlbumsTable 

因此,我们需要确定表中应包含哪些列。 由于上一次迁移,必须在您创建的文件中完成此操作。 它位于项目的gallery/database/migrations文件夹中,其名称与创建时间相关联。 必须对其进行如下编辑:

 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateAlbumsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('albums', function(Blueprint $table) { $table->increments('id')->unsigned(); $table->string('name'); //   $table->text('description'); //    $table->string('cover_image'); //   $table->timestamps(); //  .   ,     }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('albums'); } } 

别忘了做

  php artisan migrate 

现在,MySQL Branch中数据库的选项卡应采用以下形式:



因此,我们创建了数据库,现在我们需要将数据库与Eloquen模型连接,该模型将与数据库交互。

创建专辑模型




现在,我们需要创建一个雄辩的ORM模型。 如果您不了解我们如何快速地从一个迁移到另一个,则应阅读此书。 我们将使用相同的Artisan助手来生成模型模板:


PHP的工匠使:模型专辑

接下来,我们进入gallery/app/Album.php并对其进行编辑:

 <?php namespace App; use Illuminate\Database\Eloquent\Model; class Album extends Model { protected $table = 'albums'; protected $fillable = array('name','description','cover_image'); public function Photos(){ return $this->hasMany('App\Image'); } } 

图片

哇! 我们的相册模型已经准备就绪,现在您可以制作我们的图像了。 这里将再次重复该过程:

 php artisan make:migration CreateImagesTable 

我们将编辑我们的迁移:

 <?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateImagesTable extends Migration { public function up() { Schema::create('images', function (Blueprint $table) { $table->increments('id'); $table->integer('album_id')->unsigned(); $table->string('image'); $table->string('description'); $table->foreign('album_id')->references('id')->on('albums')->onDelete('CASCADE')->onUpdate('CASCADE'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('images'); } } 

再一次,我们进行迁移:

 php artisan migrate 

希望您的迁移成功! 但是,我们需要解释一件事,而在评论中写下来太长了:我们使用foreign键将两个表AlbumsImages联接在一起 。 每个相册都有自己的图像,如果您要删除某种相册,则可能会认为照片也将被删除。

影像模型

现在是时候创建一个可以使用images表的模型了。 我希望您已经猜到该怎么办:

 php artisan make:model Image 

模板已创建,请转到gallery/app/Image.php进行编辑。
在这里,一切也应该清楚:

 class Image extends Model { protected $table = 'images'; // ,      protected $fillable = array('album_id','description','image'); // } 

我们的图像模型已准备就绪。 现在我们需要一个控制器来在数据库中创建相册。

专辑制作

为了在相册中保存,显示和删除,我们的控制器中需要一些功能。 但是首先,您需要控制器本身:

 php artisan make:controller AlbumsController 

转到gallery/app/Http/Controllers/AlbumsController.php

 <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\MessageBag; use Validator; use App\Album; class AlbumsController extends Controller { public function getList() //   { $albums = Album::with('Photos')->get(); return view('index')->with('albums',$albums); } public function getAlbum($id) { $album = Album::with('Photos')->find($id); $albums = Album::with('Photos')->get(); return view('album', ['album'=>$album, 'albums'=>$albums]); } public function getForm() { return view('createalbum'); //   } public function postCreate(Request $request) { $rules = ['name' => 'required', 'cover_image'=>'required|image']; //        $input = ['name' => null]; //      $validator = Validator::make($request->all(), $rules); if($validator->fails()){ return redirect()->route('create_album_form')->withErrors($validator)->withInput(); } $file = $request->file('cover_image'); $random_name = str_random(8); $destinationPath = 'albums/'; $extension = $file->getClientOriginalExtension(); $filename=$random_name.'_cover.'.$extension; $uploadSuccess = $request->file('cover_image')->move($destinationPath, $filename); $album = Album::create(array( 'name' => $request->get('name'), 'description' => $request->get('description'), 'cover_image' => $filename, )); return redirect()->route('show_album',['id'=>$album->id]); } public function getDelete($id) //    { $album = Album::find($id); $album->delete(); return Redirect::route('index'); } } 

然后,我们必须重新定义路径。 对于那些不知道的人,路由是建立在浏览器中显示给用户的路径以及我们的应用程序应执行的操作。 我们转到web.php文件:

 <?php //  Route::get('/', array('as' => 'index','uses' => 'AlbumsController@getList')); //      Route::get('/createalbum', array('as' => 'create_album_form','uses' => 'AlbumsController@getForm')); //    Route::post('/createalbum', array('as' => 'create_album','uses' => 'AlbumsController@postCreate')); //   Route::get('/deletealbum/{id}', array('as' => 'delete_album','uses' => 'AlbumsController@getDelete')); //   Route::get('/album/{id}', array('as' => 'show_album','uses' => 'AlbumsController@getAlbum')); //   //       Route::get('/addimage/{id}', array('as' => 'add_image','uses' => 'ImageController@getForm')); //    Route::post('/addimage', array('as' => 'add_image_to_album','uses' => 'ImageController@postAdd')); //     Route::get('/deleteimage/{id}', array('as' => 'delete_image','uses' => 'ImageController@getDelete')); // Route::post('/moveimage', array('as' => 'move_image', 'uses' => 'ImageController@postMove')); 

哇 为了确保我们的应用程序正常工作,在设置视图之前,我们需要确保在gallery/config/app.php末尾具有必要类的别名的必要链接。 这些只是技术设置:

 'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 'Bus' => Illuminate\Support\Facades\Bus::class, 'Cache' => Illuminate\Support\Facades\Cache::class, 'Config' => Illuminate\Support\Facades\Config::class, 'Cookie' => Illuminate\Support\Facades\Cookie::class, 'Crypt' => Illuminate\Support\Facades\Crypt::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Notification' => Illuminate\Support\Facades\Notification::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, 'Redis' => Illuminate\Support\Facades\Redis::class, 'Request' => Illuminate\Support\Facades\Request::class, 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, 'Schema' => Illuminate\Support\Facades\Schema::class, 'Session' => Illuminate\Support\Facades\Session::class, 'Storage' => Illuminate\Support\Facades\Storage::class, 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, 'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class, ], //   FORM     ) 
太好了! 现在我们需要定义我们的想法! 转到gallery/resources/views文件夹。 您可以删除welcome.blade.php ,也可以离开,没关系。 创建index.blade.phpincludes子文件夹以添加view的重复部分。 因此,我们的index.blade.php应该采用以下形式:

 @include('includes.header') <body> @include('includes.nav') <div class="container"> <div class="starter-template"> <div class="row"> @foreach($albums as $album) <div class="col-lg-3"> <div class="thumbnail" style="min-height: 514px;"> <img alt="{{$album->name}}" src="/albums/{{$album->cover_image}}"> <div class="caption"> <h3>{{$album->name}}</h3> <p>{{$album->description}}</p> <p>{{count($album->Photos)}} image(s).</p> <p>Created date: {{ date("d FY",strtotime($album->created_at)) }} at {{date("g:ha",strtotime($album->created_at)) }}</p> <p><a href="{{route('show_album', ['id'=>$album->id])}}" class="btn btn-big btn-default"> </a></p> </div> </div> </div> @endforeach </div> </div><!-- /.container --> </div> </body> </html> 

内容includes/header.blade.php

 <!doctype html> <html lang="ru"> <head> <meta charset="UTF-8"> <title> </title> <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script> <style> body { padding-top: 50px; } .starter-template { padding: 40px 15px; text-align: center; } </style> </head> 
内容includes/nav.blade.php

 <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".nav-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> </a> <div class="nav-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="{{URL::route('create_album_form')}}">  </a></li> </ul> </div><!--/.nav-collapse --> </div> </div> 

今天就这些! 当然,这只是我们应用程序的第一部分。 谢谢大家的关注,在下一部分中,我们将补充我们的view并讨论图像验证的问题。

有用的链接:

俄语文档
比文档更好的英文有用指南,介绍了Blade模板的继承和扩展如何工作
许多有用的信息和创建应用程序的实际示例

Source: https://habr.com/ru/post/zh-CN471776/


All Articles