lundi 25 mai 2020

GroupBy On OneToMany Relationship (Laravel 5.8)

I have the following chunk of code which returns data successfully:

ProductAttributeKey::withAndWhereHas('product_attribute_values', function($query) use ($organization_id, $country_id) {
    $query->whereHas('product', function ($query) use ($organization_id, $country_id) {
        $query->whereHas('organization_price_matrix', function ($query) use ($organization_id, $country_id) {
            $query->where('organization_id', $organization_id)
                ->where('product_cost_matrix.country_id', $country_id);
       });
   }); /* Tested Here: ->grouBy("name") */
})
->orderBy($order_by, $sort_by)
->paginate($per_page)

The data comes back in the following format when returned in a resource:

enter image description here

I want to group by the attribute "name" in the array "product_attribute_values".

I have tested groupBy name as you can see in the code block at the top. This seems works fine when the array for "product_attribute_values" contains more than one value, but if it contains one value it seems to remove it.

With groupBy("name"):

enter image description here

As you can see, it works fine for the first value "Alcohol Volume", but on the next value, "Batteries Included", it removes the only value in the array "product_attribute_values". I don't want it to remove that single value.

How would this be fixed?



via Chebli Mohamed

Change location Controllers\Auth

I make project in Laravel 7. I change location Http\Controllers\Auth to Http\Controllers**Admin**\Auth

In all files in Auth directory I change namespaces:

from:

namespace App\Http\Controllers\Auth;

to

namespace App\Http\Controllers\Admin\Auth;

Them I make composer dump-autoload.

Login work fine.

Now when I try logout with my code:

<a href=""
                       onclick="event.preventDefault(); document.getElementById('logout-form').submit();" class="btn btn-sm btn-light-primary font-weight-bolder py-2 px-5">Wyloguj</a>
                    <form id="logout-form" action="" method="POST" style="display: none;">
                        @csrf
                    </form>

I have error:

Illuminate\Contracts\Container\BindingResolutionException Target class [App\Http\Controllers\Front\Auth\LoginController] does not exist.

My RouteServiceProvider:

class RouteServiceProvider extends ServiceProvider
{
    /**
     * This namespace is applied to your controller routes.
     *
     * In addition, it is set as the URL generator's root namespace.
     *
     * @var string
     */
    protected $namespace = 'App\Http\Controllers';

    /**
     * The path to the "home" route for your application.
     *
     * @var string
     */
    public const HOME = '/';

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @return void
     */
    public function boot()
    {
        //

        parent::boot();
    }

    /**
     * Define the routes for the application.
     *
     * @return void
     */
    public function map()
    {
        $this->mapApiRoutes();

        if(config('app.admin_only'))
        {
            $this->mapAdminOnlyRoutes();
        }
        else
        {
            $this->mapWebRoutes();
            $this->mapAdminRoutes();
        }
    }

    /**
     * Define the "web" routes for the application.
     *
     * These routes all receive session state, CSRF protection, etc.
     *
     * @return void
     */
    protected function mapWebRoutes()
    {
        Route::middleware('web')
            ->namespace($this->namespace. '\Front')
            ->group(base_path('routes/web.php'));
    }

    /**
     * Define the "api" routes for the application.
     *
     * These routes are typically stateless.
     *
     * @return void
     */
    protected function mapApiRoutes()
    {
        Route::prefix('api')
            ->middleware('api')
            ->namespace($this->namespace)
            ->group(base_path('routes/api.php'));
    }

    protected function mapAdminRoutes()
    {
        Route::prefix(config('app.admin_prefix'))
            ->middleware('web')
            ->namespace($this->namespace.'\Admin')
            ->group(base_path('routes/admin.php'));
    }

    protected function mapAdminOnlyRoutes()
    {
        Route::middleware('web')
            ->namespace($this->namespace. '\Admin')
            ->group(base_path('routes/admin.php'));
    }
}

What is wrong? How can I repair it?



via Chebli Mohamed

Laravel hashids laravel v.5.4.36 PHP version 5.6.31

I probably annoy in this issue What should I use to install composer require vinkla/hashids ??? version? for my laravel and php version?



