Laravelの勉強でSNS「ねこぴく」というサイトを作ってみました
ブランクを克服するために、最近トレンドなPHPのフレームワークのLaravelを使い、SNS「ねこぴく」というサイトを作ってみました
サイト
概要
猫の写真を他の人と共有するWEBサイトです。
機能は以下になります。
・お気に入り機能(いいね機能)
・マイページでアップロードした写真を管理(編集、削除)
・写真にコメントできる機能
・タグ検索機能(複数のタグを組み合わせることができるor検索)
・ログイン、ログアウト、登録
・スマートフォン対応(Androidで確認)
Laravelで、テキスト内のhttpリンクの変換方法
Laravelにて、プロフィールなどの説明に、httpのリンクを途中で入れてあった場合、ちゃんとリンクされるようにしたい
間違った方法
Controllerで
<?php ~略~ 'introduction' => $user->introduction
blade.phpで
<p> {{ $introduction }} </p>
これだと、このようになってしまいます。
解決方法
まずは、httpにaタグをつけます。
app/Libsフォルダに、PlanetextToUrl.phpを追加して以下の内容にします。
<?php namespace App\Libs; class PlanetextToUrl { public static function convertLink($plane_text) { //URL抽出の正規表現 $pattern = '/https?:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+/'; //該当する文字列に処理 $convert_text = preg_replace_callback($pattern,function ($matches) { return '<a href="'.$matches[0].'">'.$matches[0].'</a>'; },htmlspecialchars($plane_text)); return $convert_text; } }
Controller内
<?php //プロフィール紹介を文字列の中にurlがあったらコンバートするようにします。 $introduction = PlanetextToUrl::convertLink($user->introduction); //出力します。 'introduction' => $introduction
blade.php内では、以下のように改行させつつ、エスケープさせないように{!! $変数 !!}と記述します。
※nl2brで囲って、元のテキストと同じように、改行させます。
<p> {!! nl2br($introduction) !!} </p>
これで、うまくいきました!
お借りした素材サイト
LaravelのEloquentで集計関数Count()などを使うとき
LaravelのEloquentで集計関数を使いたい
データの準備
例えば、Tagsテーブルと、タグと写真を紐づける中間テーブルのTagmapsテーブルがあるとします。
・Tags
・Tagmaps
これを使って、タグ数表示を作りたいとします。
その場合は、タグの数を集計する必要があります。
そこでLaravelのEloquentで集計しようとしましたが、
<?php //~略~ $tag_count_list = \DB::table('tagmaps') ->join('tags', 'tagmaps.tag_id', '=', 'tags.id') ->select('count(*), tags.name') ->groupBy('tag_id') ->orderBy('count(*)', 'desc') ->get();
select('count(*), ...')でエラー
ここで、上のように、Laravelで、集計関数をそのままSelectに放り込んでしまうとエラーが出ます。
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'count(*), tags.name' in 'field list' (SQL: select `count(*), tag ~略~
解決策 DB::raw('count(*) as tag_count, ~')
これを解決するには、
<?php //~略~ ->select('count(*), tags.name')
を下のように変えます。
<?php //~略~ ->select(DB::raw('count(*) as tag_count, tags.name'))
<?php //~略~ $tag_count_list = DB::table('tagmaps') ->join('tags', 'tagmaps.tag_id', '=', 'tags.id') ->select(DB::raw('count(*) as tag_count, tags.name')) ->groupBy('tagmaps.tag_id') ->orderBy('tag_count', 'desc') ->get();
bladeファイルでは以下のように{{ $tag_count->tag_count }}で数が取得できるようになりました。
@foreach($tag_count_list as $tag_count) <a href="javascript:void(0)" onclick="this.parentNode.submit()" class="btn-tag m-1"> {{ $tag_count->name }} ({{ $tag_count->tag_count }}) </a> @endforeach
参考サイト
Laravelでミドルウェアでモバイル判定処理をして、全てのViewでisMobile変数を呼べるようにする
Laravelでミドルウェアでモバイル判定処理をして、全てのViewでisMobile変数を呼べるようにする
モバイル判定方法1.ヤバイパターン
まずは、ヤバイパターンとして、
モバイル判定処理を1つ1つコントローラに書いて、ビューに反映する場合
以下をすべてのコントローラーに書くのはなかなかヤバイですね…
<?php //~略~ $agent = app('agent'); return view('index', [ 'isMobile' => $agent->isMobile(), ]);
モバイル判定方法2.楽なパターン
そこで、View::share で全てのビューで使うグローバル変数を定義して、
さらに、その処理をBeforeミドルウェアを使って、リクエストがきたら行う共通処理にしておきます。
その前に、composerからモバイルのエージェントの判定できるライブラリ
github.com
をインストールしておきます。
エージェント判定ライブラリをインストール
composer require jenssegers/agent
config/app.php
<?php 'providers' => [ Jenssegers\Agent\AgentServiceProvider::class, //追加 ], 'aliases' => [ 'Agent' => Jenssegers\Agent\Facades\Agent::class, //追加 ],
次にミドルウェアを作っていきます。
Middleware の作成
php artisan make:Middleware GetIsMobile
Kernel.phpにMiddleware を追加
全てのリクエストで処理をするため、$middlewareプロパティに追加します。
App\Http\Kernel.php
<?php protected $middleware = [ \App\Http\Middleware\CheckForMaintenanceMode::class, ~略~ \App\Http\Middleware\GetIsMobile::class, //<-追加 ];
全てのHTTPリクエスト時にモバイル判定処理を走らせる準備ができました。
MiddlewareにView::shareでグローバル変数を定義していきます。
View::shareでグローバル変数
App/Http/Middleware/GetIsMobile.php
<?php namespace App\Http\Middleware; use Closure; use Agent; use Illuminate\Http\Request; use Illuminate\Support\Facades\View; //View::share用 class GetIsMobile { public function handle($request, Closure $next) { $agent = app('agent'); View::share(['isMobile' => $agent->isMobile()]); return $next($request); } }
これで、どのページを開いてもblade内で
{{ $isMobile }}変数が使えるようになりました。
オシャレなブランドロゴを作れるLOGASTERを使ってみた!
Laravelの勉強で作ったサイト用に、ロゴを作ってみました。
こんな感じのロゴが作れますよ!
所要時間は5分かからなかったです。すごいサービスです。
ダウンロードして、Photoshopで色調を変えてみました。
なかなかいい感じに仕上がりました!
素晴らしいです!
LaravelでGROUP BY clause and contains nonaggregated columnと出たとき
問題のSQL
<?php $photos = Photo:: join ~省略~ ->select('photos.*') ->groupBy('photos.id')
と、した時に
GROUP BY clause and contains nonaggregated column
は出現しました。
原因
これはMySQL5.7からONLY_FULL_GROUP_BYがデフォルトで有効になっているためです。
qiita.com
元記事より引用
GROUP BYを使っていると、非集約カラムをSELECTで参照できなくなります。
つまりGROUP BY使っている場合はSELECTするものを全部GROUP BYに書け、とのことです。
そこで、/etc/my.cnfを編集していきたいところですが、
エラーが消えないなどハマってしまったためメモします。
解決
[mysqld]直下にsql_modeを書く!(重要)
手順
my.cnfの場所を探します
sudo find / -type f -ls | fgrep my.cnf 4 -rw-r--r-- 1 root root 1352 Jun 26 20:18 /etc/my.cnf
と出たので、/etc/my.cnfにありますね!
sudo vi /etc/my.cnf
[mysqld] sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION # # Remove leading # and set to the amount of RAM for the most important data
my.cnfの一番下に書いてもなぜか反映されなかった。
保存して、mysqlサーバーを再起動する。
sudo systemctl restart mysqld
mysqlコンソールにて、ONLY_FULL_GROUP_BYが消えていることを確認します。
mysql> SELECT @@global.sql_mode; +----------------------------------------------------------------------------------------------------+ | @@global.sql_mode | +----------------------------------------------------------------------------------------------------+ | STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | +----------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
ONLY_FULL_GROUP_BYが消えていますので、WEBサイトにアクセスします。
すると、エラーGROUP BY clause and contains nonaggregated columnが消えました。
Laravelプロジェクトを本番サーバーで公開する時、Permission deniedでハマったら
The stream or file "/var/www/laravel/nekopic_website/storage/logs/laravel-2019-06-30.log" could not be opened: failed to open stream: Permission denied
結論
権限の設定が必要
WEBサーバーを実行するapacheユーザーの権限が
logにないよ、ということでした。
さらに、Laravelのサイトにもある通り、
今後のためにstorageディレクトリと、bootstrap/cacheディレクトリにも権限を与えておく必要があります。
権限の設定法
こちらを参考に自分用にアレンジしました。
参考サイト
手順
まずはユーザーについてですが、以下のユーザーがいます
・hogeuser(puttyなどでログインしているユーザー)
sftpなどでファイル操作ができる
・apache
webサーバーの実行ユーザー
Laravel用のユーザーグループを作成
sudo groupadd laravel
今作ったlaravelグループに、hogeuserとapacheを追加
sudo gpasswd -a hogeuser laravel sudo gpasswd -a apache laravel
laravelプロジェクトに移動
cd /var/www/laravel/nekopic_website
パーミッションを、ディレクトリ:755、ファイル:644にする
sudo find ./ -type d -exec chmod 755 {} \; sudo find ./ -type f -exec chmod 644 {} \;
所有グループを変更(エラーが修正される)
sudo chown -R :laravel ./storage sudo chown -R :laravel ./bootstrap/cache
もう一度、storageとbootstrap/cache内のパーミッションを
ディレクトリ:755、ファイル:644にする
sudo find ./storage -type d -exec chmod 775 {} \; sudo find ./storage -type f -exec chmod 664 {} \; sudo find ./bootstrap/cache -type d -exec chmod 775 {} \; sudo find ./bootstrap/cache -type f -exec chmod 664 {} \;
SGIDを設定することにより、今後、storage内と、bootstrap/cache内で作成されたファイルやディレクトリの
所有グループはlaravelになるようにする。(logsのファイルは日ごとに作成されるため)
sudo find ./storage -type d -exec chmod g+s {} \; sudo find ./bootstrap/cache -type d -exec chmod g+s {} \;
ACLのデフォルト設定で、
今後、storageとbootstrap/cache下にファイルやディレクトリが作られたら、
ディレクトリ:775、ファイル:664になる
sudo setfacl -R -d -m g::rwx ./storage sudo setfacl -R -d -m g::rwx ./bootstrap/cache
再起動する
sudo shutdown -r now