I can't see where I'm going wrong with my code. I believe I have my relationships/models set up correctly but my bannerclicks table will not insert a row, and worse it seems to break the banner redirect.
MIGRATION
const TBL_BANNER_CLICKS = 'banner_clicks';
public function up()
{
// Create the clicks table
Schema::create(self::TBL_BANNER_CLICKS, function($table){
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('banner_id')->unsigned();
$table->string('ip_address', 45);
$table->integer('clicks')->unsigned()->default(0);
$table->integer('created_at');
$table->foreign('banner_id')
->references('id')->on('banners')
->onUpdate('cascade')
->onDelete('cascade')
;
});
}
MODELS
Banner.php
public function bannerclicks()
{
return $this->hasMany('BannerClick');
}
BannerClick.php
protected $table = 'banner_clicks';
public function banner()
{
return $this->belongsTo('Banner');
}
BannerController.php
public function redirect($id)
{
try {
// Original (want to keep)
$banner = Banner::where('id', $id)
->where('active', 1)
->firstOrFail();
$banner->clicks++;
$banner->save();
// new banner_clicks table
$bannerclick = new BannerClick($id);
$bannerclick->banner_id = $id;
$bannerclick->clicks = 1;
$bannerclick->bannerclicks()->save($bannerclick);
return Redirect::to($banner->url);
} catch (Exception $ex) {
return Redirect::to('/');
}
}
HTML
<a href="{{URL::action('BannerController#redirect', $banner->id)}}" target="_blank" rel="nofollow">
<img src="{{$banner->image}}" class="img-responsive" alt="{{$banner->title}}"></a>
I think you should be saving your relation with something like this:
public function redirect($id)
{
try {
// Original (want to keep)
$banner = Banner::where('id', $id)
->where('active', 1)
->firstOrFail();
$banner->clicks++;
$banner->save();
// new banner_clicks table
$bannerclick = new BannerClick(array('clicks' => 1));
$banner->bannerclicks()->save($bannerclick);
return Redirect::to($banner->url);
} catch (Exception $ex) {
return Redirect::to('/');
}
}
See here: http://laravel.com/docs/eloquent#inserting-related-models
Or just do this:
$banner = Banner::where('id', $id)
->where('active', 1)
->firstOrFail();
$banner->clicks++;
$banner->save();
// new banner_clicks table
$bannerclick = new BannerClick;
$bannerclick->clicks = 1;
$bannerclick->banner_id= $banner->id;
$bannerclick->save();
Related
Laravel 8.0 CACHE_DRIVER=file.
Stored in cache 'posts' and 'post_detail'.
I'm using full url for save in cache unique page of pagination posts.
public function __contructor()
{
$this->full_url = request()->fullUrl();
}
// ALL POSTS WITH PAGINATION
public function posts()
{
if (Cache::has("posts_".$this->full_url)) {
$posts = Cache::get("posts_".$this->full_url);
} else {
$posts = Cache::rememberForever($this->full_url, function() {
return Post::paginate(15);
});
}
}
// DETAIL POST
public function post_detail($slug)
{
if (Cache::has("post_detail_".$this->full_url)) {
$post_detail = Cache::get("post_detail_".$this->full_url);
} else {
$post_detail = Cache::rememberForever("post_detail_".$this->full_url, function() {
return Post::where('slug', $slug)->first();
});
}
}
I can forget cache only for 'post_detail' but I have no idea how to remove the cache for all posts that include the key 'posts_'
// UPDATE POST
public function update()
{
...
$post->update();
$full_url = $request->getSchemeAndHttpHost()."/".$post->post_categories->category_slug . "/" .$post->slug);
Cache::forget("post_detail_".$full_url.""); // OK
Cache::forget("posts_*"); // forget al posts contains 'posts_' key.
}
thanks
I'm trying to save an item I created which has options that belong to it, in my case it's a question that has options like the answer options. The question is saved into it's own table, and the options are in a separate table.
This is the table structure
Schema::create('survey_questions', function (Blueprint $table) {
$table->increments('id');
$table->string('question');
$table->integer('survey_section_id')->unsigned();
$table->integer('response_type_id')->unsigned();
$table->boolean('optional');
$table->timestamps();
$table->foreign('survey_section_id')->references('id')->on('survey_sections');
$table->foreign('response_type_id')->references('id')->on('response_types');
});
Schema::create('survey_question_options', function (Blueprint $table) {
$table->increments('id');
$table->integer('survey_question_id')->unsigned();
$table->string('option');
$table->timestamps();
$table->foreign('survey_question_id')->references('id')->on('survey_questions');
});
The relationships go like this
SurveyQuestion Model
public function surveyQuestionOption()
{
return $this->hasMany(SurveyQuestionOption::class);
}
SurveyQuestionOption Model
public function surveyQuestion()
{
return $this->belongsTo(SurveyQuestion::class);
}
This is my current store method in the controller
public function store(Request $request)
{
DB::beginTransaction();
$preg = new SurveyQuestion;
$preg->question = $request->question;
$preg->survey_section_id = $request->survey_section_id;
$preg->response_type_id = $request->response_type_id;
$preg->optional = $request->optional;
$preg->save();
if ($request->has('questionOptions')) {
$questionOptions = [];
$survey_question_id = $preg->id;
foreach ($request->get('questionOptions') as $item) {
$option = $item['option'];
if (isset($option)) {
$questionOptions[] = [
"survey_question_id" => $survey_question_id,
"option" => $option,
];
}
}
if (count($questionOptions)) {
SurveyQuestionOption::insert($questionOptions);
}
}
$preg->save();
DB::commit();
return back();
}
This is my update
public function update(Request $request, $id)
{
DB::beginTransaction();
$preg = SurveyQuestion::findOrFail($id);
$preg->question = $request->question;
$preg->survey_section_id = $request->survey_section_id;
$preg->response_type_id = $request->response_type_id;
$preg->optional = $request->optional;
$preg->save();
$ids = [];
if (!empty($request->get('questionOptions'))) {
foreach ($request->get('questionOptions') as $item) {
$opt = SurveyQuestionOption::where('survey_question_id', $preg->id)->first();
if (empty($opt)) {
$opt = new SurveyQuestionOption();
$opt->survey_question_id = $preg->id;
}
$opt->option = $item['option'];
$opt->save();
}
}
if (count($ids) > 0) {
SurveyQuestionOption::whereNotIn('id', $ids)->delete();
}
$preg->save();
DB::commit();
return back();
}
When I try to save on the vue it doesn't give me any errors but it also doesn't save into the survey_question_option table. I'm not entirely sure if my error is on the controller side or the vue side.
The two tables tbl_product_manager and tbl_tags with many to many relations. I used eloquent to to make a relations between the corresponding models. I am able to to insert the data in these two table but the problem is the pivot table is not updated correspondingly.
Controller.php:
public function addProduct()
{
$rules = array('product_name' => 'required',
'product_url' => 'required');
$validator = Validator::make(Input::all(), $rules);
if($validator->fails()){
Session::flash('class', 'alert alert-error');
Session::flash('message', 'Some fields are missing');
return View::make('admin.product.add');
}
else {
$productName = Input::get('product_name');
$productUrl = Input::get('product_url');
$productUrl = preg_replace('/[^A-Za-z0-9\-]/', '', $productUrl);
$productExist = ProductManagementModel::checkExist($productUrl);
if( count($productExist)!=0) {
$message = 'product <b>'.$productName.'</b> with url <b>'.$productUrl.'</b> is already exist';
Session::flash('class', 'alert alert-error');
Session::flash('message', $message);
return View::make('admin.product.add');
}
else {
$imageFile = Input::file('userfile');
$destinationPath = 'uploads/products/';
$rEFileTypes = "/^\.(jpg|jpeg|gif|png){1}$/i";
$maximum_filesize = 1 * 1024 * 1024;
if($imageFile) {
$filename = $imageFile->getClientOriginalName();
$extension = strrchr($filename, '.');
$size = $imageFile->getSize();
$new_image_name = "products" . "_" . time();
if ($size <= $maximum_filesize && preg_match($rEFileTypes, $extension)) {
$attachment = $imageFile->move($destinationPath, $new_image_name.$extension);
} else if (preg_match($rEFileTypes, $extension) == false) {
Session::flash('class', 'alert alert-error');
Session::flash('message', 'Warning : Invalid Image File!');
return View::make('admin.product_management.add');
} else if ($size > $maximum_filesize) {
Session::flash('class', 'alert alert-error');
Session::flash('message', "Warning : The size of the image shouldn't be more than 1MB!");
return View::make('admin.product_management.add');
}
}
$logo = isset($attachment) ? $new_image_name . $extension : NULL;
$objectProduct = new ProductManagementModel;
$objectProduct->product_name = Input::get('product_name');
$objectProduct->product_url = $productUrl;
$objectProduct->category_id = Input::get('category_id');
$objectProduct->product_cost = Input::get('product_cost');
$objectProduct->product_short_description = Input::get('product_short_description');
$objectProduct->product_description = Input::get('product_description');
$objectProduct->is_active = Input::get('is_active');
$objectProduct->created_at = Auth::user()->id;
$objectProduct->updated_at = Auth::user()->id;
if($logo != '')
{
$objectProduct->product_attachment = $logo;
}
$objectTags = new TagModel;
$objectTags->size_id = Input::get('size_id');
$objectTags->brand_id = Input::get('brand_id');
$objectTags->color_id = Input::get('color_id');
$objectTags->food_id = Input::get('food_id');
$objectTags->save();
//$tag = new TagModel::all();
$objectProduct->save();
if(isset($request->tags)) {
$post->Tags()->sync($request->tags, false);
}
if($objectProduct->id) {
Session::flash('class', 'alert alert-success');
Session::flash('message', 'Product successfully added');
return View::make('admin.product_management.add');
} else {
Session::flash('class', 'alert alert-error');
Session::flash('message', 'Something error');
return View::make('admin.product_management.add');
}
}
}
}
ProductManagementModel.php
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class ProductManagementModel extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'product_manager';
public function Tags(){
return $this->belongsToMany('TagModel', 'product_tag', 'product_id', 'tag_id');
}
public function Categories(){
return $this->hasOne('CategoriesModel', 'id');
}
public static function getAllProducts(){
return $products = ProductManagementModel::with('categories','tags')->get();
}
public static function checkExist($url)
{
return $products = DB::table('product_manager')
->where('is_deleted', 0)
->where('product_url', $url)
->first();
}
}
TagModel.php
<?php
use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
class TagModel extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'tag';
public function ProductManagents() {
return $this->belongsToMany('ProductManagentModel');
}
public function Color(){
return $this->hasOne('ColorModel', 'color_id');
}
public function Brand() {
return $this->hasOne('BrandproModel','brand_id');
}
public function size() {
return $this->hasOne('SizeModel','size_id');
}
public function food() {
return $this->hasOne('FoodModel','food_id');
}
}
During my research i found that using sync function will be appropriate to updated the pivot table. But I failed to use it.
I am expecting to resolve this problem or something new way to find out the solution.
Thanks in advance.
Look at attach, detach or synch method :
https://laravel.com/docs/5.5/eloquent-relationships#updating-many-to-many-relationships
Note it's more easily if you respect the eloquent naming convention
http://www.rappasoft.com/articles/laravel-eloquent-naming-convention-guide/
I currently have a relationship between checklistItem and actions as followed:
public function action()
{
return $this->belongsTo(Action::class, 'action_id', 'id');
}
public function checklistItem()
{
return $this->hasOne(ChecklistItem::class, 'action_id', 'id');
}
I currently made a method, when saving an action, the checklistItem status should also change depending on what was chosen:
public static function saveFromRequest(Request $request)
{
if (($action = parent::saveFromRequest($request)) !== null){
if (!is_null($action->checklistItem)) {
$action->checklistItem->value->status = $action->switchStatusChecklist($action);
//Need to update or save this specific checklistItem
$action->checklistItem->save();
}
}
return $action;
}
function switchStatusChecklist($action)
{
switch($action->status) {
case 'closed':
$status = 'checked';
break;
case 'canceled':
$status = 'notapplicable';
break;
default:
$status = 'open';
break;
}
return $status;
}
Problem:
My checklistitem does not get updated.
I use a trait for generate uuid on my model. It's work because, in my database the uuid value is not empty. But the current instance of my model don't have the new value.
this is the trait :
trait UuidModel
{
public static function bootUuidModel()
{
static::creating(function ($model) {
// Don't let people provide their own UUIDs, we will generate a proper one.
$model->uuid = Uuid::generate(4);
return true;
});
static::saving(function ($model) {
// What's that, trying to change the UUID huh? Nope, not gonna happen.
$original_uuid = $model->getOriginal('uuid');
if ($original_uuid !== $model->uuid) {
$model->uuid = $original_uuid;
}
return true;
});
}
public function scopeUuid($query, $uuid, $first = true)
{
if (!is_string($uuid) || (preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $uuid) !== 1)) {
throw (new ModelNotFoundException)->setModel(get_class($this));
}
$search = $query->where('uuid', $uuid);
return $first ? $search->firstOrFail() : $search;
}
public function scopeIdOrUuId($query, $id_or_uuid, $first = true)
{
if (!is_string($id_or_uuid) && !is_numeric($id_or_uuid)) {
throw (new ModelNotFoundException)->setModel(get_class($this));
}
if (preg_match('/^([0-9]+|[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$/', $id_or_uuid) !== 1) {
throw (new ModelNotFoundException)->setModel(get_class($this));
}
$search = $query->where(function ($query) use ($id_or_uuid) {
$query->where('id', $id_or_uuid)
->orWhere('uuid', $id_or_uuid);
});
return $first ? $search->firstOrFail() : $search;
}
}
This is my model :
class Image extends BaseModel
{
use UuidModel;
protected $table = 'images';
public $incrementing = false;
public $timestamps = true;
protected $guarded = array('id', 'timestamps', 'path');
protected $visible = array('timestamps', 'uuid');
protected $hidden = array('id', 'path');
public function Item()
{
return $this->belongsTo('App\Models\Item', 'id', 'item_id');
}
}
This is my Controller :
class ImageController extends Controller
{
...
public function store(CreateImageRequest $request, $itemSlug)
{
$item = $this->getItem($itemSlug);
$image = new Image();
$image->path = "";
$image = $item->Images()->save($image);
return Response::json($image->uuid, 201);
}
...
}
And the response is always : {} but the uuid is not empty in my database.
UPDATE
This test works :
public function store(CreateImageRequest $request, $collectionSlug, $itemSlug)
{
$item = $this->getParentItem($collectionSlug, $itemSlug);
$image = new Image();
$image->path = $filePath;
$image = $item->Images()->save($image);
$newImage = Image::find($image->id);
return Response::json($newImage->uuid, 201);
}
i'm having the same problem yesterday, here's the working trait
trait UuidTrait
{
public static function bootUuidTrait(){
static::creating(function($model){
$model->incrementing = false;
$model->{$model->getKeyName()} = Uuid::generate()->string;
});
}
}
so maybe here's the answer on your problem
static::creating(function ($model) {
// Don't let people provide their own UUIDs, we will generate a proper one.
$model->uuid = Uuid::generate(4)->string;
return true;
});
i hope i would help someone :D
You are hooking onto "creating" and "saving" events, but what you should be doing is hooking onto "creating" and "updating" events.
If you check official documentation it says that "saving" event is triggered on both creating a new model and updating an existing one - so in your case it gets called when creating new model and thus leaves "uuid" value on previous one (which is nothing); and also when updating it's the same thing.
If you switch to "creating" and "updating" events then everything will work as you want it to - basically just replace "saving" with "updating" and that's it.