via Chebli Mohamed

dimanche 24 mai 2020

Laravel: How to print out strings in an array within escaped controller text

I am setting a text block to email out and setting the $body variable. The issue is that my $app->reference_image_url field is an array of strings so I get an array to string conversion error. I tried a foreach loop to have each url string added but that threw an error.

       $body = <<<COMMENT
* Main Image
$app->image_url
$app->image_notes

* Reference Images

$app->reference_image_url
$app->reference_image_notes
COMMENT;

$this->send($body);


via Chebli Mohamed

Laravel: Best way to create logs to a User table?

I have a Users table and I want to add a field to the table that has an array of logs and each log as a timestamp and action, so basically:

[ {created_at: 1590357784, action: "Logged In"}, {created_at: 1590357734, action: "Changed Password"} ]

I was thinking of adding a json field to the data ( $table->json('user_logs')->nullable();) but would this be sufficient to achieve this?



via Chebli Mohamed

Use DB::select + binding too select a row

I'm trying to get a row from the database but when using binding. I know that this doesn't work because the query automatically puts single quotes so it will be like this: select model, magazine, round('name', 2) etc. This doesn't work of course but how do I get rid of the single quotes?

$merkinformation = DB::select('select Model, Magazine, round(?, 2) as Rondetijd from rondetijden where Merk = ? order by ? limit 3;', [$track, $merk, $track]);



via Chebli Mohamed

How to create and update post in Vue and Laravel 5

I want to build a Vue frontend over API data. I can retrieve and delete contents. But i can neither Create nor update content in Vue. I know it's an issue with my Vue script because the API works fine without the frontend. My application is built using Laravel 5.8

The following are my API routes:

//Show a headline
Route::get('Headlines/{id}', 'NewsheadlinesController@show');

//List all headlines
Route::get('Headlines', 'NewsheadlinesController@index');

//Create a headline
Route::post('Headline', 'NewsheadlinesController@store');

//Update a headline
Route::put('Headline', 'NewsheadlinesController@store');

//Delete a headline
Route::delete('Headline/{id}', 'NewsheadlinesController@destroy');

My web.php route:

Route::get('/', function () {
    return view('layouts.headline');
});

Here's my Vue component register:

Vue.component('navbar', require('./components/Navbar.vue').default);
Vue.component('headlines', require('./components/Headlines.vue').default);

Navbar.vue component:

<template>
    <nav class="navbar navbar-expand-sm navbar-dark bg-info mb-2">
        <div class="container">
            <a href="#" class="navbar-brand">News Headlines</a>
        </div>
    </nav>
</template>

Headlines.vue component markup:

