laravel 5.6 Eloquent optimizando consultas

Para ver las querys que se ejecutan en una vista

vamos al archivo de rutas

routes/web.php

y escribimos el sgt codigo


DB::listen(function ($query){
echo "<pre>{$query->sql}</pre>";
});

por ejemplo si vamos a la vista de usuarios
vemos que se
ejecuta 1 request para a la tabla de Users para traer a los usuarios
y 1 request a la tabla user_role por cada usuario para traer los nombres de sus roles.

osea que para mostrar un listado de 100 usuarios estariamos haciendo 100 consultas a la base de datos!


esto lo modificamos en el controller de USer
app\Http\Controllers\UsersController.php


y en  public function index()
    {
        $users = User::all();
        return view('users.index',compact('users'));
    }

CAmbiamos User::all() por

 $users = User::with('roles')->get();

y listo.

Ahora la vista solo ejecutara una unica llamada a la base de datos para mostrar
la lista de usuarios




laravel 5.6 HasMany

vamos a crear las relaciones de usuario con mensajes

un usuario puede enviar varios mensajes

un mensaje es enviado por un usuario

vamos a agregar el campo user_id en la tabla messages

desde la consola

php artisan make:migration add_user_to_messages --table=messages

vamos al archivo generado y editamos el up y el down

public function up()
    {
        Schema::table('messages', function (Blueprint $table) {
            //
            $table->integer('user_id')->nullable();
        });
    } 

 public function down()
    {
        Schema::table('messages', function (Blueprint $table) {
            //
            $table->dropColumn('user_id');
        });
    }


y ejecutamos la migration asi:

php artisan migrate

Vamos a la clase User y creemos la relacion con messages

creamos 

public function messages(){
        return $this->hasMany(Message::class);
}

y en la clase Message

creamos la relacion

public function user()
{
return $this->belongsTo(User::class);
}


Ahora en la pagina de creacion de mensaje, vamos a mostrar el campo name e email del formulario
solo para los casos en que se haya entrado sin loguearse
(si se esta logueado se envian estos campos como hiddens con los valores correspondientes al usuario logueado)

en el controller

modificamos la funcion store:

public function store(ContactoRequest $request)
    {
     
        $message = Message::create($request->all());

        if(auth()->check()){
            auth()->user()->messages()->save($message);
        }
        return redirect()->route('mensajes.create');
    }

entonces en /views/messages/index.blade.php

podemos mostrar el nombre y email del user logueado que envio el mensaje
asi:

@if($message->user_id)
<td> {{$message->user->name}}</td>
<td>{{$message->user->email}}</td>
@



si los mensajes pueden ser enviados por usuarios logueados, la funcion store del controller podria simplificarse de este modo

auth()->user()->messages()->create($request->all());



instalar node js en ubuntu

sudo apt-get install nodejs

sudo apt-get install nodejs-legacy

Finalmente, podemos instalar el gestor de paquetes npm con el comando:
sudo apt-get install npm

google map api styling

se puede modificar el mapa que por default nos muestra google,

podemos definir un array con los estilos a aplicar, por ejemplo

var styles = [
          {
            featureType: 'road.highway',
            elementType: 'geometry.stroke',
            stylers: [
              { color: '#efe9e4' },
              { lightness: -40 }
            ]
          },{
            featureType: 'transit.station',
            stylers: [
              { weight: 9 },
              { hue: '#e85113' }
            ]
          }
        ];

y luego asignarselo al map

map = new google.maps.Map(document.getElementById('map'), {
  center: {lat: -34.619108, lng: -58.43131},
  zoom: 15,
  styles: styles,
 
  });

se pueden descargar distintos estilos para mapas desde esta pagina

google map api creando una marca mark

dentro de la function initMap, agregamos el sgt codigo

 <script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.619108, lng: -58.43131},
          zoom: 15
        });


        var tienda_de_cafe={lat:-34.619214,lng:-58.434158};
        var marker =new google.maps.Marker(
        {
        position: tienda_de_cafe,
        map:map,
        title: 'La Tienda de Cafe!'
        });
      }
    </script>

cuando pasemos el mouse por arriba del Mark (globo rojo) se mostrara el texto "La Tienda de Cafe!"



podemos ademas agregar information sobre ese punto y que aparezca cuando clickeamos sobre el.

var infoWinfow=new google.maps.InfoWindow(
        {content:'Vení a conocernos, disfrutá de la experiencia que tenemos para brindarte. Y llevate a tu casa el mejor café del mundo. '});

        marker.addListener('click',function(){
        infoWinfow.open(map,this);
        });


Se puede hacer lo mismo para varios puntos a la vez

var locations=[{title:'punto 1',location:{lat:-34.622628,lng:-58.43234}},{title:'punto 2',location:{lat:-34.615105,lng:-58.428648} },{title:'punto 3',location:{lat:-34.615928,lng:-58.430953}}
  ];
        
        var infoWinfowCommon=new google.maps.InfoWindow();
           
  for (var i = locations.length - 1; i >= 0; i--) {
  var marker =new google.maps.Marker(
  {
  position: locations[i].location,
  map:map,
  title: locations[i].title
  });
           
            populateInfoWindow(marker,infoWinfowCommon);
  }

donde:

function populateInfoWindow(marker,infoWindow){
  if(infoWindow.marker!=marker){
      marker.addListener('click',function(){
            infoWindow.marker = marker;
          infoWindow.setContent(marker.title);
      infoWindow.open(map,marker);
      infoWindow.addListener('closeclick',function(){
                     this.marker=null;
      });
        });
  }
 
  }




google map api configuracion proyecto

1) ir a https://console.developers.google.com

2) click en el combo de proyectos en la esquina superior izquierda

3) click en + para crear uno nuevo

4) escribir el nombre de tu proyecto y click en el boton "create"

click en el boton  de "Enable Apis"


(verificar que el combo superior este en tu nuevo proyecto)
5) click en Maps Javascript Api , click en el boton "enable"

*******************

desplegar el menu de la izquierda, ir a APIS

y habilitar:

roads api

maps static api

street view api

places api

geocoding api

directions api

distance matrix api

geolocation api

maps elevation api

timezone api

ir al menu Credentials de cualquiera de las Apis
click en Create Credentials y generar una Credential del tipo Api Key...esta se usara para todas las apis habilitadas en el proyecto

darle un nombre que describa la intencion con la que sera usada, por ejemplo:

maps_api_udacity_course


nuestra primera aplicacion,
por simplicidad lo haremos en una sola pagina web.

en la seccion de head, agregaremos el sgt codigo

<style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>

<script>
      var map;
      function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
          center: {lat: -34.619108, lng: -58.43131},
          zoom: 15
        });
      }
    </script>



<body>

<div id="map"></div>
   <script src="https://maps.googleapis.com/maps/api/js?key=TU_API_KEY&callback=initMap"
    async defer></script>

</body>


el rsultado sera un mapa con un zoom de 15 teniendo como centro las coordenadas dadas.

tip:
para obtener las coordenadas de una determinada direccion usar la siguiente
pagina

https://google-developers.appspot.com/maps/documentation/utils/geocoder






laravel 5.6 Politicas de acceso Policies

vamos a hacer uso de las clases policy de laravel para programar accesos
hacia algunas funcionalidades del sitio

entonces la idea final es que un usuario pueda editar/actualizar sus propios datos
y tambien que un usuario con rol admin pueda hacerlo para cualquiera.

1) crear la clase UserPolicy

php artisan make:policy UserPolicy

este comando creara la clase app/policies/UserPolicy.php

2) registrar la relacion del modelo User con la clase UserPolicy

ir a app/Providers/AuthServiceProvider.php

protected $policies = [
        'App\User' => 'App\Policies\UserPolicy',
    ];

3) en UserPolicy.php crear la function before, que se llamara antes de cualquier otra declarada en la clase. Aqui se evaluara si el usuario logueado es admin y si es verdadero devuelve true, salteando la evaluacion de las otras funciones. De lo contrario, llama a la function correspondiente para que haga la evaluacion de si el usuario logueado es el mismo que se quiere editar/actualizar.



 public function before($user,$ability){
        if($user->hasRoles(['admin'])){
            return true;
        }
    }

    public function edit(User $authUser, User $user){
        return ($authUser->id == $user->id);
    }
    public function update(User $authUser, User $user){
        return ($authUser->id == $user->id);
    }
    public function destroy(User $authUser, User $user){
        return ($authUser->id == $user->id);
    }


4)en UserController exceptuar la validacion para los casos de edit y update

public function __construct(){
       //$this->middleware(['auth','checkRoles:admin,moderador']);
        $this->middleware('auth');
        $this->middleware('checkRoles:admin,moderador',['except'=>['edit','update']]);
    }

5)en UserController llamar desde las functiones de edit y update
a la function authorize para que dispare las validaciones del UserPolicy

public function edit($id)
    {
        $user = User::findOrFail($id);

        $this->authorize($user);

        return view('users.edit',compact('user'));
    }

    public function update(UpdateUserRequest $request, $id)
    {
        $user = User::findOrFail($id);

        $this->authorize($user);
       

        $user->update($request->all())  ;
        return redirect()->route('users.index');

    }



linux ubuntu mint actualizar chrome

 desde una terminal: $ sudo apt update $ sudo apt install google-chrome-stable