<template>
    <div>
        <h2>Headlines</h2>
        <div class="row">
            <div class="col-sm-12 col-md-4 col-lg-4">
                <h3>Create News Headlines</h3>
                <form @submit.prevent="addHeadline">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Enter Title" v-model="headline.title" required>
                    </div>
                    <div class="form-group">
                        <textarea class="form-control" placeholder="Enter summary" v-model="headline.description" required></textarea>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Unique identification or alias of the curator or correspondent" v-model="headline.identity" required>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Name of the curator or correspondent" v-model="headline.name" required>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Enter URL for this News Headline" v-model="headline.url" required>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Enter URL to photo image" v-model="headline.urlToImage" required>
                    </div>
                    <div class="form-group">
                        <textarea class="form-control" placeholder="Enter full content" v-model="headline.content" required></textarea>
                    </div>
                    <div class="form-group">
                        <select class="form-control" v-model="headline.category" required>
                            <option value="">Select news category</option>
                            <option value="health">Health</option>
                            <option value="science">Science</option>
                            <option value="general">General</option>
                            <option value="technology">Technology</option>
                            <option value="entertainment">Entertainment</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <select class="form-control" v-model="headline.language" required>
                            <option value="">Select your language</option>
                            <option value="nl">Netherlands</option>
                            <option value="ch">Chinese</option>
                            <option value="en">English</option>
                            <option value="fr">French</option>
                            <option value="es">Spanish</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <select class="form-control" v-model="headline.country" required>
                            <option value="">Select you country</option>
                            <option value="ru">Russia</option>
                            <option value="nl">Netherlands</option>
                            <option value="ch">China</option>
                            <option value="uk">United Kingdom</option>
                            <option value="fr">France</option>
                            <option value="us">USA</option>
                            <option value="sp">Spain</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Set publication time for this Headline" v-model="headline.publishedAt" required>
                        <small class="form-text text-muted">Year-Month-Day Hour:Minute:Second => 2001-03-07 04:05:20</small>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" disabled="" value="2001-03-07 04:05:20" v-model="headline.created_at" required>
                        <small class="form-text text-muted">Creation time for this Headline => Year-Month-Day Hour:Minute:Second</small>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" disabled="" value="2001-03-07 04:05:20" v-model="headline.updated_at" required>
                        <small class="form-text text-muted">Last editing time for this Headline => Year-Month-Day Hour:Minute:Second</small>
                    </div>
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="Enter photo caption" v-model="headline.diskImageFileName" required>
                        <small class="form-text text-muted">Maximum is 30 characters</small>
                    </div>
                    <button type="submit" class="btn btn-dark btn-block">Upload</button>
                </form>
            </div>
            <div class="col-sm-12 col-md-8 col-lg-8">
                <nav aria-label="News headline pagination">
                    <ul class="pagination">
                        <li v-bind:class="[{disabled: !pagination.prev_page_url}]" class="page-item">
                            <a class="page-link" href="#" @click="fetchHeadlines(pagination.prev_page_url)">
                                Previous
                            </a>
                        </li>
                        <li class="page-item disabled">
                            <a class="page-link text-dark" href="">
                                Page  of 
                            </a>
                        </li>
                        <li v-bind:class="[{disabled: !pagination.next_page_url}]" class="page-item">
                            <a class="page-link" href="#" @click="fetchHeadlines(pagination.next_page_url)">
                                Next
                            </a>
                        </li>
                    </ul>
                </nav>
                <div class="card card-body mb-2" v-for="headline in headlines" v-bind:key="headline.id">
                    <h3></h3>
                    <div class="row col-offset-md-2 col-md-10 mb-2">
                        <div class="col-sm-12 col-md-8 col-lg-8">
                            <p><b>Category:</b> . <br><b>Created by: </b> <br>
                            <i>Created on . <br>Published on </i><br>
                            <b>Country ISO code:</b> . <b>Language: </b> <br></p>
                            <p>Post ID: </p>
                        </div>
                        <div class="col-sm-12 col-md-4 col-lg-4">
                            <img style="height: 150px; width: 200%; display: block;" src="" alt="">
                        </div>
                    </div>
                    <p><b>Summary:</b>  </p>
                    <p><b>Content:</b>    </p>

                    <button @click="editHeadline(headline)" class="btn btn-warning mb-2">Edit news</button>

                    <button @click="deleteHeadline(headline.id)" class="btn btn-danger">Delete news</button>
                </div>
            </div>
        </div>
    </div>
</template>

Headlines.vue component script:

<script>
    export default {
        data() {
            return {
                headlines: [],
                headline: {
                    id: '',
                    identity: '',
                    name: '',
                    title: '',
                    description: '',
                    url: '',
                    urlToImage: '',
                    publishedAt: '',
                    content: '',
                    category: '',
                    language: '',
                    country: '',
                    diskImageFileName: '',
                    created_at: '',
                    updated_at: ''
                },
                headline_id: '',
                pagination: {},
                edit: false
            };
        },

        created() {
            this.fetchHeadlines();
        },

        methods: {
            fetchHeadlines(page_url){
                let vm = this;
                page_url = page_url || 'api/Headlines';
                fetch(page_url)
                    .then(res => res.json())
                    .then(res => {
                        this.headlines = res.data;
                        vm.makePagination(res.meta, res.links);
                    })
                    .catch(err => console.log(err));
            },/* end fetchHeadlines */

            makePagination(meta, links) {
                let pagination = {
                    current_page: meta.current_page,
                    last_page: meta.last_page,

                    first_page_url: links.first,
                    last_page_url: links.last,

                    next_page_url: links.next,
                    prev_page_url: links.prev
                };

                this.pagination = pagination;
            },/* end makePagination */

            deleteHeadline(id) {
                if(confirm('Deleting a news headline is irreversible. Are you sure you want to delete it?')) {
                    fetch(`api/Headline/${id}`, {
                        method: 'delete'
                    })
                        .then(res => res.json())
                        .then(data => {
                            alert('The news headline has been removed');
                            this.fetchHeadlines();
                        })
                        .catch(err => console.log(err));
                }
            },/* end deleteHeadline */

            addHeadline() {
                if (this.edit === false) {
                    //Add this new news headline
                    fetch('api/Headline', {
                        method: 'post',/*
                        description: JSON.stringify(this.headline),
                        content: JSON.stringify(this.headline),*/
                        headers: {
                            'content-type': 'application/json'
                        }
                    })
                    .then(res => res.json)
                    .then(data => {
                        this.headline.title = '';
                        this.headline.identity= '';
                        this.headline.name= '';
                        this.headline.title= '';
                        this.headline.description= '';
                        this.headline.url= '';
                        this.headline.urlToImage= '';
                        this.headline.publishedAt= '';
                        this.headline.content= '';
                        this.headline.category= '';
                        this.headline.language= '';
                        this.headline.country= '';
                        this.headline.diskImageFileName= '';
                        this.headline.created_at= '';
                        this.headline.updated_at= '';
                        alert('Your News Headline has been added. Thanks for the contribution.');
                        this.fetchHeadlines();
                    })
                }
                else {
                    //Just update
                    fetch('api/Headline', {
                        method: 'put',
                        description: JSON.stringify(this.headline),
                        content: JSON.stringify(this.headline),
                        headers: {
                            'content-type': 'application/json'
                        }
                    })
                    .then(res => res.json)
                    .then(data => {
                        this.headline.title = '';
                        this.headline.identity= '';
                        this.headline.name= '';
                        this.headline.title= '';
                        this.headline.description= '';
                        this.headline.url= '';
                        this.headline.urlToImage= '';
                        this.headline.publishedAt= '';
                        this.headline.content= '';
                        this.headline.category= '';
                        this.headline.language= '';
                        this.headline.country= '';
                        this.headline.diskImageFileName= '';
                        this.headline.created_at= '';
                        this.headline.updated_at= '';
                        alert('Your News Headline has been updated. Thanks for the contribution.');
                        this.fetchHeadlines();
                    })
                }
            },/* end addHeadline */

            editHeadline(headline) {
                this.edit = true;
                this.headline.id = headline.id;
                this.headline.headline_id = headline.id;
                this.headline.identity = headline.identity;
                this.headline.name = headline.name;
                this.headline.title = headline.title;
                this.headline.description = headline.description;
                this.headline.url = headline.url;
                this.headline.urlToImage = headline.urlToImage;
                this.headline.publishedAt = headline.publishedAt;
                this.headline.content = headline.content;
                this.headline.category = headline.category;
                this.headline.language = headline.language;
                this.headline.country = headline.country;
                this.headline.diskImageFileName = headline.diskImageFileName;
                this.headline.created_at = headline.created_at;
                this.headline.updated_at = headline.updated_at;
            }
        }
    };
</script>

Frontend page, 'layouts.headline':

<!doctype html>
<html lang="">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!-- Protect against cross site forgery -->
        <meta name="csrf-token" content="">
        <script>
            window.Laravel = { csrfToken: '' }
        </script>

        <link href="" rel="stylesheet">

        <!-- Title of this page -->
        <title>News Headlines with Vue</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet">
    </head>
    <body>
        <div id="app">
            <navbar></navbar>
            <div class="container">
                <headlines></headlines>
            </div>
        </div>

        <link href="">
        <link href="">
        <link href="">
        <script src=""></script>
    </body>
</html>

Pardon me, for the lengthy code. 'Just want to give full info.



via Chebli Mohamed